diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-10-17 19:10:05 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-10-17 19:10:05 +0400 |
commit | 7471c217810397f05ae7a8c518af80da7baf0f4a (patch) | |
tree | 5ed4cee825e03914834ddaded78dc655c370a271 /Zend/zend_object_handlers.c | |
parent | 9935bf7df70d8fcfa9ef5c2f47e1d760ffc3f666 (diff) | |
download | php-git-7471c217810397f05ae7a8c518af80da7baf0f4a.tar.gz |
Optimized property access handlers. Removed EG(std_property_info).
Diffstat (limited to 'Zend/zend_object_handlers.c')
-rw-r--r-- | Zend/zend_object_handlers.c | 197 |
1 files changed, 93 insertions, 104 deletions
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ba089674c1..e9897ed34e 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; |