]> granicus.if.org Git - php/commitdiff
Optimized property access handlers. Removed EG(std_property_info).
authorDmitry Stogov <dmitry@zend.com>
Fri, 17 Oct 2014 15:10:05 +0000 (19:10 +0400)
committerDmitry Stogov <dmitry@zend.com>
Fri, 17 Oct 2014 15:10:05 +0000 (19:10 +0400)
Zend/zend_API.c
Zend/zend_globals.h
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h
ext/reflection/php_reflection.c
ext/soap/php_encoding.c

index 41214865f4756798262ee00ea028455f0eb90d50..fe17968f064171cf80e648d0eaffba375e439983 100644 (file)
@@ -1248,9 +1248,9 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti
 
        ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
                        property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC);
-                       if (property_info &&
-                           (property_info->flags & ZEND_ACC_STATIC) == 0 &&
-                           property_info->offset >= 0) {
+                       if (property_info != ZEND_WRONG_PROPERTY_INFO &&
+                           property_info &&
+                           (property_info->flags & ZEND_ACC_STATIC) == 0) {
                                ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
                                ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]);
                        }
@@ -1267,9 +1267,9 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties
 
        ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
                property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC);
-               if (property_info &&
-                   (property_info->flags & ZEND_ACC_STATIC) == 0 &&
-                   property_info->offset >= 0) {
+               if (property_info != ZEND_WRONG_PROPERTY_INFO &&
+                   property_info &&
+                   (property_info->flags & ZEND_ACC_STATIC) == 0) {
                    zval_ptr_dtor(&object->properties_table[property_info->offset]);
                        ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
                        zval_add_ref(&object->properties_table[property_info->offset]);
index 43abffd1cedb233f2b00321695e852491fa1b94d..89abb445e9350735483943ace2142f9d17e35078 100644 (file)
@@ -222,8 +222,6 @@ struct _zend_executor_globals {
 
        struct _zend_module_entry *current_module;
 
-       zend_property_info std_property_info;
-
        zend_bool active;
        zend_bool valid_symbol_table;
 
index ba089674c1b02ae11b9974f69c0f8573643d8343..e9897ed34eddce4c62c27e53385fd167cb0c90f4 100644 (file)
@@ -293,22 +293,14 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla
 }
 /* }}} */
 
-static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */
 {
        zend_property_info *property_info;
        zend_property_info *scope_property_info;
        zend_bool denied_access = 0;
 
        if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) {
-               property_info = CACHED_PTR_EX(cache_slot + 1);
-               if (UNEXPECTED(!property_info)) {
-                       EG(std_property_info).flags = ZEND_ACC_PUBLIC;
-                       EG(std_property_info).name = member;
-                       EG(std_property_info).ce = ce;
-                       EG(std_property_info).offset = -1;
-                       property_info = &EG(std_property_info);
-               }
-               return property_info;
+               return CACHED_PTR_EX(cache_slot + 1);
        }
 
        if (UNEXPECTED(member->val[0] == '\0')) {
@@ -319,10 +311,10 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
                                zend_error_noreturn(E_ERROR, "Cannot access property started with '\\0'");
                        }
                }
-               return NULL;
+               return ZEND_WRONG_PROPERTY_INFO;
        }
-       property_info = NULL;
-       if ((property_info = zend_hash_find_ptr(&ce->properties_info, member)) != NULL) {
+       property_info = zend_hash_find_ptr(&ce->properties_info, member);
+       if (property_info != NULL) {
                if (UNEXPECTED((property_info->flags & ZEND_ACC_SHADOW) != 0)) {
                        /* if it's a shadow - go to access it's private */
                        property_info = NULL;
@@ -364,7 +356,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
                        if (!silent) {
                                zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name->val, member->val);
                        }
-                       return NULL;
+                       return ZEND_WRONG_PROPERTY_INFO;
                } else {
                        /* fall through, return property_info... */
                        if (cache_slot) {
@@ -375,17 +367,12 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
                if (cache_slot) {
                        CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, NULL);
                }
-               EG(std_property_info).flags = ZEND_ACC_PUBLIC;
-               EG(std_property_info).name = member;
-               EG(std_property_info).ce = ce;
-               EG(std_property_info).offset = -1;
-               property_info = &EG(std_property_info);
        }
        return property_info;
 }
 /* }}} */
 
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */
+ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */
 {
        return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC);
 }
