diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index c265c973f7dde..5fcf9e552e3fc 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2269,9 +2269,7 @@ static uint32_t zend_convert_type(const zend_script *script, zend_type type, zen if (pce) { /* As we only have space to store one CE, * we use a plain object type for class unions. */ - if (ZEND_TYPE_HAS_CE(type)) { - *pce = ZEND_TYPE_CE(type); - } else if (ZEND_TYPE_HAS_NAME(type)) { + if (ZEND_TYPE_HAS_NAME(type)) { zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(type)); *pce = zend_optimizer_get_class_entry(script, lcname); zend_string_release_ex(lcname, 0); diff --git a/Zend/tests/objects_008.phpt b/Zend/tests/objects_008.phpt index 6a8159249959a..fca878c4c33f1 100644 --- a/Zend/tests/objects_008.phpt +++ b/Zend/tests/objects_008.phpt @@ -1,9 +1,5 @@ --TEST-- method overloading with different method signature ---SKIPIF-- - --FILE-- type == ZEND_INTERNAL_CLASS); - zend_string_release(lc_type_name); - return ce; -} - -static void zend_resolve_property_types(void) /* {{{ */ -{ - zend_class_entry *ce; - zend_property_info *prop_info; - - ZEND_HASH_FOREACH_PTR(CG(class_table), ce) { - if (ce->type != ZEND_INTERNAL_CLASS) { - continue; - } - - if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) { - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { - zend_type *single_type; - ZEND_TYPE_FOREACH(prop_info->type, single_type) { - if (ZEND_TYPE_HAS_NAME(*single_type)) { - zend_string *type_name = ZEND_TYPE_NAME(*single_type); - ZEND_TYPE_SET_CE(*single_type, resolve_type_name(type_name)); - zend_string_release(type_name); - } - } ZEND_TYPE_FOREACH_END(); - } ZEND_HASH_FOREACH_END(); - } - } ZEND_HASH_FOREACH_END(); -} -/* }}} */ /* Unlink the global (r/o) copies of the class, function and constant tables, * and use a fresh r/w copy for the startup thread @@ -1065,7 +1032,7 @@ zend_result zend_post_startup(void) /* {{{ */ zend_executor_globals *executor_globals = ts_resource(executor_globals_id); #endif - zend_resolve_property_types(); + startup_done = true; if (zend_post_startup_cb) { zend_result (*cb)(void) = zend_post_startup_cb; @@ -1164,6 +1131,7 @@ void zend_shutdown(void) /* {{{ */ zend_destroy_rsrc_list_dtors(); zend_optimizer_shutdown(); + startup_done = false; } /* }}} */ @@ -1892,3 +1860,29 @@ ZEND_API void zend_map_ptr_extend(size_t last) CG(map_ptr_last) = last; } } + +ZEND_API void zend_alloc_ce_cache(zend_string *type_name) +{ + if (ZSTR_HAS_CE_CACHE(type_name) || !ZSTR_IS_INTERNED(type_name)) { + return; + } + + if ((GC_FLAGS(type_name) & IS_STR_PERMANENT) && startup_done) { + /* Don't allocate slot on permanent interned string outside module startup. + * The cache slot would no longer be valid on the next request. */ + return; + } + + if (zend_string_equals_literal_ci(type_name, "self") + || zend_string_equals_literal_ci(type_name, "parent")) { + return; + } + + /* We use the refcount to keep map_ptr of corresponding type */ + uint32_t ret; + do { + ret = (uint32_t)(uintptr_t)zend_map_ptr_new(); + } while (ret <= 2); + GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR); + GC_SET_REFCOUNT(type_name, ret); +} diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b32bad3091ee0..da05581d47c2f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3053,6 +3053,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class class_entry->type = ZEND_INTERNAL_CLASS; zend_initialize_class_data(class_entry, 0); + zend_alloc_ce_cache(class_entry->name); class_entry->ce_flags = orig_class_entry->ce_flags | ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES; class_entry->info.internal.module = EG(current_module); @@ -4126,6 +4127,17 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z property_info->ce = ce; property_info->type = type; + if (is_persistent_class(ce)) { + zend_type *single_type; + ZEND_TYPE_FOREACH(property_info->type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type)); + ZEND_TYPE_SET_PTR(*single_type, name); + zend_alloc_ce_cache(name); + } + } ZEND_TYPE_FOREACH_END(); + } + zend_hash_update_ptr(&ce->properties_info, name, property_info); return property_info; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5f5fc41034c69..af0523264cf58 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1202,43 +1202,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop zend_type *list_type; bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type); ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { - if (ZEND_TYPE_HAS_CE(*list_type)) { - str = add_type_string(str, ZEND_TYPE_CE(*list_type)->name, is_intersection); - } else { - zend_string *name = ZEND_TYPE_NAME(*list_type); - - if (ZSTR_HAS_CE_CACHE(name) - && ZSTR_GET_CE_CACHE(name)) { - zend_class_entry *ce = ZSTR_GET_CE_CACHE(name); - 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, is_intersection); - } else { - str = add_type_string(str, ce->name, is_intersection); - } - } else { - zend_string *resolved = resolve_class_name(name, scope); - str = add_type_string(str, resolved, is_intersection); - zend_string_release(resolved); - } - } + zend_string *name = ZEND_TYPE_NAME(*list_type); + zend_string *resolved = resolve_class_name(name, scope); + str = add_type_string(str, resolved, is_intersection); + zend_string_release(resolved); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(type)) { - zend_string *name = ZEND_TYPE_NAME(type); - - if (ZSTR_HAS_CE_CACHE(name) - && ZSTR_GET_CE_CACHE(name)) { - zend_class_entry *ce = ZSTR_GET_CE_CACHE(name); - 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(name, scope); - } - } else if (ZEND_TYPE_HAS_CE(type)) { - str = zend_string_copy(ZEND_TYPE_CE(type)->name); + str = resolve_class_name(ZEND_TYPE_NAME(type), scope); } uint32_t type_mask = ZEND_TYPE_PURE_MASK(type); @@ -6232,6 +6202,8 @@ static zend_type zend_compile_single_typename(zend_ast *ast) } } + class_name = zend_new_interned_string(class_name); + zend_alloc_ce_cache(class_name); return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, 0, 0); } } @@ -7687,6 +7659,9 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ ce->type = ZEND_USER_CLASS; ce->name = name; zend_initialize_class_data(ce, 1); + if (!(decl->flags & ZEND_ACC_ANON_CLASS)) { + zend_alloc_ce_cache(ce->name); + } if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) { ce->ce_flags |= ZEND_ACC_PRELOADED; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f43e49ea7ab78..c0883c8eb7586 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -851,11 +851,6 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error( static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class_entry *self_ce) { if (zend_string_equals_literal_ci(name, "self")) { - /* We need to explicitly check for this here, to avoid updating the type in the trait and - * later using the wrong "self" when the trait is used in a class. */ - if (UNEXPECTED((self_ce->ce_flags & ZEND_ACC_TRAIT) != 0)) { - return NULL; - } return self_ce; } else if (zend_string_equals_literal_ci(name, "parent")) { return self_ce->parent; @@ -866,26 +861,16 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class static zend_always_inline zend_class_entry *zend_ce_from_type( zend_property_info *info, zend_type *type) { - if (UNEXPECTED(!ZEND_TYPE_HAS_NAME(*type))) { - ZEND_ASSERT(ZEND_TYPE_HAS_CE(*type)); - return ZEND_TYPE_CE(*type); - } - + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*type)); zend_string *name = ZEND_TYPE_NAME(*type); - zend_class_entry *ce; if (ZSTR_HAS_CE_CACHE(name)) { - ce = ZSTR_GET_CE_CACHE(name); + zend_class_entry *ce = ZSTR_GET_CE_CACHE(name); if (!ce) { ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); } - } else { - ce = resolve_single_class_type(name, info->ce); - if (ce && !(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) { - zend_string_release(name); - ZEND_TYPE_SET_CE(*type, ce); - } + return ce; } - return ce; + return resolve_single_class_type(name, info->ce); } static bool zend_check_and_resolve_property_class_type( diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 2dc2175811079..d2edae17cd364 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -430,9 +430,6 @@ static inheritance_status zend_is_intersection_subtype_of_class( if (!proto_ce) proto_ce = lookup_class(proto_scope, proto_class_name); fe_ce = lookup_class(fe_scope, fe_class_name); - } else if (ZEND_TYPE_HAS_CE(*single_type)) { - if (!proto_ce) proto_ce = lookup_class(proto_scope, proto_class_name); - fe_ce = ZEND_TYPE_CE(*single_type); } else { /* standard type in an intersection type is impossible, * because it would be a fatal compile error */ @@ -456,8 +453,9 @@ static inheritance_status zend_is_intersection_subtype_of_class( /* Check whether a single class proto type is a subtype of a potentially complex fe_type. */ static inheritance_status zend_is_class_subtype_of_type( - zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *fe_ce, + zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *proto_scope, zend_type proto_type) { + zend_class_entry *fe_ce = NULL; bool have_unresolved = 0; /* If the parent has 'object' as a return type, any class satisfies the co-variant check */ @@ -503,9 +501,6 @@ static inheritance_status zend_is_class_subtype_of_type( if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); proto_ce = lookup_class(proto_scope, proto_class_name); - } else if (ZEND_TYPE_HAS_CE(*single_type)) { - if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); - proto_ce = ZEND_TYPE_CE(*single_type); } else { /* standard type */ ZEND_ASSERT(!is_intersection); @@ -535,16 +530,10 @@ static inheritance_status zend_is_class_subtype_of_type( return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } -static zend_string *get_class_from_type( - zend_class_entry **ce, zend_class_entry *scope, zend_type single_type) { +static zend_string *get_class_from_type(zend_class_entry *scope, zend_type single_type) { if (ZEND_TYPE_HAS_NAME(single_type)) { - *ce = NULL; return resolve_class_name(scope, ZEND_TYPE_NAME(single_type)); } - if (ZEND_TYPE_HAS_CE(single_type)) { - *ce = ZEND_TYPE_CE(single_type); - return (*ce)->name; - } return NULL; } @@ -617,14 +606,11 @@ static inheritance_status zend_perform_covariant_type_check( if (proto_type_mask & (MAY_BE_OBJECT|MAY_BE_ITERABLE)) { bool any_class = (proto_type_mask & MAY_BE_OBJECT) != 0; ZEND_TYPE_FOREACH(fe_type, single_type) { - zend_class_entry *fe_ce; - zend_string *fe_class_name = get_class_from_type(&fe_ce, fe_scope, *single_type); + zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); if (!fe_class_name) { continue; } - if (!fe_ce) { - fe_ce = lookup_class(fe_scope, fe_class_name); - } + zend_class_entry *fe_ce = lookup_class(fe_scope, fe_class_name); if (fe_ce) { if (any_class || unlinked_instanceof(fe_ce, zend_ce_traversable)) { track_class_dependency(fe_ce, fe_class_name); @@ -643,13 +629,12 @@ static inheritance_status zend_perform_covariant_type_check( early_exit_status = ZEND_TYPE_IS_INTERSECTION(proto_type) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS; ZEND_TYPE_FOREACH(proto_type, single_type) { - zend_class_entry *proto_ce; - zend_string *proto_class_name = - get_class_from_type(&proto_ce, proto_scope, *single_type); + zend_string *proto_class_name = get_class_from_type(proto_scope, *single_type); if (!proto_class_name) { continue; } + zend_class_entry *proto_ce = NULL; inheritance_status status = zend_is_intersection_subtype_of_class( fe_scope, fe_type, proto_scope, proto_class_name, proto_ce); if (status == early_exit_status) { @@ -666,14 +651,13 @@ static inheritance_status zend_perform_covariant_type_check( * whether proto_type is a union or intersection (only the inner check differs). */ early_exit_status = INHERITANCE_ERROR; ZEND_TYPE_FOREACH(fe_type, single_type) { - zend_class_entry *fe_ce; - zend_string *fe_class_name = get_class_from_type(&fe_ce, fe_scope, *single_type); + zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); if (!fe_class_name) { continue; } inheritance_status status = zend_is_class_subtype_of_type( - fe_scope, fe_class_name, fe_ce, proto_scope, proto_type); + fe_scope, fe_class_name, proto_scope, proto_type); if (status == early_exit_status) { return status; } diff --git a/Zend/zend_map_ptr.h b/Zend/zend_map_ptr.h index 5e039267bd165..5fd239d69d08a 100644 --- a/Zend/zend_map_ptr.h +++ b/Zend/zend_map_ptr.h @@ -103,5 +103,6 @@ ZEND_API void zend_map_ptr_reset(void); ZEND_API void *zend_map_ptr_new(void); ZEND_API void zend_map_ptr_extend(size_t last); +ZEND_API void zend_alloc_ce_cache(zend_string *type_name); #endif /* ZEND_MAP_PTR_H */ diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 3a101fead8bc6..dd55e733aeb4a 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -111,13 +111,11 @@ typedef void (*copy_ctor_func_t)(zval *pElement); * ZEND_TYPE_IS_SET() - checks if there is a type-hint * ZEND_TYPE_IS_ONLY_MASK() - checks if type-hint refer to standard type only * ZEND_TYPE_IS_COMPLEX() - checks if type is a type_list, or contains a class either as a CE or as a name - * ZEND_TYPE_HAS_CE() - checks if type-hint contains some class as zend_class_entry * * ZEND_TYPE_HAS_NAME() - checks if type-hint contains some class as zend_string * * ZEND_TYPE_IS_INTERSECTION() - checks if the type_list represents an intersection type list * ZEND_TYPE_IS_UNION() - checks if the type_list represents a union type list * * ZEND_TYPE_NAME() - returns referenced class name - * ZEND_TYPE_CE() - returns referenced class entry * ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask * ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags * @@ -144,9 +142,8 @@ typedef struct { #define _ZEND_TYPE_MASK ((1u << 25) - 1) /* Only one of these bits may be set. */ #define _ZEND_TYPE_NAME_BIT (1u << 24) -#define _ZEND_TYPE_CE_BIT (1u << 23) #define _ZEND_TYPE_LIST_BIT (1u << 22) -#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_CE_BIT|_ZEND_TYPE_NAME_BIT) +#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_NAME_BIT) /* TODO: bit 21 is not used */ /* Whether the type list is arena allocated */ #define _ZEND_TYPE_ARENA_BIT (1u << 20) @@ -163,13 +160,10 @@ typedef struct { (((t).type_mask & _ZEND_TYPE_MASK) != 0) /* If a type is complex it means it's either a list with a union or intersection, - * or the void pointer is a CE/Name */ + * or the void pointer is a class name */ #define ZEND_TYPE_IS_COMPLEX(t) \ ((((t).type_mask) & _ZEND_TYPE_KIND_MASK) != 0) -#define ZEND_TYPE_HAS_CE(t) \ - ((((t).type_mask) & _ZEND_TYPE_CE_BIT) != 0) - #define ZEND_TYPE_HAS_NAME(t) \ ((((t).type_mask) & _ZEND_TYPE_NAME_BIT) != 0) @@ -194,9 +188,6 @@ typedef struct { #define ZEND_TYPE_LITERAL_NAME(t) \ ((const char *) (t).ptr) -#define ZEND_TYPE_CE(t) \ - ((zend_class_entry *) (t).ptr) - #define ZEND_TYPE_LIST(t) \ ((zend_type_list *) (t).ptr) @@ -242,13 +233,10 @@ typedef struct { (t).type_mask |= (kind_bit); \ } while (0) -#define ZEND_TYPE_SET_CE(t, ce) \ - ZEND_TYPE_SET_PTR_AND_KIND(t, ce, _ZEND_TYPE_CE_BIT) - #define ZEND_TYPE_SET_LIST(t, list) \ ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_LIST_BIT) -/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits. +/* FULL_MASK() includes the MAY_BE_* type mask, as well as additional metadata bits. * The PURE_MASK() only includes the MAY_BE_* type mask. */ #define ZEND_TYPE_FULL_MASK(t) \ ((t).type_mask) @@ -285,9 +273,6 @@ typedef struct { #define ZEND_TYPE_INIT_PTR_MASK(ptr, type_mask) \ { (void *) (ptr), (type_mask) } -#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \ - ZEND_TYPE_INIT_PTR(_ce, _ZEND_TYPE_CE_BIT, allow_null, extra_flags) - #define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \ ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 5e55d838b4425..95daa37c9399d 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -485,8 +485,7 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str) do { s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos); if (EXPECTED(ZSTR_H(s) == h) && zend_string_equal_content(s, str)) { - zend_string_release(str); - return s; + goto finish; } pos = STRTAB_COLLISION(s); } while (pos != STRTAB_INVALID_POS); @@ -511,6 +510,15 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str) memcpy(ZSTR_VAL(s), ZSTR_VAL(str), ZSTR_LEN(s) + 1); ZCSG(interned_strings).top = STRTAB_NEXT(s); +finish: + /* Transfer CE_CACHE map ptr slot to new interned string. + * Should only happen for permanent interned strings with permanent map_ptr slot. */ + if (ZSTR_HAS_CE_CACHE(str) && !ZSTR_HAS_CE_CACHE(s)) { + ZEND_ASSERT(GC_FLAGS(str) & IS_STR_PERMANENT); + GC_SET_REFCOUNT(s, GC_REFCOUNT(str)); + GC_ADD_FLAGS(s, IS_STR_CLASS_NAME_MAP_PTR); + } + zend_string_release(str); return s; } @@ -624,6 +632,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int if (ce->name) { ce->name = new_interned_string(ce->name); + ZEND_ASSERT(ZSTR_HAS_CE_CACHE(ce->name)); } ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, q) { @@ -741,20 +750,6 @@ static zend_string* ZEND_FASTCALL accel_replace_string_by_shm_permanent(zend_str return str; } -static void accel_allocate_ce_cache_slots(void) -{ - Bucket *p; - - ZEND_HASH_FOREACH_BUCKET(CG(class_table), p) { - zend_class_entry *ce; - - ce = (zend_class_entry*)Z_PTR(p->val); - if (ce->name) { - zend_accel_get_class_name_map_ptr(ce->name); - } - } ZEND_HASH_FOREACH_END(); -} - static void accel_use_shm_interned_strings(void) { HANDLE_BLOCK_INTERRUPTIONS(); @@ -763,7 +758,6 @@ static void accel_use_shm_interned_strings(void) if (ZCSG(interned_strings).saved_top == NULL) { accel_copy_permanent_strings(accel_new_interned_string); - accel_allocate_ce_cache_slots(); } else { ZCG(counted) = 1; accel_copy_permanent_strings(accel_replace_string_by_shm_permanent); @@ -3789,32 +3783,6 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) return ok || was_changed; } -static zend_class_entry *preload_fetch_resolved_ce(zend_string *name) { - zend_string *lcname = zend_string_tolower(name); - zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lcname); - zend_string_release(lcname); - return ce; -} - -static void preload_try_resolve_property_types(zend_class_entry *ce) -{ - if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) { - zend_property_info *prop; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - zend_type *single_type; - ZEND_TYPE_FOREACH(prop->type, single_type) { - if (ZEND_TYPE_HAS_NAME(*single_type)) { - zend_class_entry *p = - preload_fetch_resolved_ce(ZEND_TYPE_NAME(*single_type)); - if (p) { - ZEND_TYPE_SET_CE(*single_type, p); - } - } - } ZEND_TYPE_FOREACH_END(); - } ZEND_HASH_FOREACH_END(); - } -} - static void (*orig_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message); static void preload_error_cb(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message) @@ -3986,18 +3954,6 @@ static void preload_link(void) } ZEND_HASH_FOREACH_END(); } while (changed); - /* Resolve property types */ - ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { - ce = Z_PTR_P(zv); - if (ce->type == ZEND_INTERNAL_CLASS) { - break; - } - if (!(ce->ce_flags & ZEND_ACC_TRAIT)) { - preload_try_resolve_property_types(ce); - } - } ZEND_HASH_FOREACH_END(); - - do { changed = 0; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 9a7f0d73b1eed..93a8ab24a4506 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -260,35 +260,35 @@ static void *zend_file_cache_serialize_interned(zend_string *str, ((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1), 0); } - memcpy(ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size, str, len); + + zend_string *new_str = (zend_string *) (ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size); + memcpy(new_str, str, len); + GC_ADD_FLAGS(new_str, IS_STR_INTERNED); + GC_DEL_FLAGS(new_str, IS_STR_PERMANENT|IS_STR_CLASS_NAME_MAP_PTR); info->str_size += len; return ret; } static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm) { - zend_string *ret; - str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1))); - if (in_shm) { - ret = accel_new_interned_string(str); - if (ret == str) { - /* We have to create new SHM allocated string */ - size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)); - ret = zend_shared_alloc(size); - if (!ret) { - zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM); - LONGJMP(*EG(bailout), FAILURE); - } - memcpy(ret, str, size); - /* String wasn't interned but we will use it as interned anyway */ - GC_SET_REFCOUNT(ret, 1); - GC_TYPE_INFO(ret) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERSISTENT | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); + if (!in_shm) { + return str; + } + + zend_string *ret = accel_new_interned_string(str); + if (ret == str) { + /* We have to create new SHM allocated string */ + size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)); + ret = zend_shared_alloc(size); + if (!ret) { + zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM); + LONGJMP(*EG(bailout), FAILURE); } - } else { - ret = str; - GC_ADD_FLAGS(ret, IS_STR_INTERNED); - GC_DEL_FLAGS(ret, IS_STR_PERMANENT); + memcpy(ret, str, size); + /* String wasn't interned but we will use it as interned anyway */ + GC_SET_REFCOUNT(ret, 1); + GC_TYPE_INFO(ret) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERSISTENT | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); } return ret; } @@ -440,10 +440,6 @@ static void zend_file_cache_serialize_type( zend_string *type_name = ZEND_TYPE_NAME(*type); SERIALIZE_STR(type_name); ZEND_TYPE_SET_PTR(*type, type_name); - } else if (ZEND_TYPE_HAS_CE(*type)) { - zend_class_entry *ce = ZEND_TYPE_CE(*type); - SERIALIZE_PTR(ce); - ZEND_TYPE_SET_PTR(*type, ce); } } @@ -1232,11 +1228,9 @@ static void zend_file_cache_unserialize_type( ZEND_TYPE_SET_PTR(*type, type_name); if (!script->corrupted) { zend_accel_get_class_name_map_ptr(type_name); + } else { + zend_alloc_ce_cache(type_name); } - } else if (ZEND_TYPE_HAS_CE(*type)) { - zend_class_entry *ce = ZEND_TYPE_CE(*type); - UNSERIALIZE_PTR(ce); - ZEND_TYPE_SET_PTR(*type, ce); } } @@ -1497,9 +1491,12 @@ static void zend_file_cache_unserialize_class(zval *zv, ce = Z_PTR_P(zv); UNSERIALIZE_STR(ce->name); - if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS) - && !script->corrupted) { - zend_accel_get_class_name_map_ptr(ce->name); + if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)) { + if (!script->corrupted) { + zend_accel_get_class_name_map_ptr(ce->name); + } else { + zend_alloc_ce_cache(ce->name); + } } if (ce->parent) { if (!(ce->ce_flags & ZEND_ACC_LINKED)) { diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 52575f6fd3640..98303173f02a8 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -1118,24 +1118,6 @@ void zend_update_parent_ce(zend_class_entry *ce) } } - if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) { - zend_property_info *prop; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - zend_type *single_type; - ZEND_TYPE_FOREACH(prop->type, single_type) { - if (ZEND_TYPE_HAS_CE(*single_type)) { - zend_class_entry *ce = ZEND_TYPE_CE(*single_type); - if (ce->type == ZEND_USER_CLASS) { - ce = zend_shared_alloc_get_xlat_entry(ce); - if (ce) { - ZEND_TYPE_SET_PTR(*single_type, ce); - } - } - } - } ZEND_TYPE_FOREACH_END(); - } ZEND_HASH_FOREACH_END(); - } - /* update methods */ if (ce->constructor) { zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->constructor); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 32e2e41020e46..1fa3de534ea93 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -3061,17 +3061,7 @@ ZEND_METHOD(ReflectionUnionType, getTypes) } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(param->type)) { zend_string *name = ZEND_TYPE_NAME(param->type); - - if (ZSTR_HAS_CE_CACHE(name) && ZSTR_GET_CE_CACHE(name)) { - append_type(return_value, - (zend_type) ZEND_TYPE_INIT_CE(ZSTR_GET_CE_CACHE(name), 0, 0)); - } else { - append_type(return_value, - (zend_type) ZEND_TYPE_INIT_CLASS(name, 0, 0)); - } - } else if (ZEND_TYPE_HAS_CE(param->type)) { - append_type(return_value, - (zend_type) ZEND_TYPE_INIT_CE(ZEND_TYPE_CE(param->type), 0, 0)); + append_type(return_value, (zend_type) ZEND_TYPE_INIT_CLASS(name, 0, 0)); } type_mask = ZEND_TYPE_PURE_MASK(param->type); diff --git a/ext/reflection/tests/intersection_types.phpt b/ext/reflection/tests/intersection_types.phpt index cbd6ae04063f0..4ee3ac6379576 100644 --- a/ext/reflection/tests/intersection_types.phpt +++ b/ext/reflection/tests/intersection_types.phpt @@ -1,9 +1,5 @@ --TEST-- Intersection types in reflection ---SKIPIF-- - --FILE-- --FILE--