Skip to content

Commit ccc12b8

Browse files
committed
Avoid unnecessary reference-counting on strings.
1 parent ce18738 commit ccc12b8

29 files changed

+636
-510
lines changed

Zend/zend.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,15 @@ ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */
322322

323323
ZEND_API size_t zend_print_zval(zval *expr, int indent) /* {{{ */
324324
{
325-
zend_string *str = zval_get_string(expr);
325+
zend_string *tmp_str;
326+
zend_string *str = zval_get_tmp_string(expr, &tmp_str);
326327
size_t len = ZSTR_LEN(str);
327328

328329
if (len != 0) {
329330
zend_write(ZSTR_VAL(str), len);
330331
}
331332

332-
zend_string_release(str);
333+
zend_tmp_string_release(tmp_str);
333334
return len;
334335
}
335336
/* }}} */
@@ -436,9 +437,12 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
436437
case IS_REFERENCE:
437438
zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent);
438439
break;
440+
case IS_STRING:
441+
smart_str_append(buf, Z_STR_P(expr));
442+
break;
439443
default:
440444
{
441-
zend_string *str = zval_get_string(expr);
445+
zend_string *str = zval_get_string_func(expr);
442446
smart_str_append(buf, str);
443447
zend_string_release(str);
444448
}

Zend/zend_closures.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,16 @@ ZEND_METHOD(Closure, bind)
198198
} else if (Z_TYPE_P(scope_arg) == IS_NULL) {
199199
ce = NULL;
200200
} else {
201-
zend_string *class_name = zval_get_string(scope_arg);
201+
zend_string *tmp_class_name;
202+
zend_string *class_name = zval_get_tmp_string(scope_arg, &tmp_class_name);
202203
if (zend_string_equals_literal(class_name, "static")) {
203204
ce = closure->func.common.scope;
204205
} else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
205206
zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name));
206207
zend_string_release(class_name);
207208
RETURN_NULL();
208209
}
209-
zend_string_release(class_name);
210+
zend_tmp_string_release(tmp_class_name);
210211
}
211212
} else { /* scope argument not given; do not change the scope by default */
212213
ce = closure->func.common.scope;

Zend/zend_execute.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
12421242

12431243
if (Z_TYPE_P(value) != IS_STRING) {
12441244
/* Convert to string, just the time to pick the 1st byte */
1245-
zend_string *tmp = zval_get_string(value);
1245+
zend_string *tmp = zval_get_string_func(value);
12461246

12471247
string_len = ZSTR_LEN(tmp);
12481248
c = (zend_uchar)ZSTR_VAL(tmp)[0];
@@ -1934,19 +1934,19 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
19341934
static zend_always_inline zval* zend_fetch_static_property_address(zval *varname, zend_uchar varname_type, znode_op op2, zend_uchar op2_type, int type EXECUTE_DATA_DC OPLINE_DC)
19351935
{
19361936
zval *retval;
1937-
zend_string *name;
1937+
zend_string *name, *tmp_name;
19381938
zend_class_entry *ce;
19391939

19401940
if (varname_type == IS_CONST) {
19411941
name = Z_STR_P(varname);
19421942
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
19431943
name = Z_STR_P(varname);
1944-
zend_string_addref(name);
1944+
tmp_name = NULL;
19451945
} else {
19461946
if (varname_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
19471947
zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
19481948
}
1949-
name = zval_get_string(varname);
1949+
name = zval_get_tmp_string(varname, &tmp_name);
19501950
}
19511951

19521952
if (op2_type == IS_CONST) {
@@ -1969,7 +1969,7 @@ static zend_always_inline zval* zend_fetch_static_property_address(zval *varname
19691969
ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
19701970
if (UNEXPECTED(ce == NULL)) {
19711971
if (varname_type != IS_CONST) {
1972-
zend_string_release(name);
1972+
zend_tmp_string_release(tmp_name);
19731973
}
19741974
return NULL;
19751975
}
@@ -1981,7 +1981,7 @@ static zend_always_inline zval* zend_fetch_static_property_address(zval *varname
19811981
ce = zend_fetch_class(NULL, op2.num);
19821982
if (UNEXPECTED(ce == NULL)) {
19831983
if (varname_type != IS_CONST) {
1984-
zend_string_release(name);
1984+
zend_tmp_string_release(tmp_name);
19851985
}
19861986
return NULL;
19871987
}
@@ -2007,7 +2007,7 @@ static zend_always_inline zval* zend_fetch_static_property_address(zval *varname
20072007
retval = zend_std_get_static_property(ce, name, type == BP_VAR_IS);
20082008

20092009
if (varname_type != IS_CONST) {
2010-
zend_string_release(name);
2010+
zend_tmp_string_release(tmp_name);
20112011
}
20122012

20132013
if (UNEXPECTED(retval == NULL)) {

Zend/zend_inheritance.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,10 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function
520520
smart_str_appends(&str, "<expression>");
521521
}
522522
} else {
523-
zend_string *zv_str = zval_get_string(zv);
523+
zend_string *tmp_zv_str;
524+
zend_string *zv_str = zval_get_tmp_string(zv, &tmp_zv_str);
524525
smart_str_append(&str, zv_str);
525-
zend_string_release(zv_str);
526+
zend_tmp_string_release(tmp_zv_str);
526527
}
527528
}
528529
} else {

Zend/zend_ini_parser.y

+4-3
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,14 @@ static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
111111
int length, op1_len;
112112

113113
if (Z_TYPE_P(op1) != IS_STRING) {
114-
zend_string *str = zval_get_string(op1);
115114
/* ZEND_ASSERT(!Z_REFCOUNTED_P(op1)); */
116115
if (ZEND_SYSTEM_INI) {
116+
zend_string *tmp_str;
117+
zend_string *str = zval_get_tmp_string(op1, &tmp_str);
117118
ZVAL_PSTRINGL(op1, ZSTR_VAL(str), ZSTR_LEN(str));
118-
zend_string_release(str);
119+
zend_tmp_string_release(tmp_str);
119120
} else {
120-
ZVAL_STR(op1, str);
121+
ZVAL_STR(op1, zval_get_string_func(op1));
121122
}
122123
}
123124
op1_len = (int)Z_STRLEN_P(op1);

Zend/zend_object_handlers.c

+4-12
Original file line numberDiff line numberDiff line change
@@ -886,16 +886,12 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /
886886
static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
887887
{
888888
zend_object *zobj;
889-
zend_string *name;
889+
zend_string *name, *tmp_name;
890890
zval *retval = NULL;
891891
uintptr_t property_offset;
892892

893893
zobj = Z_OBJ_P(object);
894-
if (EXPECTED(Z_TYPE_P(member) == IS_STRING)) {
895-
name = Z_STR_P(member);
896-
} else {
897-
name = zval_get_string(member);
898-
}
894+
name = zval_get_tmp_string(member, &tmp_name);
899895

900896
#if DEBUG_OBJECT_HANDLERS
901897
fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
@@ -928,9 +924,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
928924
zobj->properties = zend_array_dup(zobj->properties);
929925
}
930926
if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) {
931-
if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
932-
zend_string_release(name);
933-
}
927+
zend_tmp_string_release(tmp_name);
934928
return retval;
935929
}
936930
}
@@ -948,9 +942,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
948942
}
949943
}
950944