@@ -407,7 +394,14 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
        }
        property_info = zend_get_property_info_quick(zobj->ce, member, 1, NULL TSRMLS_CC);
        zend_string_release(member);
-       if (!property_info) {
+       if (property_info == NULL) {
+               /* undefined public property */
+               if (class_name && class_name[0] != '*') {
+                       /* we we're looking for a private prop */
+                       return FAILURE;
+               }
+               return SUCCESS;
+       } else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
                return FAILURE;
        }
        if (class_name && class_name[0] != '*') {
@@ -423,19 +417,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
 }
 /* }}} */
 
-static zend_long *zend_get_property_guard(zend_object *zobj, zval *member) /* {{{ */
+static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
 {
        zval stub, *guard;
 
        if (!zobj->guards) {
                ALLOC_HASHTABLE(zobj->guards);
                zend_hash_init(zobj->guards, 8, NULL, NULL, 0);
-       } else if ((guard = zend_hash_find(zobj->guards, Z_STR_P(member))) != NULL) {
+       } else if ((guard = zend_hash_find(zobj->guards, member)) != NULL) {
                return &Z_LVAL_P(guard);
        }
 
        ZVAL_LONG(&stub, 0);
-       guard = zend_hash_add_new(zobj->guards, Z_STR_P(member), &stub);
+       guard = zend_hash_add_new(zobj->guards, member, &stub);
        return &Z_LVAL_P(guard);
 }
 /* }}} */
@@ -463,22 +457,23 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
        /* make zend_get_property_info silent if we have getter - we may want to use it */
        property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL)) {
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
+       if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+
                        retval = &zobj->properties_table[property_info->offset];
                        if (Z_TYPE_P(retval) != IS_UNDEF) {
                                goto exit;
                        }
                } else if (UNEXPECTED(zobj->properties != NULL)) {
-                       retval = zend_hash_find(zobj->properties, property_info->name);
+                       retval = zend_hash_find(zobj->properties, Z_STR_P(member));
                        if (retval) goto exit;
                }
        }
 
        /* magic get */
        if (zobj->ce->__get) {
-               zend_long *guard = zend_get_property_guard(zobj, member);
+               zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
                if (!((*guard) & IN_GET)) {
                        zval tmp_object;
 
@@ -501,6 +496,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                                retval = &EG(uninitialized_zval);
                        }
                        zval_ptr_dtor(&tmp_object);
+                       goto exit;
                } else {
                        if (Z_STRVAL_P(member)[0] == '\0') {
                                if (Z_STRLEN_P(member) == 0) {
@@ -509,17 +505,12 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                                        zend_error(E_ERROR, "Cannot access property started with '\\0'");
                                }
                        }
-                       if (type != BP_VAR_IS) {
-                               zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
-                       }
-                       retval = &EG(uninitialized_zval);
-               }
-       } else {
-               if ((type != BP_VAR_IS)) {
-                       zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
                }
-               retval = &EG(uninitialized_zval);
        }
+       if ((type != BP_VAR_IS)) {
+               zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
+       }
+       retval = &EG(uninitialized_zval);
 
 exit:
        if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) {
@@ -549,15 +540,16 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
 
        property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL)) {
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
+       if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+
                        variable_ptr = &zobj->properties_table[property_info->offset];
                        if (Z_TYPE_P(variable_ptr) != IS_UNDEF) {
                                goto found;
                        }
                } else if (EXPECTED(zobj->properties != NULL)) {
-                       if ((variable_ptr = zend_hash_find(zobj->properties, property_info->name)) != NULL) {
+                       if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
 found:
                                /* if we already have this value there, we don't actually need to do anything */
                                if (EXPECTED(variable_ptr != value)) {
@@ -611,7 +603,7 @@ found:
 
        /* magic set */
        if (zobj->ce->__set) {
-               zend_long *guard = zend_get_property_guard(zobj, member);
+               zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
 
            if (!((*guard) & IN_SET)) {
                        zval tmp_object;
@@ -623,7 +615,7 @@ found:
                        }
                        (*guard) &= ~IN_SET;
                        zval_ptr_dtor(&tmp_object);
-               } else if (EXPECTED(property_info != NULL)) {
+               } else if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
                        goto write_std_property;
                } else {
                        if (Z_STRVAL_P(member)[0] == '\0') {
@@ -634,7 +626,7 @@ found:
                                }
                        }
                }
-       } else if (EXPECTED(property_info != NULL)) {
+       } else if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
                zval tmp;
 
 write_std_property:
