From: Dmitry Stogov Date: Thu, 17 Jan 2019 22:22:14 +0000 (+0300) Subject: Optimize zend_handle_fetch_obj_flags() X-Git-Tag: php-7.4.0alpha1~1202 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77db3d524e298f9444bc130d4fa877c62cfe968b;p=php Optimize zend_handle_fetch_obj_flags() --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 8efea990da..cee7e95292 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2624,65 +2624,82 @@ ZEND_API zend_property_info* ZEND_FASTCALL zend_check_ref_array_assignable(zend_ return i_zend_check_ref_array_assignable(ref); } -static zend_always_inline zend_bool zend_need_to_handle_fetch_obj_flags(uint32_t flags, zval *ptr) { - return (flags == ZEND_FETCH_REF && Z_TYPE_P(ptr) != IS_REFERENCE) - || (flags == ZEND_FETCH_DIM_WRITE && promotes_to_array(ptr)) - || (flags == ZEND_FETCH_OBJ_WRITE && promotes_to_object(ptr)); +static zend_property_info *zend_object_fetch_property_type_info( + zend_object *obj, zval *slot) +{ + if (EXPECTED(!ZEND_CLASS_HAS_TYPE_HINTS(obj->ce))) { + return NULL; + } + + /* Not a declared property */ + if (UNEXPECTED(slot < obj->properties_table || + slot >= obj->properties_table + obj->ce->default_properties_count)) { + return NULL; + } + + return zend_get_typed_property_info_for_slot(obj, slot); } static zend_never_inline zend_bool zend_handle_fetch_obj_flags( - zval *result, zval *ptr, zend_property_info *prop_info, uint32_t flags) + zval *result, zval *ptr, zend_object *obj, zend_property_info *prop_info, uint32_t flags) { - ZEND_ASSERT(prop_info && prop_info->type); switch (flags) { case ZEND_FETCH_DIM_WRITE: - if (!check_type_array_assignable(prop_info->type)) { - zend_throw_auto_init_in_prop_error(prop_info, "array"); - if (result) ZVAL_ERROR(result); - return 0; + if (promotes_to_array(ptr)) { + if (!prop_info) { + prop_info = zend_object_fetch_property_type_info(obj, ptr); + if (!prop_info) { + break; + } + } + if (!check_type_array_assignable(prop_info->type)) { + zend_throw_auto_init_in_prop_error(prop_info, "array"); + if (result) ZVAL_ERROR(result); + return 0; + } } break; case ZEND_FETCH_OBJ_WRITE: - if (!check_type_stdClass_assignable(prop_info->type)) { - zend_throw_auto_init_in_prop_error(prop_info, "stdClass"); - if (result) ZVAL_ERROR(result); - return 0; - } - break; - case ZEND_FETCH_REF: - if (Z_TYPE_P(ptr) == IS_UNDEF) { - if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) { - zend_throw_access_uninit_prop_by_ref_error(prop_info); + if (promotes_to_object(ptr)) { + if (!prop_info) { + prop_info = zend_object_fetch_property_type_info(obj, ptr); + if (!prop_info) { + break; + } + } + if (!check_type_stdClass_assignable(prop_info->type)) { + zend_throw_auto_init_in_prop_error(prop_info, "stdClass"); if (result) ZVAL_ERROR(result); return 0; } - ZVAL_NULL(ptr); - } + } + break; + case ZEND_FETCH_REF: + if (Z_TYPE_P(ptr) != IS_REFERENCE) { + if (!prop_info) { + prop_info = zend_object_fetch_property_type_info(obj, ptr); + if (!prop_info) { + break; + } + } + if (Z_TYPE_P(ptr) == IS_UNDEF) { + if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) { + zend_throw_access_uninit_prop_by_ref_error(prop_info); + if (result) ZVAL_ERROR(result); + return 0; + } + ZVAL_NULL(ptr); + } - ZVAL_NEW_REF(ptr, ptr); - ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(ptr), prop_info); + ZVAL_NEW_REF(ptr, ptr); + ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(ptr), prop_info); + } break; EMPTY_SWITCH_DEFAULT_CASE() } return 1; } -static zend_always_inline zend_property_info *zend_object_fetch_property_type_info( - zend_object *obj, zval *slot) -{ - if (EXPECTED(!ZEND_CLASS_HAS_TYPE_HINTS(obj->ce))) { - return NULL; - } - - /* Not a declared property */ - if (UNEXPECTED(slot < obj->properties_table || - slot >= obj->properties_table + obj->ce->default_properties_count)) { - return NULL; - } - - return zend_get_typed_property_info_for_slot(obj, slot); -} - static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_bool init_undef OPLINE_DC) { zval *ptr; @@ -2714,11 +2731,12 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { ptr = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_P(ptr) != IS_UNDEF)) { - zend_property_info *prop_info; ZVAL_INDIRECT(result, ptr); - if (flags && (prop_info = CACHED_PTR_EX(cache_slot + 2)) && - UNEXPECTED(zend_need_to_handle_fetch_obj_flags(flags, ptr))) { - zend_handle_fetch_obj_flags(result, ptr, prop_info, flags); + if (flags) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags); + } } return; } @@ -2748,11 +2766,20 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } ZVAL_INDIRECT(result, ptr); - if (flags && UNEXPECTED(zend_need_to_handle_fetch_obj_flags(flags, ptr))) { - zend_property_info *prop_info = - zend_object_fetch_property_type_info(Z_OBJ_P(container), ptr); - if (prop_info && !zend_handle_fetch_obj_flags(result, ptr, prop_info, flags)) { - return; + if (flags) { + zend_property_info *prop_info; + + if (prop_op_type == IS_CONST) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags))) { + return; + } + } + } else { + if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, Z_OBJ_P(container), NULL, flags))) { + return; + } } } if (init_undef && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) { @@ -2862,8 +2889,8 @@ static zend_always_inline int zend_fetch_static_property_address(zval **retval, } } - if (flags && property_info->type && zend_need_to_handle_fetch_obj_flags(flags, *retval)) { - zend_handle_fetch_obj_flags(NULL, *retval, property_info, flags); + if (flags && property_info->type) { + zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags); } if (prop_info) {