]> granicus.if.org Git - php/commitdiff
Optimize zend_handle_fetch_obj_flags()
authorDmitry Stogov <dmitry@zend.com>
Thu, 17 Jan 2019 22:22:14 +0000 (01:22 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 17 Jan 2019 22:22:14 +0000 (01:22 +0300)
Zend/zend_execute.c

index 8efea990da32a96e4c7a8f7a196f3230e3e7a84e..cee7e95292c29fe4382e40b5e7518d860e8e9444 100644 (file)
@@ -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) {