]> granicus.if.org Git - php/commitdiff
Use zend_type.ce_cache__ptr for caching class resulution during argument/result type...
authorDmitry Stogov <dmitry@zend.com>
Wed, 10 Feb 2021 15:00:00 +0000 (18:00 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 10 Feb 2021 15:00:00 +0000 (18:00 +0300)
Zend/zend_compile.c
Zend/zend_execute.c
Zend/zend_inheritance.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/jit/zend_jit_helpers.c

index d617547f81ef6f0706fdc6c951f1d059499579af..069acae0c151fa65041d6fdd0c46645e7fd809eb 100644 (file)
@@ -1197,7 +1197,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
                        } else {
                                if (ZEND_TYPE_HAS_CE_CACHE(*list_type)
                                 && ZEND_TYPE_CE_CACHE(*list_type)) {
-                                       str = add_type_string(str, ZEND_TYPE_CE_CACHE(*list_type)->name);
+                                       zend_class_entry *ce = ZEND_TYPE_CE_CACHE(*list_type);
+                                       if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
+                                               zend_string *tmp = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
+                                               str = add_type_string(str, tmp);
+                                       } else {
+                                               str = add_type_string(str, ce->name);
+                                       }
                                } else {
                                        zend_string *resolved = resolve_class_name(ZEND_TYPE_NAME(*list_type), scope);
                                        str = add_type_string(str, resolved);
@@ -1208,7 +1214,12 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
        } else if (ZEND_TYPE_HAS_NAME(type)) {
                if (ZEND_TYPE_HAS_CE_CACHE(type)
                 && ZEND_TYPE_CE_CACHE(type)) {
-                       str = zend_string_copy(ZEND_TYPE_CE_CACHE(type)->name);
+                       zend_class_entry *ce = ZEND_TYPE_CE_CACHE(type);
+                       if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
+                               str = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
+                       } else {
+                               str = zend_string_copy(ce->name);
+                       }
                } else {
                        str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
                }
