From: Nikita Popov Date: Thu, 16 Jan 2020 16:04:11 +0000 (+0100) Subject: Use zend_type inside type lists X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd1977282c14c1daa1718a82eb4b3bf79250ca16;p=php Use zend_type inside type lists Instead of having a completely independent encoding for type list entries. This is going to use more memory, but I'm not particularly concerned about that, as type unions that contain multiple classes should be uncommon. On the other hand, this allows us to treat top-level types and types inside lists mostly the same. A new ZEND_TYPE_FOREACH macros allows to transparently treat list and non-list types the same way. I'm not using it everywhere it could be used for now, just the places that seemed most obvious. Of course, this will make any future type system changes much simpler, as it will not be necessary to duplicate all logic two times. --- diff --git a/Zend/zend.c b/Zend/zend.c index 427db2a861..20e7e85acc 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -600,10 +600,10 @@ static void function_copy_ctor(zval *zv) /* {{{ */ memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); ZEND_TYPE_SET_PTR(new_arg_info[i].type, new_list); - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(new_list, entry) { - zend_string *name = zend_string_dup(ZEND_TYPE_LIST_GET_NAME(*entry), 1); - *entry = ZEND_TYPE_LIST_ENCODE_NAME(name); + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(new_list, list_type) { + zend_string *name = zend_string_dup(ZEND_TYPE_NAME(*list_type), 1); + ZEND_TYPE_SET_PTR(*list_type, name); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) { zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); @@ -983,20 +983,14 @@ static void zend_resolve_property_types(void) /* {{{ */ if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) { ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { - if (ZEND_TYPE_HAS_LIST(prop_info->type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop_info->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - zend_string *type_name = ZEND_TYPE_LIST_GET_NAME(*entry); - *entry = ZEND_TYPE_LIST_ENCODE_CE(resolve_type_name(type_name)); - zend_string_release(type_name); - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(prop_info->type)) { - zend_string *type_name = ZEND_TYPE_NAME(prop_info->type); - ZEND_TYPE_SET_CE(prop_info->type, resolve_type_name(type_name)); - zend_string_release(type_name); - } + 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(); } ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 1e092222c5..0f01d1a4e5 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1164,13 +1164,12 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { zend_string *str = NULL; if (ZEND_TYPE_HAS_LIST(type)) { - void *elem; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), elem) { - if (ZEND_TYPE_LIST_IS_CE(elem)) { - str = add_type_string(str, ZEND_TYPE_LIST_GET_CE(elem)->name); + zend_type *list_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); } else { - str = add_type_string(str, - resolve_class_name(ZEND_TYPE_LIST_GET_NAME(elem), scope)); + str = add_type_string(str, resolve_class_name(ZEND_TYPE_NAME(*list_type), scope)); } } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(type)) { @@ -1245,23 +1244,16 @@ static void zend_mark_function_as_generator() /* {{{ */ if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { zend_type return_type = CG(active_op_array)->arg_info[-1].type; - zend_bool valid_type = 0; - if (ZEND_TYPE_HAS_CLASS(return_type)) { - if (ZEND_TYPE_HAS_LIST(return_type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(return_type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); - if (is_generator_compatible_class_type(ZEND_TYPE_LIST_GET_NAME(entry))) { - valid_type = 1; - break; - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else { - ZEND_ASSERT(ZEND_TYPE_HAS_NAME(return_type)); - valid_type = is_generator_compatible_class_type(ZEND_TYPE_NAME(return_type)); - } - } else { - valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_ITERABLE) != 0; + zend_bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_ITERABLE) != 0; + if (!valid_type) { + zend_type *single_type; + ZEND_TYPE_FOREACH(return_type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type) + && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) { + valid_type = 1; + break; + } + } ZEND_TYPE_FOREACH_END(); } if (!valid_type) { @@ -5521,17 +5513,13 @@ static zend_type zend_compile_single_typename(zend_ast *ast) } static zend_bool zend_type_contains_traversable(zend_type type) { - if (ZEND_TYPE_HAS_LIST(type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); - if (zend_string_equals_literal_ci(ZEND_TYPE_LIST_GET_NAME(entry), "Traversable")) { - return 1; - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(type)) { - return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "Traversable"); - } + zend_type *single_type; + ZEND_TYPE_FOREACH(type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type) + && zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) { + return 1; + } + } ZEND_TYPE_FOREACH_END(); return 0; } @@ -5561,6 +5549,7 @@ static zend_type zend_compile_typename( "Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str)); } ZEND_TYPE_FULL_MASK(type) |= ZEND_TYPE_PURE_MASK(single_type); + ZEND_TYPE_FULL_MASK(single_type) &= ~_ZEND_TYPE_MAY_BE_MASK; if (ZEND_TYPE_HAS_CLASS(single_type)) { if (!ZEND_TYPE_HAS_CLASS(type)) { @@ -5580,15 +5569,16 @@ static zend_type zend_compile_typename( } else { list = erealloc(old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types + 1)); } - list->types[list->num_types++] = ZEND_TYPE_NAME(single_type); } else { /* Switch from single name to name list. */ size_t size = ZEND_TYPE_LIST_SIZE(2); list = use_arena ? zend_arena_alloc(&CG(arena), size) : emalloc(size); - list->num_types = 2; - list->types[0] = ZEND_TYPE_NAME(type); - list->types[1] = ZEND_TYPE_NAME(single_type); + list->num_types = 1; + list->types[0] = type; + ZEND_TYPE_FULL_MASK(list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK; } + + list->types[list->num_types++] = single_type; ZEND_TYPE_SET_LIST(type, list); if (use_arena) { ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT; @@ -5597,8 +5587,7 @@ static zend_type zend_compile_typename( /* Check for trivially redundant class types */ for (size_t i = 0; i < list->num_types - 1; i++) { if (zend_string_equals_ci( - ZEND_TYPE_LIST_GET_NAME(list->types[i]), - ZEND_TYPE_NAME(single_type))) { + ZEND_TYPE_NAME(list->types[i]), ZEND_TYPE_NAME(single_type))) { zend_string *single_type_str = zend_type_to_string(single_type); zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str)); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 17de515410..cbd3a06fad 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -941,18 +941,18 @@ static zend_bool zend_check_and_resolve_property_class_type( zend_property_info *info, zend_class_entry *object_ce) { zend_class_entry *ce; if (ZEND_TYPE_HAS_LIST(info->type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(info->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - zend_string *name = ZEND_TYPE_LIST_GET_NAME(*entry); + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) { + 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); - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); + ZEND_TYPE_SET_CE(*list_type, ce); } else { - ce = ZEND_TYPE_LIST_GET_CE(*entry); + ce = ZEND_TYPE_CE(*list_type); } if (instanceof_function(object_ce, ce)) { return 1; @@ -1032,12 +1032,12 @@ static zend_always_inline zend_bool zend_check_type_slow( if (ZEND_TYPE_HAS_CLASS(type) && Z_TYPE_P(arg) == IS_OBJECT) { zend_class_entry *ce; if (ZEND_TYPE_HAS_LIST(type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { if (*cache_slot) { ce = *cache_slot; } else { - ce = zend_fetch_class(ZEND_TYPE_LIST_GET_NAME(entry), + ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); if (!ce) { cache_slot++; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 53494515b6..9a9199a198 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -49,10 +49,10 @@ static void zend_type_copy_ctor(zend_type *type, zend_bool persistent) { memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); ZEND_TYPE_SET_PTR(*type, new_list); - void *entry; - ZEND_TYPE_LIST_FOREACH(new_list, entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); - zend_string_addref(ZEND_TYPE_LIST_GET_NAME(entry)); + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(new_list, list_type) { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); + zend_string_addref(ZEND_TYPE_NAME(*list_type)); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { zend_string_addref(ZEND_TYPE_NAME(*type)); @@ -323,19 +323,13 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce } static zend_bool zend_type_contains_traversable(zend_type type) { - if (ZEND_TYPE_HAS_LIST(type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); - if (zend_string_equals_literal_ci(ZEND_TYPE_LIST_GET_NAME(entry), "Traversable")) { - return 1; - } - } ZEND_TYPE_LIST_FOREACH_END(); - return 0; - } - if (ZEND_TYPE_HAS_NAME(type)) { - return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "Traversable"); - } + zend_type *single_type; + ZEND_TYPE_FOREACH(type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type) + && zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) { + return 1; + } + } ZEND_TYPE_FOREACH_END(); return 0; } @@ -373,33 +367,18 @@ static inheritance_status zend_perform_covariant_class_type_check( return INHERITANCE_SUCCESS; } } - if (ZEND_TYPE_HAS_NAME(proto_type)) { - zend_string *proto_class_name = resolve_class_name(proto_scope, ZEND_TYPE_NAME(proto_type)); - if (zend_string_equals_ci(fe_class_name, proto_class_name)) { - return INHERITANCE_SUCCESS; - } - /* Make sure to always load both classes, to avoid only registering one of them as - * a delayed autoload. */ - if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); - zend_class_entry *proto_ce = - lookup_class(proto_scope, proto_class_name, register_unresolved); - if (!fe_ce || !proto_ce) { - have_unresolved = 1; - } else if (unlinked_instanceof(fe_ce, proto_ce)) { - return INHERITANCE_SUCCESS; - } - } - if (ZEND_TYPE_HAS_LIST(proto_type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(proto_type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + zend_type *single_type; + ZEND_TYPE_FOREACH(proto_type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *proto_class_name = - resolve_class_name(proto_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type)); if (zend_string_equals_ci(fe_class_name, proto_class_name)) { return INHERITANCE_SUCCESS; } + /* Make sure to always load both classes, to avoid only registering one of them as + * a delayed autoload. */ if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); zend_class_entry *proto_ce = lookup_class(proto_scope, proto_class_name, register_unresolved); @@ -408,8 +387,9 @@ static inheritance_status zend_perform_covariant_class_type_check( } else if (unlinked_instanceof(fe_ce, proto_ce)) { return INHERITANCE_SUCCESS; } - } ZEND_TYPE_LIST_FOREACH_END(); - } + } + } ZEND_TYPE_FOREACH_END(); + return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR; } @@ -452,14 +432,14 @@ static inheritance_status zend_perform_covariant_type_check( } if (ZEND_TYPE_HAS_LIST(fe_type)) { - void *entry; + zend_type *list_type; zend_bool all_success = 1; /* First try to check whether we can succeed without resolving anything */ - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), list_type) { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); zend_string *fe_class_name = - resolve_class_name(fe_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + resolve_class_name(fe_scope, ZEND_TYPE_NAME(*list_type)); inheritance_status status = zend_perform_covariant_class_type_check( fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 0); if (status == INHERITANCE_ERROR) { @@ -477,10 +457,10 @@ static inheritance_status zend_perform_covariant_type_check( } /* Register all classes that may have to be resolved */ - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), list_type) { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); zend_string *fe_class_name = - resolve_class_name(fe_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + resolve_class_name(fe_scope, ZEND_TYPE_NAME(*list_type)); zend_perform_covariant_class_type_check( fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 1); } ZEND_TYPE_LIST_FOREACH_END(); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index e197e9bf16..b7423de45b 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -104,10 +104,10 @@ ZEND_API void destroy_zend_function(zend_function *function) ZEND_API void zend_type_release(zend_type type, zend_bool persistent) { if (ZEND_TYPE_HAS_LIST(type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(entry)) { - zend_string_release(ZEND_TYPE_LIST_GET_NAME(entry)); + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { + if (ZEND_TYPE_HAS_NAME(*list_type)) { + zend_string_release(ZEND_TYPE_NAME(*list_type)); } } ZEND_TYPE_LIST_FOREACH_END(); if (!ZEND_TYPE_USES_ARENA(type)) { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 2df97fcd3f..b9f09ffede 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -131,8 +131,8 @@ typedef struct { } zend_type; typedef struct { - size_t num_types; - void *types[1]; + uint32_t num_types; + zend_type types[1]; } zend_type_list; #define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24 @@ -182,45 +182,39 @@ typedef struct { #define ZEND_TYPE_LIST(t) \ ((zend_type_list *) (t).ptr) -/* Type lists use the low bit to distinguish NAME and CE entries, - * both of which may exist in the same list. */ -#define ZEND_TYPE_LIST_IS_CE(entry) \ - (((uintptr_t) (entry)) & 1) - -#define ZEND_TYPE_LIST_IS_NAME(entry) \ - !ZEND_TYPE_LIST_IS_CE(entry) - -#define ZEND_TYPE_LIST_GET_NAME(entry) \ - ((zend_string *) (entry)) - -#define ZEND_TYPE_LIST_GET_CE(entry) \ - ((zend_class_entry *) ((uintptr_t) (entry) & ~1)) - -#define ZEND_TYPE_LIST_ENCODE_NAME(name) \ - ((void *) (name)) - -#define ZEND_TYPE_LIST_ENCODE_CE(ce) \ - ((void *) (((uintptr_t) ce) | 1)) - #define ZEND_TYPE_LIST_SIZE(num_types) \ - (sizeof(zend_type_list) + ((num_types) - 1) * sizeof(void *)) + (sizeof(zend_type_list) + ((num_types) - 1) * sizeof(zend_type)) -#define ZEND_TYPE_LIST_FOREACH_PTR(list, entry_ptr) do { \ - void **_list = (list)->types; \ - void **_end = _list + (list)->num_types; \ +/* This iterates over a zend_type_list. */ +#define ZEND_TYPE_LIST_FOREACH(list, type_ptr) do { \ + zend_type *_list = (list)->types; \ + zend_type *_end = _list + (list)->num_types; \ for (; _list < _end; _list++) { \ - entry_ptr = _list; - -#define ZEND_TYPE_LIST_FOREACH(list, entry) do { \ - void **_list = (list)->types; \ - void **_end = _list + (list)->num_types; \ - for (; _list < _end; _list++) { \ - entry = *_list; + type_ptr = _list; #define ZEND_TYPE_LIST_FOREACH_END() \ } \ } while (0) +/* This iterates over any zend_type. If it's a type list, all list elements will + * be visited. If it's a single type, only the single type is visited. */ +#define ZEND_TYPE_FOREACH(type, type_ptr) do { \ + zend_type *_cur, *_end; \ + if (ZEND_TYPE_HAS_LIST(type)) { \ + zend_type_list *_list = ZEND_TYPE_LIST(type); \ + _cur = _list->types; \ + _end = _cur + _list->num_types; \ + } else { \ + _cur = &(type); \ + _end = _cur + 1; \ + } \ + do { \ + type_ptr = _cur; + +#define ZEND_TYPE_FOREACH_END() \ + } while (++_cur < _end); \ +} while (0) + #define ZEND_TYPE_SET_PTR(t, _ptr) \ ((t).ptr = (_ptr)) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0e62f37659..c2c81ba8a6 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -602,16 +602,13 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int num_args++; } for (i = 0 ; i < num_args; i++) { - if (ZEND_TYPE_HAS_LIST(arg_info[i].type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(arg_info[i].type), entry) { - ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(*entry)); - *entry = zend_new_interned_string(ZEND_TYPE_LIST_GET_NAME(*entry)); - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) { - ZEND_TYPE_SET_PTR(arg_info[i].type, - new_interned_string(ZEND_TYPE_NAME(arg_info[i].type))); - } + zend_type *single_type; + ZEND_TYPE_FOREACH(arg_info[i].type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + ZEND_TYPE_SET_PTR(*single_type, + new_interned_string(ZEND_TYPE_NAME(*single_type))); + } + } ZEND_TYPE_FOREACH_END(); } } } ZEND_HASH_FOREACH_END(); @@ -3581,31 +3578,18 @@ static zend_class_entry *preload_fetch_resolved_ce(zend_string *name, zend_class static zend_bool preload_try_resolve_property_types(zend_class_entry *ce) { zend_bool ok = 1; - zend_property_info *prop; - zend_class_entry *p; - if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) { + zend_property_info *prop; ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - if (ZEND_TYPE_HAS_LIST(prop->type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - p = preload_fetch_resolved_ce(ZEND_TYPE_LIST_GET_NAME(*entry), ce); - if (!p) { - ok = 0; - continue; - } - *entry = ZEND_TYPE_LIST_ENCODE_CE(p); - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(prop->type)) { - p = preload_fetch_resolved_ce(ZEND_TYPE_NAME(prop->type), ce); + zend_type *single_type; + ZEND_TYPE_FOREACH(prop->type, single_type) { + zend_class_entry *p = preload_fetch_resolved_ce(ZEND_TYPE_NAME(*single_type), ce); if (!p) { ok = 0; continue; } - ZEND_TYPE_SET_CE(prop->type, p); - } + ZEND_TYPE_SET_CE(*single_type, p); + } ZEND_TYPE_FOREACH_END(); } ZEND_HASH_FOREACH_END(); } @@ -3625,19 +3609,15 @@ static zend_bool preload_is_class_type_known(zend_class_entry *ce, zend_string * return known; } -static zend_bool preload_is_type_known(zend_class_entry *ce, zend_type type) { - if (ZEND_TYPE_HAS_LIST(type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(entry) - && !preload_is_class_type_known(ce, ZEND_TYPE_LIST_GET_NAME(entry))) { +static zend_bool preload_is_type_known(zend_class_entry *ce, zend_type *type) { + zend_type *single_type; + ZEND_TYPE_FOREACH(*type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + if (!preload_is_class_type_known(ce, ZEND_TYPE_NAME(*single_type))) { return 0; } - } ZEND_TYPE_LIST_FOREACH_END(); - } - if (ZEND_TYPE_HAS_NAME(type)) { - return preload_is_class_type_known(ce, ZEND_TYPE_NAME(type)); - } + } + } ZEND_TYPE_FOREACH_END(); return 1; } @@ -3685,13 +3665,13 @@ static zend_bool preload_needed_types_known(zend_class_entry *ce) { ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, lcname, fptr) { uint32_t i; if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - if (!preload_is_type_known(ce, fptr->common.arg_info[-1].type) && + if (!preload_is_type_known(ce, &fptr->common.arg_info[-1].type) && preload_is_method_maybe_override(ce, lcname)) { return 0; } } for (i = 0; i < fptr->common.num_args; i++) { - if (!preload_is_type_known(ce, fptr->common.arg_info[i].type) && + if (!preload_is_type_known(ce, &fptr->common.arg_info[i].type) && preload_is_method_maybe_override(ce, lcname)) { return 0; } @@ -3979,20 +3959,14 @@ static void preload_ensure_classes_loadable() { if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) { zend_property_info *prop; ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - if (ZEND_TYPE_HAS_LIST(prop->type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - zend_class_entry *ce = preload_load_prop_type( - prop, ZEND_TYPE_LIST_GET_NAME(*entry)); - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(prop->type)) { - zend_class_entry *ce = - preload_load_prop_type(prop, ZEND_TYPE_NAME(prop->type)); - ZEND_TYPE_SET_CE(prop->type, ce); - } + zend_type *single_type; + ZEND_TYPE_FOREACH(prop->type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + zend_class_entry *ce = preload_load_prop_type( + prop, ZEND_TYPE_NAME(*single_type)); + ZEND_TYPE_SET_CE(*single_type, ce); + } + } ZEND_TYPE_FOREACH_END(); } ZEND_HASH_FOREACH_END(); } ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED; diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index c04985110c..38294d5c27 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1148,12 +1148,12 @@ static void ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, const zend_op_arra if (ZEND_TYPE_HAS_CLASS(arg_info->type) && Z_TYPE_P(arg) == IS_OBJECT) { zend_class_entry *ce; if (ZEND_TYPE_HAS_LIST(arg_info->type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), entry) { + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) { if (*cache_slot) { ce = *cache_slot; } else { - ce = zend_fetch_class(ZEND_TYPE_LIST_GET_NAME(entry), + ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); if (!ce) { cache_slot++; diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 6c54d4231c..131fc8495b 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -239,13 +239,13 @@ static void zend_hash_clone_prop_info(HashTable *ht) list = ARENA_REALLOC(list); ZEND_TYPE_SET_PTR(prop_info->type, list); - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop_info->type), entry) { - if (ZEND_TYPE_LIST_IS_CE(*entry)) { - zend_class_entry *ce = ZEND_TYPE_LIST_GET_CE(*entry); + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(prop_info->type), list_type) { + if (ZEND_TYPE_HAS_CE(*list_type)) { + zend_class_entry *ce = ZEND_TYPE_CE(*list_type); if (IN_ARENA(ce)) { ce = ARENA_REALLOC(ce); - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); + ZEND_TYPE_SET_PTR(*list_type, ce); } } } ZEND_TYPE_LIST_FOREACH_END(); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index d5d0cb4466..eb74187e5d 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -380,17 +380,9 @@ static void zend_file_cache_serialize_type( ZEND_TYPE_SET_PTR(*type, list); UNSERIALIZE_PTR(list); - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(list, entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - zend_string *name = ZEND_TYPE_LIST_GET_NAME(*entry); - SERIALIZE_STR(name); - *entry = ZEND_TYPE_LIST_ENCODE_NAME(name); - } else { - zend_class_entry *ce = ZEND_TYPE_LIST_GET_CE(*entry); - SERIALIZE_PTR(ce); - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); - } + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(list, list_type) { + zend_file_cache_serialize_type(list_type, script, info, buf); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { zend_string *type_name = ZEND_TYPE_NAME(*type); @@ -1108,17 +1100,9 @@ static void zend_file_cache_unserialize_type( UNSERIALIZE_PTR(list); ZEND_TYPE_SET_PTR(*type, list); - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(list, entry) { - if (ZEND_TYPE_LIST_IS_NAME(*entry)) { - zend_string *name = ZEND_TYPE_LIST_GET_NAME(*entry); - UNSERIALIZE_STR(name); - *entry = ZEND_TYPE_LIST_ENCODE_NAME(name); - } else { - zend_class_entry *ce = ZEND_TYPE_LIST_GET_CE(*entry); - UNSERIALIZE_PTR(ce); - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); - } + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(list, list_type) { + zend_file_cache_unserialize_type(list_type, script, buf); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { zend_string *type_name = ZEND_TYPE_NAME(*type); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index cbf91144f3..1bcec7caf0 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -260,7 +260,7 @@ static void zend_persist_zval(zval *z) static void zend_persist_type(zend_type *type) { if (ZEND_TYPE_HAS_LIST(*type)) { - void **entry; + zend_type *list_type; zend_type_list *list = ZEND_TYPE_LIST(*type); if (ZEND_TYPE_USES_ARENA(*type)) { if (!ZCG(is_immutable_class)) { @@ -275,10 +275,10 @@ static void zend_persist_type(zend_type *type) { } ZEND_TYPE_SET_PTR(*type, list); - ZEND_TYPE_LIST_FOREACH_PTR(list, entry) { - zend_string *type_name = ZEND_TYPE_LIST_GET_NAME(*entry); + ZEND_TYPE_LIST_FOREACH(list, list_type) { + zend_string *type_name = ZEND_TYPE_NAME(*list_type); zend_accel_store_interned_string(type_name); - *entry = ZEND_TYPE_LIST_ENCODE_NAME(type_name); + ZEND_TYPE_SET_PTR(*list_type, type_name); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { zend_string *type_name = ZEND_TYPE_NAME(*type); @@ -963,28 +963,18 @@ static 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) { - if (ZEND_TYPE_HAS_LIST(prop->type)) { - void **entry; - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop->type), entry) { - if (ZEND_TYPE_LIST_IS_CE(*entry)) { - zend_class_entry *ce = ZEND_TYPE_LIST_GET_CE(*entry); - if (ce->type == ZEND_USER_CLASS) { - ce = zend_shared_alloc_get_xlat_entry(ce); - if (ce) { - *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); - } + 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_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_CE(prop->type)) { - zend_class_entry *ce = ZEND_TYPE_CE(prop->type); - if (ce->type == ZEND_USER_CLASS) { - ce = zend_shared_alloc_get_xlat_entry(ce); - if (ce) { - ZEND_TYPE_SET_PTR(prop->type, ce); - } } - } + } ZEND_TYPE_FOREACH_END(); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 830a5dd8b0..293af3b3e6 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -151,16 +151,16 @@ static void zend_persist_zval_calc(zval *z) static void zend_persist_type_calc(zend_type *type) { if (ZEND_TYPE_HAS_LIST(*type)) { - void **entry; + zend_type *list_type; if (ZEND_TYPE_USES_ARENA(*type) && !ZCG(is_immutable_class)) { ADD_ARENA_SIZE(ZEND_TYPE_LIST_SIZE(ZEND_TYPE_LIST(*type)->num_types)); } else { ADD_SIZE(ZEND_TYPE_LIST_SIZE(ZEND_TYPE_LIST(*type)->num_types)); } - ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(*type), entry) { - zend_string *type_name = ZEND_TYPE_LIST_GET_NAME(*entry); + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { + zend_string *type_name = ZEND_TYPE_NAME(*list_type); ADD_INTERNED_STRING(type_name); - *entry = ZEND_TYPE_LIST_ENCODE_NAME(type_name); + ZEND_TYPE_SET_PTR(*list_type, type_name); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { zend_string *type_name = ZEND_TYPE_NAME(*type); @@ -349,16 +349,12 @@ static void check_property_type_resolution(zend_class_entry *ce) { if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) { ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - if (ZEND_TYPE_HAS_LIST(prop->type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(prop->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(entry)) { - return; - } - } ZEND_TYPE_LIST_FOREACH_END(); - } else if (ZEND_TYPE_HAS_NAME(prop->type)) { - return; - } + zend_type *single_type; + ZEND_TYPE_FOREACH(prop->type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + return; + } + } ZEND_TYPE_FOREACH_END(); } ZEND_HASH_FOREACH_END(); } ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 73ab2b8969..b240d233f7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2938,15 +2938,9 @@ ZEND_METHOD(reflection_union_type, getTypes) array_init(return_value); if (ZEND_TYPE_HAS_LIST(param->type)) { - void *entry; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), entry) { - if (ZEND_TYPE_LIST_IS_NAME(entry)) { - append_type(return_value, - (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_LIST_GET_NAME(entry), 0, 0)); - } else { - append_type(return_value, - (zend_type) ZEND_TYPE_INIT_CE(ZEND_TYPE_LIST_GET_CE(entry), 0, 0)); - } + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), list_type) { + append_type(return_value, *list_type); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(param->type)) { append_type(return_value, diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 48b8ffe564..dc8a44cd95 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -270,8 +270,8 @@ PHP_MINIT_FUNCTION(zend_test) zend_string *class_name2 = zend_string_init("Iterator", sizeof("Iterator") - 1, 1); zend_type_list *type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); type_list->num_types = 2; - type_list->types[0] = ZEND_TYPE_LIST_ENCODE_NAME(class_name1); - type_list->types[1] = ZEND_TYPE_LIST_ENCODE_NAME(class_name2); + type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name1, 0, 0); + type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name2, 0, 0); zend_type type = ZEND_TYPE_INIT_PTR(type_list, _ZEND_TYPE_LIST_BIT, 1, 0); zval val; ZVAL_NULL(&val);