From: Dmitry Stogov Date: Thu, 12 Jul 2018 11:04:14 +0000 (+0300) Subject: Improved user iterator implementation to reduce zend_class_entry memory consumption... X-Git-Tag: php-7.3.0alpha4~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7d4e18b05dc962e923236a8d3df81fb0b10b113d;p=php Improved user iterator implementation to reduce zend_class_entry memory consumption and avoid race condition during resolving/caching of user iterator functions of internal classes in ZTS build. --- diff --git a/Zend/zend.h b/Zend/zend.h index 4a4e38d9c2..4f33dd89cc 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -139,7 +139,8 @@ struct _zend_class_entry { union _zend_function *serialize_func; union _zend_function *unserialize_func; - zend_class_iterator_funcs iterator_funcs; + /* allocated only if class implements Itetrator or IteratorAggregate interface */ + zend_class_iterator_funcs *iterator_funcs_ptr; /* handlers */ zend_object* (*create_object)(zend_class_entry *class_type); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index ac589d48e9..d450c4dd21 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -189,8 +189,9 @@ typedef struct _zend_fcall_info_cache { #define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) \ { \ + memset(&class_container, 0, sizeof(zend_class_entry)); \ class_container.name = zend_string_init_interned(class_name, class_name_len, 1); \ - INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions) \ + class_container.info.internal.builtin_functions = functions; \ } #define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions) \ @@ -221,7 +222,7 @@ typedef struct _zend_fcall_info_cache { class_container.trait_precedences = NULL; \ class_container.interfaces = NULL; \ class_container.get_iterator = NULL; \ - class_container.iterator_funcs.funcs = 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 afb5f6ea17..e0a7acf12a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1750,7 +1750,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; - ce->iterator_funcs.funcs = NULL; + ce->iterator_funcs_ptr = NULL; ce->interface_gets_implemented = NULL; ce->get_static_method = NULL; ce->parent = NULL; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index c532dfe845..2b0b9609f5 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -1196,7 +1196,6 @@ void zend_register_generator_ce(void) /* {{{ */ /* get_iterator has to be assigned *after* implementing the inferface */ zend_class_implements(zend_ce_generator, 1, zend_ce_iterator); zend_ce_generator->get_iterator = zend_generator_get_iterator; - zend_ce_generator->iterator_funcs.funcs = &zend_generator_iterator_functions; memcpy(&zend_generator_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_generator_handlers.free_obj = zend_generator_free_storage; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9d7fb939d6..dc55410b66 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -99,8 +99,23 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */ if (EXPECTED(!ce->get_iterator)) { ce->get_iterator = ce->parent->get_iterator; } - if (EXPECTED(!ce->iterator_funcs.funcs)) { - ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs; + if (EXPECTED(!ce->iterator_funcs_ptr) && UNEXPECTED(ce->parent->iterator_funcs_ptr)) { + if (ce->type == ZEND_INTERNAL_CLASS) { + ce->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); + if (ce->parent->iterator_funcs_ptr->zf_new_iterator) { + ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1); + } + if (ce->parent->iterator_funcs_ptr->zf_current) { + 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); + } + } else { + ce->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); + memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + } } if (EXPECTED(!ce->__get)) { ce->__get = ce->parent->__get; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 11cab80633..6bdf432707 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -126,7 +126,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun /* {{{ zend_user_it_new_iterator */ ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval) { - zend_call_method_with_0_params(object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", retval); + zend_call_method_with_0_params(object, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); } /* }}} */ @@ -162,7 +162,7 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter) zval more; int result; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); if (Z_TYPE(more) != IS_UNDEF) { result = i_zend_is_true(&more); zval_ptr_dtor(&more); @@ -180,7 +180,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_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.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; } @@ -193,7 +193,7 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke zval *object = &iter->it.data; zval retval; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.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); @@ -214,7 +214,7 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); } /* }}} */ @@ -225,7 +225,7 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); } /* }}} */ @@ -254,7 +254,7 @@ static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zva zend_iterator_init((zend_object_iterator*)iterator); ZVAL_COPY(&iterator->it.data, object); - iterator->it.funcs = ce->iterator_funcs.funcs; + iterator->it.funcs = &zend_interface_iterator_funcs_iterator; iterator->ce = Z_OBJCE_P(object); ZVAL_UNDEF(&iterator->value); return (zend_object_iterator*)iterator; @@ -339,8 +339,18 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr } } } - class_type->iterator_funcs.zf_new_iterator = NULL; class_type->get_iterator = zend_user_it_get_new_iterator; + if (class_type->iterator_funcs_ptr != NULL) { + class_type->iterator_funcs_ptr->zf_new_iterator = NULL; + } else if (class_type->type == ZEND_INTERNAL_CLASS) { + class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); + } else { + 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); + } return SUCCESS; } /* }}} */ @@ -364,13 +374,24 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry } } class_type->get_iterator = zend_user_it_get_iterator; - class_type->iterator_funcs.zf_valid = NULL; - class_type->iterator_funcs.zf_current = NULL; - class_type->iterator_funcs.zf_key = NULL; - class_type->iterator_funcs.zf_next = NULL; - class_type->iterator_funcs.zf_rewind = NULL; - if (!class_type->iterator_funcs.funcs) { - class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator; + 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) { + class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); + } else { + 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); } return SUCCESS; } diff --git a/Zend/zend_iterators.h b/Zend/zend_iterators.h index f875e6b0d6..ed46ed9c1a 100644 --- a/Zend/zend_iterators.h +++ b/Zend/zend_iterators.h @@ -62,7 +62,6 @@ struct _zend_object_iterator { }; typedef struct _zend_class_iterator_funcs { - const zend_object_iterator_funcs *funcs; union _zend_function *zf_new_iterator; union _zend_function *zf_valid; union _zend_function *zf_current; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ce0cd2d4a5..1878a95466 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -318,6 +318,9 @@ ZEND_API void destroy_zend_class(zval *zv) } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->constants_table); } + if (ce->iterator_funcs_ptr) { + free(ce->iterator_funcs_ptr); + } if (ce->num_interfaces > 0) { free(ce->interfaces); } diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 143faaf1c4..e86b3bd651 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2186,7 +2186,6 @@ static void date_register_classes(void) /* {{{ */ ce_period.create_object = date_object_new_period; date_ce_period = zend_register_internal_class_ex(&ce_period, NULL); date_ce_period->get_iterator = date_object_period_get_iterator; - date_ce_period->iterator_funcs.funcs = &date_period_it_funcs; zend_class_implements(date_ce_period, 1, zend_ce_traversable); memcpy(&date_object_handlers_period, &std_object_handlers, sizeof(zend_object_handlers)); date_object_handlers_period.offset = XtOffsetOf(php_period_obj, std); diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 06a170b306..6cc724f42e 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -655,7 +655,6 @@ PHP_MINIT_FUNCTION(mysqli) zend_declare_property_null(ce, "num_rows", sizeof("num_rows") - 1, ZEND_ACC_PUBLIC); zend_declare_property_null(ce, "type", sizeof("type") - 1, ZEND_ACC_PUBLIC); mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator; - mysqli_result_class_entry->iterator_funcs.funcs = &php_mysqli_result_iterator_funcs; zend_class_implements(mysqli_result_class_entry, 1, zend_ce_traversable); zend_hash_add_ptr(&classes, ce->name, &mysqli_result_properties); diff --git a/ext/simplexml/php_simplexml_exports.h b/ext/simplexml/php_simplexml_exports.h index 1de8fd9c4a..461d909220 100644 --- a/ext/simplexml/php_simplexml_exports.h +++ b/ext/simplexml/php_simplexml_exports.h @@ -53,6 +53,9 @@ typedef struct { php_sxe_object *sxe; } php_sxe_iterator; +PHP_SXE_API void php_sxe_rewind_iterator(php_sxe_object *sxe); +PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe); + #endif /* PHP_SIMPLEXML_EXPORTS_H */ /** diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 4ff82631e7..1abf68fcc5 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2477,6 +2477,12 @@ static void php_sxe_iterator_move_forward(zend_object_iterator *iter) /* {{{ */ } /* }}} */ +PHP_SXE_API void php_sxe_rewind_iterator(php_sxe_object *sxe) /* {{{ */ +{ + php_sxe_reset_iterator(sxe, 1); +} +/* }}} */ + static void php_sxe_iterator_rewind(zend_object_iterator *iter) /* {{{ */ { php_sxe_object *sxe; @@ -2680,7 +2686,6 @@ PHP_MINIT_FUNCTION(simplexml) sxe.create_object = sxe_object_new; sxe_class_entry = zend_register_internal_class(&sxe); sxe_class_entry->get_iterator = php_sxe_get_iterator; - sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs; zend_class_implements(sxe_class_entry, 1, zend_ce_traversable); memcpy(&sxe_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/simplexml/sxe.c b/ext/simplexml/sxe.c index f502d87926..11658bdd4d 100644 --- a/ext/simplexml/sxe.c +++ b/ext/simplexml/sxe.c @@ -41,14 +41,11 @@ PHP_SXE_API zend_class_entry *ce_SimpleXMLElement; Rewind to first element */ PHP_METHOD(ce_SimpleXMLIterator, rewind) { - php_sxe_iterator iter; - if (zend_parse_parameters_none() == FAILURE) { return; } - iter.sxe = Z_SXEOBJ_P(getThis()); - ce_SimpleXMLElement->iterator_funcs.funcs->rewind((zend_object_iterator*)&iter); + php_sxe_rewind_iterator(Z_SXEOBJ_P(getThis())); } /* }}} */ @@ -116,14 +113,11 @@ PHP_METHOD(ce_SimpleXMLIterator, key) Move to next element */ PHP_METHOD(ce_SimpleXMLIterator, next) { - php_sxe_iterator iter; - if (zend_parse_parameters_none() == FAILURE) { return; } - iter.sxe = Z_SXEOBJ_P(getThis()); - ce_SimpleXMLElement->iterator_funcs.funcs->move_forward((zend_object_iterator*)&iter); + php_sxe_move_forward_iterator(Z_SXEOBJ_P(getThis())); } /* }}} */ diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 0ed5c55687..59ae0b8c89 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -245,19 +245,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) { - if (!class_type->iterator_funcs.zf_current) { - class_type->iterator_funcs.zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - class_type->iterator_funcs.zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - class_type->iterator_funcs.zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - class_type->iterator_funcs.zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - class_type->iterator_funcs.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 (class_type->iterator_funcs.zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; - if (class_type->iterator_funcs.zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID; - if (class_type->iterator_funcs.zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY; - if (class_type->iterator_funcs.zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT; - if (class_type->iterator_funcs.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 e906c233eb..f738b9b059 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -240,27 +240,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"); } - if (!class_type->iterator_funcs.zf_current) { - class_type->iterator_funcs.zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - class_type->iterator_funcs.zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - class_type->iterator_funcs.zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - class_type->iterator_funcs.zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - class_type->iterator_funcs.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 (class_type->iterator_funcs.zf_rewind->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND; } - if (class_type->iterator_funcs.zf_valid->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID; } - if (class_type->iterator_funcs.zf_key->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY; } - if (class_type->iterator_funcs.zf_current->common.scope != parent) { + if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT; } - if (class_type->iterator_funcs.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 c9f88ad6d9..3361fc9c73 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -443,6 +443,16 @@ static void spl_recursive_it_rewind(zend_object_iterator *iter) spl_recursive_it_rewind_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data); } +static const zend_object_iterator_funcs spl_recursive_it_iterator_funcs = { + spl_recursive_it_dtor, + spl_recursive_it_valid, + spl_recursive_it_get_current_data, + spl_recursive_it_get_current_key, + spl_recursive_it_move_forward, + spl_recursive_it_rewind, + NULL +}; + static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref) { spl_recursive_it_iterator *iterator; @@ -462,20 +472,10 @@ static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zend_iterator_init((zend_object_iterator*)iterator); ZVAL_COPY(&iterator->intern.data, zobject); - iterator->intern.funcs = ce->iterator_funcs.funcs; + iterator->intern.funcs = &spl_recursive_it_iterator_funcs; return (zend_object_iterator*)iterator; } -static const zend_object_iterator_funcs spl_recursive_it_iterator_funcs = { - spl_recursive_it_dtor, - spl_recursive_it_valid, - spl_recursive_it_get_current_data, - spl_recursive_it_get_current_key, - spl_recursive_it_move_forward, - spl_recursive_it_rewind, - NULL -}; - static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type) { zval *object = getThis(); @@ -496,7 +496,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_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs.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); @@ -524,7 +524,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_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs.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); @@ -1353,14 +1353,11 @@ static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = { #if MBO_0 static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type) { - class_type->iterator_funcs.zf_valid = NULL; - class_type->iterator_funcs.zf_current = NULL; - class_type->iterator_funcs.zf_key = NULL; - class_type->iterator_funcs.zf_next = NULL; - class_type->iterator_funcs.zf_rewind = NULL; - if (!class_type->iterator_funcs.funcs) { - class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator; - } + 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; } @@ -1518,7 +1515,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_call_method_with_0_params(zobject, ce, &ce->iterator_funcs.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; @@ -3712,7 +3709,6 @@ PHP_MINIT_FUNCTION(spl_iterators) spl_handlers_dual_it.free_obj = spl_dual_it_free_storage; spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator; - spl_ce_RecursiveIteratorIterator->iterator_funcs.funcs = &spl_recursive_it_iterator_funcs; REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "LEAVES_ONLY", RIT_LEAVES_ONLY); REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "SELF_FIRST", RIT_SELF_FIRST); diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index dde06d288b..0d99f066fc 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1031,7 +1031,7 @@ 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)) { it = &element->obj; - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.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,7 +1054,7 @@ 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)) { it = &element->obj; - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.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); } } @@ -1084,7 +1084,7 @@ 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)) { it = &element->obj; - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.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); @@ -1120,7 +1120,7 @@ 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)) { it = &element->obj; - zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.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; @@ -1131,9 +1131,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), &Z_OBJCE_P(it)->iterator_funcs.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), &Z_OBJCE_P(it)->iterator_funcs.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);