Skip to content

Commit 4182b08

Browse files
committed
Avoid copying
1 parent bf5a813 commit 4182b08

File tree

1 file changed

+43
-53
lines changed

1 file changed

+43
-53
lines changed

Zend/zend_object_handlers.c

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ *
175175
}
176176
/* }}} */
177177

178-
static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{{ */
178+
static void zend_std_call_getter(zend_object *zobj, zval *member, zval *retval) /* {{{ */
179179
{
180-
zend_class_entry *ce = Z_OBJCE_P(object);
180+
zend_class_entry *ce = zobj->ce;
181181
zend_class_entry *orig_fake_scope = EG(fake_scope);
182182
zend_fcall_info fci;
183183
zend_fcall_info_cache fcic;
@@ -191,7 +191,7 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
191191
*/
192192

193193
fci.size = sizeof(fci);
194-
fci.object = Z_OBJ_P(object);
194+
fci.object = zobj;
195195
fci.retval = retval;
196196
fci.param_count = 1;
197197
fci.params = member;
@@ -200,17 +200,17 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
200200

201201
fcic.function_handler = ce->__get;
202202
fcic.called_scope = ce;
203-
fcic.object = Z_OBJ_P(object);
203+
fcic.object = zobj;
204204

205205
zend_call_function(&fci, &fcic);
206206

207207
EG(fake_scope) = orig_fake_scope;
208208
}
209209
/* }}} */
210210

211-
static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{ */
211+
static void zend_std_call_setter(zend_object *zobj, zval *member, zval *value) /* {{{ */
212212
{
213-
zend_class_entry *ce = Z_OBJCE_P(object);
213+
zend_class_entry *ce = zobj->ce;
214214
zend_class_entry *orig_fake_scope = EG(fake_scope);
215215
zend_fcall_info fci;
216216
zend_fcall_info_cache fcic;
@@ -228,7 +228,7 @@ static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
228228
ZVAL_UNDEF(&ret);
229229

230230
fci.size = sizeof(fci);
231-
fci.object = Z_OBJ_P(object);
231+
fci.object = zobj;
232232
fci.retval = &ret;
233233
fci.param_count = 2;
234234
fci.params = args;
@@ -237,7 +237,7 @@ static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
237237

238238
fcic.function_handler = ce->__set;
239239
fcic.called_scope = ce;
240-
fcic.object = Z_OBJ_P(object);
240+
fcic.object = zobj;
241241

242242
zend_call_function(&fci, &fcic);
243243
zval_ptr_dtor(&ret);
@@ -246,9 +246,9 @@ static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
246246
}
247247
/* }}} */
248248

249-
static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
249+
static void zend_std_call_unsetter(zend_object *zobj, zval *member) /* {{{ */
250250
{
251-
zend_class_entry *ce = Z_OBJCE_P(object);
251+
zend_class_entry *ce = zobj->ce;
252252
zend_class_entry *orig_fake_scope = EG(fake_scope);
253253
zend_fcall_info fci;
254254
zend_fcall_info_cache fcic;
@@ -263,7 +263,7 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
263263
ZVAL_UNDEF(&ret);
264264

265265
fci.size = sizeof(fci);
266-
fci.object = Z_OBJ_P(object);
266+
fci.object = zobj;
267267
fci.retval = &ret;
268268
fci.param_count = 1;
269269
fci.params = member;
@@ -272,7 +272,7 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
272272

273273
fcic.function_handler = ce->__unset;
274274
fcic.called_scope = ce;
275-
fcic.object = Z_OBJ_P(object);
275+
fcic.object = zobj;
276276

277277
zend_call_function(&fci, &fcic);
278278
zval_ptr_dtor(&ret);
@@ -281,9 +281,9 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
281281
}
282282
/* }}} */
283283

284-
static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /* {{{ */
284+
static void zend_std_call_issetter(zend_object *zobj, zval *member, zval *retval) /* {{{ */
285285
{
286-
zend_class_entry *ce = Z_OBJCE_P(object);
286+
zend_class_entry *ce = zobj->ce;
287287
zend_class_entry *orig_fake_scope = EG(fake_scope);
288288
zend_fcall_info fci;
289289
zend_fcall_info_cache fcic;
@@ -297,7 +297,7 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
297297
*/
298298

299299
fci.size = sizeof(fci);
300-
fci.object = Z_OBJ_P(object);
300+
fci.object = zobj;
301301
fci.retval = retval;
302302
fci.param_count = 1;
303303
fci.params = member;
@@ -306,7 +306,7 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
306306

307307
fcic.function_handler = ce->__isset;
308308
fcic.called_scope = ce;
309-
fcic.object = Z_OBJ_P(object);
309+
fcic.object = zobj;
310310

311311
zend_call_function(&fci, &fcic);
312312

@@ -607,7 +607,7 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe
607607
ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
608608
{
609609
zend_object *zobj;
610-
zval tmp_member, tmp_object;
610+
zval tmp_member;
611611
zval *retval;
612612
uintptr_t property_offset;
613613
uint32_t *guard = NULL;
@@ -666,8 +666,6 @@ ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void
666666
goto exit;
667667
}
668668

669-
ZVAL_UNDEF(&tmp_object);
670-
671669
/* magic isset */
672670
if ((type == BP_VAR_IS) && zobj->ce->__isset) {
673671
zval tmp_result;
@@ -678,36 +676,38 @@ ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void
678676
ZVAL_COPY(&tmp_member, member);
679677
member = &tmp_member;
680678
}
681-
ZVAL_COPY(&tmp_object, object);
679+
GC_ADDREF(zobj);
682680
ZVAL_UNDEF(&tmp_result);
683681

684682
*guard |= IN_ISSET;
685-
zend_std_call_issetter(&tmp_object, member, &tmp_result);
683+
zend_std_call_issetter(zobj, member, &tmp_result);
686684
*guard &= ~IN_ISSET;
687685

688686
if (!zend_is_true(&tmp_result)) {
689687
retval = &EG(uninitialized_zval);
690-
zval_ptr_dtor(&tmp_object);
688+
OBJ_RELEASE(zobj);
691689
zval_ptr_dtor(&tmp_result);
692690
goto exit;
693691
}
694692

695693
zval_ptr_dtor(&tmp_result);
694+
if (zobj->ce->__get && !((*guard) & IN_GET)) {
695+
goto call_getter;
696+
}
697+
OBJ_RELEASE(zobj);
698+
} else if (zobj->ce->__get && !((*guard) & IN_GET)) {
699+
goto call_getter_addref;
696700
}
697-
}
698-
699-
/* magic get */
700-
if (zobj->ce->__get) {
701-
if (guard == NULL) {
702-
guard = zend_get_property_guard(zobj, Z_STR_P(member));
703-
}
701+
} else if (zobj->ce->__get) {
702+
/* magic get */
703+
guard = zend_get_property_guard(zobj, Z_STR_P(member));
704704
if (!((*guard) & IN_GET)) {
705705
/* have getter - try with it! */
706-
if (Z_TYPE(tmp_object) == IS_UNDEF) {
707-
ZVAL_COPY(&tmp_object, object);
708-
}
706+
call_getter_addref:
707+
GC_ADDREF(zobj);
708+
call_getter:
709709
*guard |= IN_GET; /* prevent circular getting */
710-
zend_std_call_getter(&tmp_object, member, rv);
710+
zend_std_call_getter(zobj, member, rv);
711711
*guard &= ~IN_GET;
712712

713713
if (Z_TYPE_P(rv) != IS_UNDEF) {
@@ -721,18 +721,15 @@ ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void
721721
} else {
722722
retval = &EG(uninitialized_zval);
723723
}
724-
zval_ptr_dtor(&tmp_object);
724+
OBJ_RELEASE(zobj);
725725
goto exit;
726726
} else if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
727-
zval_ptr_dtor(&tmp_object);
728727
zend_throw_error(NULL, "Cannot access property started with '\\0'");
729728
retval = &EG(uninitialized_zval);
730729
goto exit;
731730
}
732731
}
733732

734-
zval_ptr_dtor(&tmp_object);
735-
736733
if ((type != BP_VAR_IS)) {
737734
zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
738735
}
@@ -793,13 +790,11 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
793790
uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
794791

795792
if (!((*guard) & IN_SET)) {
796-
zval tmp_object;
797-
798-
ZVAL_COPY(&tmp_object, object);
793+
GC_ADDREF(zobj);
799794
(*guard) |= IN_SET; /* prevent circular setting */
800-
zend_std_call_setter(&tmp_object, member, value);
795+
zend_std_call_setter(zobj, member, value);
801796
(*guard) &= ~IN_SET;
802-
zval_ptr_dtor(&tmp_object);
797+
OBJ_RELEASE(zobj);
803798
} else if (EXPECTED(!IS_WRONG_PROPERTY_OFFSET(property_offset))) {
804799
goto write_std_property;
805800
} else {
@@ -1052,14 +1047,10 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s
10521047
if (zobj->ce->__unset) {
10531048
uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
10541049
if (!((*guard) & IN_UNSET)) {
1055-
zval tmp_object;
1056-
10571050
/* have unseter - try with it! */
1058-
ZVAL_COPY(&tmp_object, object);
10591051
(*guard) |= IN_UNSET; /* prevent circular unsetting */
1060-
zend_std_call_unsetter(&tmp_object, member);
1052+
zend_std_call_unsetter(zobj, member);
10611053
(*guard) &= ~IN_UNSET;
1062-
zval_ptr_dtor(&tmp_object);
10631054
} else {
10641055
if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
10651056
zend_throw_error(NULL, "Cannot access property started with '\\0'");
@@ -1276,7 +1267,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
12761267
/* Ensure that we haven't overridden a private function and end up calling
12771268
* the overriding public function...
12781269
*/
1279-
1270+
12801271
scope = zend_get_executed_scope();
12811272
if (fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
12821273
if (scope && is_derived_class(fbc->common.scope, scope)) {
@@ -1693,23 +1684,22 @@ ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exist
16931684

16941685
if (!((*guard) & IN_ISSET)) {
16951686
zval rv;
1696-
zval tmp_object;
16971687

16981688
/* have issetter - try with it! */
16991689
if (Z_TYPE(tmp_member) == IS_UNDEF) {
17001690
ZVAL_COPY(&tmp_member, member);
17011691
member = &tmp_member;
17021692
}
1703-
ZVAL_COPY(&tmp_object, object);
1693+
GC_ADDREF(zobj);
17041694
(*guard) |= IN_ISSET; /* prevent circular getting */
1705-
zend_std_call_issetter(&tmp_object, member, &rv);
1695+
zend_std_call_issetter(zobj, member, &rv);
17061696
if (Z_TYPE(rv) != IS_UNDEF) {
17071697
result = zend_is_true(&rv);
17081698
zval_ptr_dtor(&rv);
17091699
if (has_set_exists && result) {
17101700
if (EXPECTED(!EG(exception)) && zobj->ce->__get && !((*guard) & IN_GET)) {
17111701
(*guard) |= IN_GET;
1712-
zend_std_call_getter(&tmp_object, member, &rv);
1702+
zend_std_call_getter(zobj, member, &rv);
17131703
(*guard) &= ~IN_GET;
17141704
if (Z_TYPE(rv) != IS_UNDEF) {
17151705
result = i_zend_is_true(&rv);
@@ -1723,7 +1713,7 @@ ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exist
17231713
}
17241714
}
17251715
(*guard) &= ~IN_ISSET;
1726-
zval_ptr_dtor(&tmp_object);
1716+
OBJ_RELEASE(zobj);
17271717
}
17281718
}
17291719

0 commit comments

Comments
 (0)