951-
if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
952-
zend_string_release(name);
953-
}
945+
zend_tmp_string_release(tmp_name);
954946
return retval;
955947
}
956948
/* }}} */

Zend/zend_operators.c

+20-16
Original file line numberDiff line numberDiff line change
@@ -1809,8 +1809,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
18091809

18101810
ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
18111811
{
1812-
zend_string *str1 = zval_get_string(op1);
1813-
zend_string *str2 = zval_get_string(op2);
1812+
zend_string *tmp_str1, *tmp_str2;
1813+
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
1814+
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
18141815
int ret;
18151816

18161817
if (case_insensitive) {
@@ -1819,8 +1820,8 @@ ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, zend
18191820
ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
18201821
}
18211822

1822-
zend_string_release(str1);
1823-
zend_string_release(str2);
1823+
zend_tmp_string_release(tmp_str1);
1824+
zend_tmp_string_release(tmp_str2);
18241825
return ret;
18251826
}
18261827
/* }}} */
@@ -1835,12 +1836,13 @@ ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2) /* {{{
18351836
return zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
18361837
}
18371838
} else {
1838-
zend_string *str1 = zval_get_string(op1);
1839-
zend_string *str2 = zval_get_string(op2);
1839+
zend_string *tmp_str1, *tmp_str2;
1840+
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
1841+
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
18401842
int ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
18411843

1842-
zend_string_release(str1);
1843-
zend_string_release(str2);
1844+
zend_tmp_string_release(tmp_str1);
1845+
zend_tmp_string_release(tmp_str2);
18441846
return ret;
18451847
}
18461848
}
@@ -1856,12 +1858,13 @@ ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /*
18561858
return zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
18571859
}
18581860
} else {
1859-
zend_string *str1 = zval_get_string(op1);
1860-
zend_string *str2 = zval_get_string(op2);
1861+
zend_string *tmp_str1, *tmp_str2;
1862+
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
1863+
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
18611864
int ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
18621865

1863-
zend_string_release(str1);
1864-
zend_string_release(str2);
1866+
zend_tmp_string_release(tmp_str1);
1867+
zend_tmp_string_release(tmp_str2);
18651868
return ret;
18661869
}
18671870
}
@@ -1870,12 +1873,13 @@ ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /*
18701873
#if HAVE_STRCOLL
18711874
ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2) /* {{{ */
18721875
{
1873-
zend_string *str1 = zval_get_string(op1);
1874-
zend_string *str2 = zval_get_string(op2);
1876+
zend_string *tmp_str1, *tmp_str2;
1877+
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
1878+
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
18751879
int ret = strcoll(ZSTR_VAL(str1), ZSTR_VAL(str2));
18761880

1877-
zend_string_release(str1);
1878-
zend_string_release(str2);
1881+
zend_tmp_string_release(tmp_str1);
1882+
zend_tmp_string_release(tmp_str2);
18791883
return ret;
18801884
}
18811885
/* }}} */

Zend/zend_operators.h

+14
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,20 @@ static zend_always_inline zend_string *zval_get_string(zval *op) {
273273
return EXPECTED(Z_TYPE_P(op) == IS_STRING) ? zend_string_copy(Z_STR_P(op)) : zval_get_string_func(op);
274274
}
275275

276+
static zend_always_inline zend_string *zval_get_tmp_string(zval *op, zend_string **tmp) {
277+
if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
278+
*tmp = NULL;
279+
return Z_STR_P(op);
280+
} else {
281+
return *tmp = zval_get_string_func(op);
282+
}
283+
}
284+
static zend_always_inline void zend_tmp_string_release(zend_string *tmp) {
285+
if (UNEXPECTED(tmp)) {
286+
zend_string_release(tmp);
287+
}
288+
}
289+
276290
/* Compatibility macros for 7.2 and below */
277291
#define _zval_get_long(op) zval_get_long(op)
278292
#define _zval_get_double(op) zval_get_double(op)

0 commit comments

Comments
 (0)