index 5338a0ae43bd3213923865d757f216da79a02dfd..02912c200977f32a882d0bd5d1b44e2614b7bb09 100644 (file)
@@ -857,24 +857,26 @@ static bool zend_check_and_resolve_property_class_type(
        if (ZEND_TYPE_HAS_LIST(info->type)) {
                zend_type *list_type;
                ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
-                       if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
-                               ce = ZEND_TYPE_CE_CACHE(*list_type);
-                               if (!ce) {
+                       if (ZEND_TYPE_HAS_NAME(*list_type)) {
+                               if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
+                                       ce = ZEND_TYPE_CE_CACHE(*list_type);
+                                       if (!ce) {
+                                               zend_string *name = ZEND_TYPE_NAME(*list_type);
+                                               ce = resolve_single_class_type(name, info->ce);
+                                               if (UNEXPECTED(!ce)) {
+                                                       continue;
+                                               }
+                                               ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
+                                       }
+                               } else {
                                        zend_string *name = ZEND_TYPE_NAME(*list_type);
                                        ce = resolve_single_class_type(name, info->ce);
-                                       if (UNEXPECTED(!ce)) {
+                                       if (!ce) {
                                                continue;
                                        }
-                                       ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
-                               }
-                       } else if (ZEND_TYPE_HAS_NAME(*list_type)) {
-                               zend_string *name = ZEND_TYPE_NAME(*list_type);
-                               ce = resolve_single_class_type(name, info->ce);
-                               if (!ce) {
-                                       continue;
+                                       zend_string_release(name);
+                                       ZEND_TYPE_SET_CE(*list_type, ce);
                                }
-                               zend_string_release(name);
-                               ZEND_TYPE_SET_CE(*list_type, ce);
                        } else {
                                ce = ZEND_TYPE_CE(*list_type);
                        }
@@ -884,25 +886,27 @@ static bool zend_check_and_resolve_property_class_type(
                } ZEND_TYPE_LIST_FOREACH_END();
                return 0;
        } else {
-               if (ZEND_TYPE_HAS_CE_CACHE(info->type)) {
-                       ce = ZEND_TYPE_CE_CACHE(info->type);
-                       if (!ce) {
+               if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
+                       if (ZEND_TYPE_HAS_CE_CACHE(info->type)) {
+                               ce = ZEND_TYPE_CE_CACHE(info->type);
+                               if (!ce) {
+                                       zend_string *name = ZEND_TYPE_NAME(info->type);
+                                       ce = resolve_single_class_type(name, info->ce);
+                                       if (UNEXPECTED(!ce)) {
+                                               return 0;
+                                       }
+                                       ZEND_TYPE_SET_CE_CACHE(info->type, ce);
+                               }
+                       } else {
                                zend_string *name = ZEND_TYPE_NAME(info->type);
                                ce = resolve_single_class_type(name, info->ce);
                                if (UNEXPECTED(!ce)) {
                                        return 0;
                                }
-                               ZEND_TYPE_SET_CE_CACHE(info->type, ce);
-                       }
-               } else if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
-                       zend_string *name = ZEND_TYPE_NAME(info->type);
-                       ce = resolve_single_class_type(name, info->ce);
-                       if (UNEXPECTED(!ce)) {
-                               return 0;
-                       }
 
-                       zend_string_release(name);
-                       ZEND_TYPE_SET_CE(info->type, ce);
+                               zend_string_release(name);
+                               ZEND_TYPE_SET_CE(info->type, ce);
+                       }
                } else {
                        ce = ZEND_TYPE_CE(info->type);
                }
@@ -980,17 +984,22 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
 #endif
 
 static zend_always_inline bool zend_check_type_slow(
-               zend_type type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
+               zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
                bool is_return_type, bool is_internal)
 {
        uint32_t type_mask;
-       if (ZEND_TYPE_HAS_CLASS(type) && Z_TYPE_P(arg) == IS_OBJECT) {
+       if (ZEND_TYPE_HAS_CLASS(*type) && Z_TYPE_P(arg) == IS_OBJECT) {
                zend_class_entry *ce;
-               if (ZEND_TYPE_HAS_LIST(type)) {
+               if (ZEND_TYPE_HAS_LIST(*type)) {
                        zend_type *list_type;
-                       ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
+                       ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
                                if (HAVE_CACHE_SLOT && *cache_slot) {
                                        ce = *cache_slot;
+                               } else if (ZEND_TYPE_HAS_CE_CACHE(*list_type) && ZEND_TYPE_CE_CACHE(*list_type)) {
+                                       ce = ZEND_TYPE_CE_CACHE(*list_type);
+                                       if (HAVE_CACHE_SLOT) {
+                                               *cache_slot = ce;
+                                       }
                                } else {
                                        ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type),
                                                (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
@@ -1003,6 +1012,9 @@ static zend_always_inline bool zend_check_type_slow(
                                        if (HAVE_CACHE_SLOT) {
                                                *cache_slot = ce;
                                        }
+                                       if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
+                                               ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
+                                       }
                                }
                                if (instanceof_function(Z_OBJCE_P(arg), ce)) {
                                        return 1;
@@ -1014,14 +1026,22 @@ static zend_always_inline bool zend_check_type_slow(
                } else {
                        if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
                                ce = (zend_class_entry *) *cache_slot;
+                       } else if (ZEND_TYPE_HAS_CE_CACHE(*type) && ZEND_TYPE_CE_CACHE(*type)) {
+                               ce = ZEND_TYPE_CE_CACHE(*type);
+                               if (HAVE_CACHE_SLOT) {
+                                       *cache_slot = ce;
+                               }
                        } else {
-                               ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
+                               ce = zend_fetch_class(ZEND_TYPE_NAME(*type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
                                if (UNEXPECTED(!ce)) {
                                        goto builtin_types;
                                }
                                if (HAVE_CACHE_SLOT) {
                                        *cache_slot = (void *) ce;
                                }
+                               if (ZEND_TYPE_HAS_CE_CACHE(*type)) {
+                                       ZEND_TYPE_SET_CE_CACHE(*type, ce);
+                               }
                        }
                        if (instanceof_function(Z_OBJCE_P(arg), ce)) {
                                return 1;
@@ -1030,7 +1050,7 @@ static zend_always_inline bool zend_check_type_slow(
        }
 
 builtin_types:
-       type_mask = ZEND_TYPE_FULL_MASK(type);
+       type_mask = ZEND_TYPE_FULL_MASK(*type);
        if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
                return 1;
        }
@@ -1060,18 +1080,18 @@ builtin_types:
 }
 
 static zend_always_inline bool zend_check_type(
-               zend_type type, zval *arg, void **cache_slot, zend_class_entry *scope,
+               zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope,
                bool is_return_type, bool is_internal)
 {
        zend_reference *ref = NULL;
-       ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
+       ZEND_ASSERT(ZEND_TYPE_IS_SET(*type));
 
        if (UNEXPECTED(Z_ISREF_P(arg))) {
                ref = Z_REF_P(arg);
                arg = Z_REFVAL_P(arg);
        }
 
-       if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(arg)))) {
+       if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(*type, Z_TYPE_P(arg)))) {
                return 1;
        }
 
@@ -1086,7 +1106,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint
        cur_arg_info = &zf->common.arg_info[arg_num-1];
 
        if (ZEND_TYPE_IS_SET(cur_arg_info->type)
-                       && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
+                       && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
                zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
                return 0;
        }
@@ -1098,7 +1118,7 @@ static zend_always_inline bool zend_verify_variadic_arg_type(
                zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot)
 {
        ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
-       if (UNEXPECTED(!zend_check_type(arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
+       if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
                zend_verify_arg_error(zf, arg_info, arg_num, arg);
                return 0;
        }
@@ -1123,7 +1143,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
                }
 
                if (ZEND_TYPE_IS_SET(cur_arg_info->type)
-                               && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
+                               && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
                        return 0;
                }
                arg++;
@@ -1256,7 +1276,7 @@ static bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
                return 1;
        }
 
-       if (UNEXPECTED(!zend_check_type(ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
+       if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
                zend_verify_internal_return_error(zf, ret);
                return 0;
        }
index 32d03acb4aef59b56bc419422a64432af73bb35d..9266aa74d2275c0e3ca943c1dc8190171ac99720 100644 (file)
@@ -712,8 +712,12 @@ static ZEND_COLD zend_string *zend_get_function_declaration(
        }
 
        if (fptr->common.scope) {
-               /* cut off on NULL byte ... class@anonymous */
-               smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), strlen(ZSTR_VAL(fptr->common.scope->name)));
+               if (fptr->common.scope->ce_flags & ZEND_ACC_ANON_CLASS) {
+                       /* cut off on NULL byte ... class@anonymous */
+                       smart_str_appends(&str, ZSTR_VAL(fptr->common.scope->name));
+               } else {
+                       smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), ZSTR_LEN(fptr->common.scope->name));
+               }
                smart_str_appends(&str, "::");
        }
 
index d09fcd39b84abd02a012113a401e0e4a74222e96..98b8b51d7fa8f93a22bb18978a25f4b861617c82 100644 (file)
@@ -4227,7 +4227,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
index f27f3fd5e12017894edf68d9b3ee40e714c552a9..d680541f03851ce127e0f240fa97ee825302661d 100644 (file)
@@ -9777,7 +9777,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
@@ -20133,7 +20133,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
@@ -27730,7 +27730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
@@ -34914,7 +34914,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
@@ -46624,7 +46624,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
                }
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
+               if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
                        zend_verify_return_error(EX(func), retval_ptr);
                        HANDLE_EXCEPTION();
                }
index 696013f60f81dfdf1dd62caa2e551f03653a5eee..d46ddcd9206542149647f4a64b9abe33274b9ab3 100644 (file)
@@ -1384,6 +1384,9 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
                        ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) {
                                if (*cache_slot) {
                                        ce = *cache_slot;
+                               } else if (ZEND_TYPE_HAS_CE_CACHE(*list_type) && ZEND_TYPE_CE_CACHE(*list_type)) {
+                                       ce = ZEND_TYPE_CE_CACHE(*list_type);
+                                       *cache_slot = ce;
                                } else {
                                        ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type),
                                                (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
@@ -1392,6 +1395,9 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
                                                continue;
                                        }
                                        *cache_slot = ce;
+                                       if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
+                                               ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
+                                       }
                                }
                                if (instanceof_function(Z_OBJCE_P(arg), ce)) {
                                        return 1;
@@ -1401,12 +1407,18 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
                } else {
                        if (EXPECTED(*cache_slot)) {
                                ce = (zend_class_entry *) *cache_slot;
+                       } else if (ZEND_TYPE_HAS_CE_CACHE(arg_info->type) && ZEND_TYPE_CE_CACHE(arg_info->type)) {
+                               ce = ZEND_TYPE_CE_CACHE(arg_info->type);
+                               *cache_slot = ce;
                        } else {
                                ce = zend_fetch_class(ZEND_TYPE_NAME(arg_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
                                if (UNEXPECTED(!ce)) {
                                        goto builtin_types;
                                }
                                *cache_slot = (void *) ce;
+                               if (ZEND_TYPE_HAS_CE_CACHE(arg_info->type)) {
+                                       ZEND_TYPE_SET_CE_CACHE(arg_info->type, ce);
+                               }
                        }
                        if (instanceof_function(Z_OBJCE_P(arg), ce)) {
                                return 1;