@@ -647,15 +639,15 @@ write_std_property:
                                Z_ADDREF_P(value);
                        }
                }
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
 
                        ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value);
                } else {
                        if (!zobj->properties) {
                                rebuild_object_properties(zobj);
                        }
-                       zend_hash_update(zobj->properties, property_info->name, value);
+                       zend_hash_update(zobj->properties, Z_STR_P(member), value);
                }
        }
 
@@ -751,68 +743,63 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
 static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */
 {
        zend_object *zobj;
-       zval tmp_member;
-       zval *retval, tmp;
+       zend_string *name;
+       zval *retval = NULL;
        zend_property_info *property_info;
-       zend_long *guard;
 
        zobj = Z_OBJ_P(object);
-
-       ZVAL_UNDEF(&tmp_member);
-       if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
-               ZVAL_STR(&tmp_member, zval_get_string(member));
-               member = &tmp_member;
-               cache_slot = NULL;
+       if (EXPECTED(Z_TYPE_P(member) == IS_STRING)) {
+               name = Z_STR_P(member);
+       } else {
+               name = zval_get_string(member);
        }
 
 #if DEBUG_OBJECT_HANDLERS
-       fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
+       fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), name->val);
 #endif
 
-       property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__get != NULL), cache_slot TSRMLS_CC);
+       property_info = zend_get_property_info_quick(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL)) {
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
-                       retval = &zobj->properties_table[property_info->offset];
-                       if (Z_TYPE_P(retval) != IS_UNDEF) {
-                               goto exit;
-                       }
-               } else if (UNEXPECTED(zobj->properties != NULL)) {
-                       retval = zend_hash_find(zobj->properties, property_info->name);
-                       if (retval) goto exit;
-               }
-       }
-
-       if (!zobj->ce->__get ||
-               (guard = zend_get_property_guard(zobj, member)) == NULL ||
-               (property_info && ((*guard) & IN_GET))) {
+       if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
 
-               ZVAL_NULL(&tmp);
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
                        retval = &zobj->properties_table[property_info->offset];
-                       ZVAL_NULL(retval);
+                       if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
+                               if (EXPECTED(!zobj->ce->__get) ||
+                                   UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
+                                       ZVAL_NULL(retval);
+                                       /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
+                                        * being overwritten in an error handler. */
+                                       if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
+                                               zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val);
+                                       }
+                               } else {
+                                       /* we do have getter - fail and let it try again with usual get/set */
+                                       retval = NULL;
+                               }
+                       }
                } else {
-                       if (!zobj->properties) {
-                               rebuild_object_properties(zobj);
+                       if (UNEXPECTED(!zobj->properties) ||
+                           UNEXPECTED((retval = zend_hash_find(zobj->properties, name)) == NULL)) {
+                               if (EXPECTED(!zobj->ce->__get) ||
+                                   UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
+                                       if (UNEXPECTED(!zobj->properties)) {
+                                               rebuild_object_properties(zobj);
+                                       }
+                                       retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
+                                       /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
+                                        * being overwritten in an error handler. */
+                                       if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
+                                               zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val);
+                                       }
+                       }
                        }
-                       retval = zend_hash_update(zobj->properties, property_info->name, &tmp);
                }
-
-               /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
-                * being overwritten in an error handler. */
-               if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
-                       zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
-               }
-       } else {
-               /* we do have getter - fail and let it try again with usual get/set */
-               retval = NULL;
        }
 
