From 4740dabb843c6d4f7f866b4a2456073c9eaf4c77 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 Oct 2018 14:12:28 +0300 Subject: [PATCH] Reverted back ce->iterator_funcs_ptr. Initialize ce->iterator_funcs_ptr fields in immutable classes. --- UPGRADING.INTERNALS | 6 +- Zend/zend.h | 2 +- Zend/zend_API.h | 2 +- Zend/zend_compile.c | 2 +- Zend/zend_inheritance.c | 4 +- Zend/zend_interfaces.c | 126 ++++++---------------- Zend/zend_opcode.c | 4 +- ext/opcache/zend_accelerator_util_funcs.c | 5 - ext/opcache/zend_file_cache.c | 39 ++++--- ext/opcache/zend_persist.c | 25 +++-- ext/opcache/zend_persist_calc.c | 7 +- ext/spl/spl_array.c | 25 ++--- ext/spl/spl_fixedarray.c | 24 ++--- ext/spl/spl_iterators.c | 22 ++-- ext/spl/spl_observer.c | 24 ++--- 15 files changed, 125 insertions(+), 192 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 85011cf4c4a..8f4046032b7 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -128,9 +128,9 @@ PHP 7.4 INTERNALS UPGRADE NOTES Few related data structures were changed to allow addressing mutable data structures from immutable ones. This access is implemented through ZEND_MAP_PTR... abstraction macros and, basically, uses additional level of - indirection. op_array->run_time_cache, op_array->static_variables_ptr, - class_entry->static_members_table and class_entry->iterator_funcs_ptr now - have to be accessed through ZEND_MAP_PTR... macros. + indirection. op_array->run_time_cache, op_array->static_variables_ptr and + class_entry->static_members_table now have to be accessed through + ZEND_MAP_PTR... macros. It's also not allowed to change op_array->reserved[] handles of immutable op_arrays. Instead, now you have to reserve op_array handle using zend_get_op_array_extension_handle() during MINIT and access its value diff --git a/Zend/zend.h b/Zend/zend.h index 4e0bb07b000..0d3ce9ffa8e 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -148,7 +148,7 @@ struct _zend_class_entry { zend_function *unserialize_func; /* allocated only if class implements Iterator or IteratorAggregate interface */ - ZEND_MAP_PTR_DEF(zend_class_iterator_funcs *, iterator_funcs_ptr); + zend_class_iterator_funcs *iterator_funcs_ptr; /* handlers */ union { diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 8ba9d737580..d80f5d2f0d5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -219,7 +219,7 @@ typedef struct _zend_fcall_info_cache { class_container.trait_precedences = NULL; \ class_container.interfaces = NULL; \ class_container.get_iterator = NULL; \ - ZEND_MAP_PTR_INIT(class_container.iterator_funcs_ptr, NULL); \ + class_container.iterator_funcs_ptr = NULL; \ class_container.info.internal.module = NULL; \ class_container.info.internal.builtin_functions = functions; \ } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 6861af32a67..c907594fadb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1638,7 +1638,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->__tostring = NULL; ce->create_object = NULL; ce->get_iterator = NULL; - ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, NULL); + ce->iterator_funcs_ptr = NULL; ce->get_static_method = NULL; ce->parent = NULL; ce->parent_name = NULL; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index afc01fc9ab7..ed5a554fb67 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -92,9 +92,9 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */ if (EXPECTED(!ce->get_iterator)) { ce->get_iterator = parent->get_iterator; } - if (ZEND_MAP_PTR(parent->iterator_funcs_ptr)) { + if (parent->iterator_funcs_ptr) { /* Must be initialized through iface->interface_gets_implemented() */ - ZEND_ASSERT(ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr)); + ZEND_ASSERT(ce->iterator_funcs_ptr); } if (EXPECTED(!ce->__get)) { ce->__get = parent->__get; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 906f5840edc..2e7f70c7952 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -119,36 +119,12 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun } /* }}} */ -typedef struct _zend_class_iterator_funcs_ptr { - zend_class_iterator_funcs *ptr; - zend_class_iterator_funcs data; -} zend_class_iterator_funcs_ptr; - /* iterator interface, c-level functions used by engine */ -static zend_never_inline zend_class_iterator_funcs* zend_alloc_iterator_funcs_ptr(zend_class_entry *ce) /* {{{ */ -{ - zend_class_iterator_funcs *ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); - memset(ptr, 0, sizeof(zend_class_iterator_funcs)); - ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, ptr); - return ptr; -} -/* }}} */ - -static zend_always_inline zend_class_iterator_funcs* zend_get_iterator_funcs_ptr(zend_class_entry *ce) /* {{{ */ -{ - if (ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr)) { - return ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr); - } else { - return zend_alloc_iterator_funcs_ptr(ce); - } -} -/* }}} */ /* {{{ zend_user_it_new_iterator */ ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval) { - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); + zend_call_method_with_0_params(object, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); } /* }}} */ @@ -183,10 +159,8 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter) zval *object = &iter->it.data; zval more; int result; - zend_class_entry *ce = iter->ce; - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_valid, "valid", &more); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); result = i_zend_is_true(&more); zval_ptr_dtor(&more); return result ? SUCCESS : FAILURE; @@ -202,10 +176,7 @@ ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter) zval *object = &iter->it.data; if (Z_ISUNDEF(iter->value)) { - zend_class_entry *ce = iter->ce; - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); - - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_current, "current", &iter->value); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value); } return &iter->value; } @@ -217,10 +188,8 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke zend_user_iterator *iter = (zend_user_iterator*)_iter; zval *object = &iter->it.data; zval retval; - zend_class_entry *ce = iter->ce; - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_key, "key", &retval); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval); if (Z_TYPE(retval) != IS_UNDEF) { ZVAL_ZVAL(key, &retval, 1, 1); @@ -239,11 +208,9 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter) { zend_user_iterator *iter = (zend_user_iterator*)_iter; zval *object = &iter->it.data; - zend_class_entry *ce = iter->ce; - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_next, "next", NULL); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); } /* }}} */ @@ -252,11 +219,9 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter) { zend_user_iterator *iter = (zend_user_iterator*)_iter; zval *object = &iter->it.data; - zend_class_entry *ce = iter->ce; - zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce); zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); } /* }}} */ @@ -347,7 +312,6 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr { uint32_t i; int t = -1; - zend_class_iterator_funcs *iterator_funcs_ptr; if (class_type->get_iterator) { if (class_type->type == ZEND_INTERNAL_CLASS) { @@ -376,31 +340,17 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr } } class_type->get_iterator = zend_user_it_get_new_iterator; - if (ZEND_MAP_PTR(class_type->iterator_funcs_ptr)) { - iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr); - ZEND_ASSERT(iterator_funcs_ptr); - if (class_type->type == ZEND_USER_CLASS) { - iterator_funcs_ptr->zf_new_iterator = NULL; - return SUCCESS; - } + if (class_type->iterator_funcs_ptr != NULL) { + class_type->iterator_funcs_ptr->zf_new_iterator = NULL; } else if (class_type->type == ZEND_INTERNAL_CLASS) { - /* We can use pointer even in ZTS mode, because this structure is read-only */ - zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr = - calloc(1, sizeof(zend_class_iterator_funcs_ptr)); - ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr); - iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data; - iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr; + class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); } else { - zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr = - zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs_ptr)); - iterator_funcs_ptr_ptr->ptr = &iterator_funcs_ptr_ptr->data; - ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr); - iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data; - iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr; - memset(iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); - return SUCCESS; + class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); + memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + } + if (class_type->type == ZEND_INTERNAL_CLASS) { + class_type->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1); } - iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1); return SUCCESS; } /* }}} */ @@ -408,8 +358,6 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr /* {{{ zend_implement_iterator */ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type) { - zend_class_iterator_funcs *iterator_funcs_ptr; - if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) { if (class_type->type == ZEND_INTERNAL_CLASS) { /* inheritance ensures the class has the necessary userland methods */ @@ -426,39 +374,25 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry } } class_type->get_iterator = zend_user_it_get_iterator; - if (ZEND_MAP_PTR(class_type->iterator_funcs_ptr)) { - iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr); - ZEND_ASSERT(iterator_funcs_ptr); - if (class_type->type == ZEND_USER_CLASS) { - iterator_funcs_ptr->zf_valid = NULL; - iterator_funcs_ptr->zf_current = NULL; - iterator_funcs_ptr->zf_key = NULL; - iterator_funcs_ptr->zf_next = NULL; - iterator_funcs_ptr->zf_rewind = NULL; - return SUCCESS; - } + if (class_type->iterator_funcs_ptr != NULL) { + class_type->iterator_funcs_ptr->zf_valid = NULL; + class_type->iterator_funcs_ptr->zf_current = NULL; + class_type->iterator_funcs_ptr->zf_key = NULL; + class_type->iterator_funcs_ptr->zf_next = NULL; + class_type->iterator_funcs_ptr->zf_rewind = NULL; } else if (class_type->type == ZEND_INTERNAL_CLASS) { - /* We can use pointer even in ZTS mode, because this structure is read-only */ - zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr = - calloc(1, sizeof(zend_class_iterator_funcs_ptr)); - ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr); - iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data; - iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr; + class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); } else { - zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr = - zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs_ptr)); - iterator_funcs_ptr_ptr->ptr = &iterator_funcs_ptr_ptr->data; - ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr); - iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data; - iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr; - memset(iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); - return SUCCESS; + class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); + memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + } + if (class_type->type == ZEND_INTERNAL_CLASS) { + class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } - iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); return SUCCESS; } /* }}} */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 18ff8872a1d..9d974620ac6 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -347,8 +347,8 @@ ZEND_API void destroy_zend_class(zval *zv) } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->constants_table); } - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - free(ZEND_MAP_PTR(ce->iterator_funcs_ptr)); + if (ce->iterator_funcs_ptr) { + free(ce->iterator_funcs_ptr); } if (ce->num_interfaces > 0) { free(ce->interfaces); diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 66964e2ef72..acec571f4df 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -373,11 +373,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce) ce->trait_precedences = trait_precedences; } } - - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, ARENA_REALLOC(ZEND_MAP_PTR(ce->iterator_funcs_ptr))); - ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, ARENA_REALLOC(ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr))); - } } static void zend_accel_function_hash_copy(HashTable *target, HashTable *source) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 50082931572..fc477e662c1 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -757,14 +757,17 @@ static void zend_file_cache_serialize_class(zval *zv, SERIALIZE_PTR(ce->__callstatic); SERIALIZE_PTR(ce->__debugInfo); - ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { - ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, (void*)(uintptr_t)1); - } else { - SERIALIZE_PTR(ZEND_MAP_PTR(ce->iterator_funcs_ptr)); - } + if (ce->iterator_funcs_ptr) { + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator); + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind); + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid); + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key); + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current); + SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next); + SERIALIZE_PTR(ce->iterator_funcs_ptr); } + + ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); } static void zend_file_cache_serialize(zend_persistent_script *script, @@ -1413,18 +1416,20 @@ static void zend_file_cache_unserialize_class(zval *zv, ce->unserialize = zend_class_unserialize_deny; } - if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { - if (ce->default_static_members_table) { - ZEND_MAP_PTR_NEW(ce->static_members_table); - } else { - ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); - } - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - ZEND_MAP_PTR_NEW(ce->iterator_funcs_ptr); - } + if (ce->iterator_funcs_ptr) { + UNSERIALIZE_PTR(ce->iterator_funcs_ptr); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current); + UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next); + } + + if (ce->ce_flags & ZEND_ACC_IMMUTABLE && ce->default_static_members_table) { + ZEND_MAP_PTR_NEW(ce->static_members_table); } else { ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); - UNSERIALIZE_PTR(ZEND_MAP_PTR(ce->iterator_funcs_ptr)); } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index e325c495bb0..4f59655ffde 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -27,6 +27,7 @@ #include "zend_vm.h" #include "zend_constants.h" #include "zend_operators.h" +#include "zend_interfaces.h" #ifdef HAVE_OPCACHE_FILE_CACHE #define zend_set_str_gc_flags(str) do { \ @@ -905,14 +906,8 @@ static void zend_persist_class_entry(zval *zv) } } - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { - ZEND_MAP_PTR_NEW(ce->iterator_funcs_ptr); - } else { - ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, ZCG(arena_mem)); - ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*))); - ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, zend_shared_memdup_arena(ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr), sizeof(zend_class_iterator_funcs))); - } + if (ce->iterator_funcs_ptr) { + ce->iterator_funcs_ptr = zend_shared_memdup(ce->iterator_funcs_ptr, sizeof(zend_class_iterator_funcs)); } } } @@ -968,6 +963,20 @@ static int zend_update_parent_ce(zval *zv) } } } + + if (ce->iterator_funcs_ptr) { + memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + if (instanceof_function_ex(ce, zend_ce_aggregate, 1)) { + ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1); + } + if (instanceof_function_ex(ce, zend_ce_iterator, 1)) { + ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1); + ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1); + ce->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&ce->function_table, "key", sizeof("key") - 1); + ce->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&ce->function_table, "current", sizeof("current") - 1); + ce->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&ce->function_table, "next", sizeof("next") - 1); + } + } } /* update methods */ diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index e7a4db0d831..86949ddca85 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -431,11 +431,8 @@ static void zend_persist_class_entry_calc(zval *zv) } } - if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) { - if (!ZCG(is_immutable_class)) { - ADD_ARENA_SIZE(sizeof(void*)); - ADD_ARENA_SIZE(sizeof(zend_class_iterator_funcs)); - } + if (ce->iterator_funcs_ptr) { + ADD_SIZE(sizeof(zend_class_iterator_funcs)); } } } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index ba0614cf7a2..04e73bf26e6 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -243,22 +243,19 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval * /* Cache iterator functions if ArrayIterator or derived. Check current's */ /* cache since only current is always required */ if (intern->std.handlers == &spl_handler_ArrayIterator) { - zend_class_iterator_funcs *iterator_funcs_ptr = - ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr); - - if (!iterator_funcs_ptr->zf_current) { - iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + if (!class_type->iterator_funcs_ptr->zf_current) { + class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { - if (iterator_funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; - if (iterator_funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID; - if (iterator_funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY; - if (iterator_funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT; - if (iterator_funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT; + if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; + if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID; + if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY; + if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT; + if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT; } } diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 9b92f885522..392175f781f 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -207,7 +207,6 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z spl_fixedarray_object *intern; zend_class_entry *parent = class_type; int inherited = 0; - zend_class_iterator_funcs *iterator_funcs_ptr; intern = zend_object_alloc(sizeof(spl_fixedarray_object), parent); @@ -239,28 +238,27 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray"); } - iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr); - if (!iterator_funcs_ptr->zf_current) { - iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + if (!class_type->iterator_funcs_ptr->zf_current) { + class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { - if (iterator_funcs_ptr->zf_rewind->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND; } - if (iterator_funcs_ptr->zf_valid->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID; } - if (iterator_funcs_ptr->zf_key->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY; } - if (iterator_funcs_ptr->zf_current->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT; } - if (iterator_funcs_ptr->zf_next->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT; } diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 6cc0bc1d979..40fa9f3f064 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -494,8 +494,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) { if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) { - zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(iterator)->iterator_funcs_ptr); - zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval); + zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval); iterator = &aggregate_retval; } else { Z_ADDREF_P(iterator); @@ -523,8 +522,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|ll", &iterator, &mode, &flags) == SUCCESS) { if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) { - zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(iterator)->iterator_funcs_ptr); - zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval); + zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval); iterator = &aggregate_retval; } else { Z_ADDREF_P(iterator); @@ -1348,6 +1346,19 @@ static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = { PHP_FE_END }; +#if MBO_0 +static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type) +{ + class_type->iterator_funcs_ptr->zf_valid = NULL; + class_type->iterator_funcs_ptr->zf_current = NULL; + class_type->iterator_funcs_ptr->zf_key = NULL; + class_type->iterator_funcs_ptr->zf_next = NULL; + class_type->iterator_funcs_ptr->zf_rewind = NULL; + + return SUCCESS; +} +#endif + static zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key) { zend_function *function_handler; @@ -1500,8 +1511,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z ce = ce_cast; } if (instanceof_function(ce, zend_ce_aggregate)) { - zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr); - zend_call_method_with_0_params(zobject, ce, &iterator_funcs_ptr->zf_new_iterator, "getiterator", &retval); + zend_call_method_with_0_params(zobject, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", &retval); if (EG(exception)) { zval_ptr_dtor(&retval); return NULL; diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index c61f31b4ff4..0dd755e07f7 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1028,11 +1028,8 @@ SPL_METHOD(MultipleIterator, rewind) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { - zend_class_iterator_funcs *iterator_funcs_ptr; - it = &element->obj; - iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr); - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_rewind, "rewind", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1054,11 +1051,8 @@ SPL_METHOD(MultipleIterator, next) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { - zend_class_iterator_funcs *iterator_funcs_ptr; - it = &element->obj; - iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr); - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_next, "next", NULL); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_next, "next", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1087,11 +1081,8 @@ SPL_METHOD(MultipleIterator, valid) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { - zend_class_iterator_funcs *iterator_funcs_ptr; - it = &element->obj; - iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr); - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_valid, "valid", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval); if (!Z_ISUNDEF(retval)) { valid = (Z_TYPE(retval) == IS_TRUE); @@ -1126,11 +1117,8 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { - zend_class_iterator_funcs *iterator_funcs_ptr; - it = &element->obj; - iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr); - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_valid, "valid", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval); if (!Z_ISUNDEF(retval)) { valid = Z_TYPE(retval) == IS_TRUE; @@ -1141,9 +1129,9 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ if (valid) { if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) { - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_current, "current", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_current, "current", &retval); } else { - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_key, "key", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_key, "key", &retval); } if (Z_ISUNDEF(retval)) { zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0);