-exit:
-       if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) {
-               zval_dtor(&tmp_member);
+       if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
+               zend_string_release(name);
        }
        return retval;
 }
@@ -835,23 +822,24 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
 
        property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL)) {
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
+       if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+
                        if (Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
                                zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
                                ZVAL_UNDEF(&zobj->properties_table[property_info->offset]);
                                goto exit;
                        }
                } else if (zobj->properties &&
-               UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) != FAILURE)) {
+               EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) {
                        goto exit;
                }
        }
        
        /* magic unset */
        if (zobj->ce->__unset) {
-               zend_long *guard = zend_get_property_guard(zobj, member);
+               zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
                if (!((*guard) & IN_UNSET)) {
                        zval tmp_object;
 
@@ -1431,15 +1419,16 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
 
        property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), 1, cache_slot TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL)) {
-               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0) {
+       if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
+               if (EXPECTED(property_info != NULL) &&
+                   EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+
                        value = &zobj->properties_table[property_info->offset];
                        if (Z_TYPE_P(value) != IS_UNDEF) {
                                goto found;
                        }
                } else if (UNEXPECTED(zobj->properties != NULL) &&
-                          (value = zend_hash_find(zobj->properties, property_info->name)) != NULL) {
+                          (value = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
 found:
                        switch (has_set_exists) {
                                case 0:
@@ -1459,7 +1448,7 @@ found:
 
        result = 0;
        if ((has_set_exists != 2) && zobj->ce->__isset) {
-               zend_long *guard = zend_get_property_guard(zobj, member);
+               zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
 
                if (!((*guard) & IN_ISSET)) {
                        zval rv;
index 2b06ebdf3da737212505641faef29ac9c8d0fec9..ac0965ad572c15fa4afe83ffaa55d5c55c76d8a6 100644 (file)
@@ -25,6 +25,9 @@
 union _zend_function;
 struct _zend_property_info;
 
+#define ZEND_WRONG_PROPERTY_INFO \
+       ((struct _zend_property_info*)((zend_intptr_t)-1))
+
 /* The following rule applies to read_property() and read_dimension() implementations:
    If you return a zval which is not otherwise referenced by the extension or the engine's
    symbol table, its reference count should be 0.
index 57e11945c1f809a9791b4e347703ad63aa727054..cc4ed54deab4d6713c2184f7fbc528b52813e734 100644 (file)
@@ -3922,9 +3922,14 @@ static int _adddynproperty(zval *ptr TSRMLS_DC, int num_args, va_list args, zend
                return 0; /* non public cannot be dynamic */
        }
 
-       if (zend_get_property_info(ce, hash_key->key, 1 TSRMLS_CC) == &EG(std_property_info)) {
-               EG(std_property_info).flags = ZEND_ACC_IMPLICIT_PUBLIC;
-               reflection_property_factory(ce, &EG(std_property_info), &property TSRMLS_CC);
+       if (zend_get_property_info(ce, hash_key->key, 1 TSRMLS_CC) == NULL) {
+               zend_property_info property_info;
+               
+               property_info.flags = ZEND_ACC_IMPLICIT_PUBLIC;
+               property_info.name = hash_key->key;
+               property_info.ce = ce;
+               property_info.offset = -1;
+               reflection_property_factory(ce, &property_info, &property TSRMLS_CC);
                add_next_index_zval(retval, &property);
        }
        return 0;
index d34587b85ecf26e6c962a664d133d886e942177b..b12303ee0e2bc6004aa9044fcb64d8d59d7d4fc3 100644 (file)
@@ -1203,7 +1203,8 @@ static zval* get_zval_property(zval* object, char* name, zval *rv TSRMLS_DC)
 
                        property_info = zend_get_property_info(Z_OBJCE_P(object), Z_STR(member), 1 TSRMLS_CC);
                        EG(scope) = old_scope;
-                       if (property_info && zend_hash_exists(Z_OBJPROP_P(object), property_info->name)) {
+                       if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info &&
+                           zend_hash_exists(Z_OBJPROP_P(object), property_info->name)) {
                                zval_ptr_dtor(&member);
                                return data;
                        }