]> granicus.if.org Git - php/commitdiff
Improved user iterator implementation to reduce zend_class_entry memory consumption...
authorDmitry Stogov <dmitry@zend.com>
Thu, 12 Jul 2018 11:04:14 +0000 (14:04 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 12 Jul 2018 11:04:14 +0000 (14:04 +0300)
17 files changed:
Zend/zend.h
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_generators.c
Zend/zend_inheritance.c
Zend/zend_interfaces.c
Zend/zend_iterators.h
Zend/zend_opcode.c
ext/date/php_date.c
ext/mysqli/mysqli.c
ext/simplexml/php_simplexml_exports.h
ext/simplexml/simplexml.c
ext/simplexml/sxe.c
ext/spl/spl_array.c
ext/spl/spl_fixedarray.c
ext/spl/spl_iterators.c
ext/spl/spl_observer.c

index 4a4e38d9c2a75a530a69ae3e68363cbdf5feab88..4f33dd89cca25f91207c1bd1be71ca50d3d56772 100644 (file)
@@ -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);
index ac589d48e9527b18e779a203b1cb923da558ae68..d450c4dd21a744c3b15251dcec88f446e2960413 100644 (file)
@@ -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;    \
        }
index afb5f6ea17ca6022df5f5066db9fc1faa955cd21..e0a7acf12a714a500be00310e7fc173fec0c1521 100644 (file)
@@ -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;
index c532dfe8459d84a80391110aeca9f7f22049fb08..2b0b9609f52a6331805df0211a69d478258ae30f 100644 (file)
@@ -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;
index 9d7fb939d64174a045e243acc85f050fc08fa29d..dc55410b66439f8a2444e6faff5eda7dfd7a1ea8 100644 (file)
@@ -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;
index 11cab8063392646bc544afb6f89c18e09bc754bc..6bdf432707922fbf31fe3d72f3182fd518e95c96 100644 (file)
@@ -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;
 }
index f875e6b0d61a1d78aa61484119770a3975d250a8..ed46ed9c1aef7465bcb8e422dcf06457416a800d 100644 (file)
@@ -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;
index ce0cd2d4a527929062e0c02ec2d78bb92be667ab..1878a9546689ac31036ab70fa60bbc3ae1b7dffa 100644 (file)
@@ -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);
                        }
index 143faaf1c46a9b614820dd7f416fae248a1f7b93..e86b3bd6513ec116915478c37da3866c1c916947 100644 (file)
@@ -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);
index 06a170b3061f982ef65132c3750961c7b52a955f..6cc724f42ea2a44fa83c60c88407e231f5d3ef43 100644 (file)
@@ -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);
 
index 1de8fd9c4afdcd0c84c3e066d1977611798aee70..461d9092200f59229c547be650821fcc3b1a53df 100644 (file)
@@ -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 */
 
 /**
index 4ff82631e7266f4a0cf5fee5371daf9a6dc1fd3d..1abf68fcc5f1493083d74151d0b013e552c0282d 100644 (file)
@@ -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));
index f502d8792666df5d4cdadfb2c2e77a609faef90b..11658bdd4df1c9467212f42dc673d0428f9feaa7 100644 (file)
@@ -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()));
 }
 /* }}} */
 
index 0ed5c5568787a6f551464fdc4560f013ceb0c11a..59ae0b8c8902bfa69ac7c005a6f9d33a530dec56 100644 (file)
@@ -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;
                }
        }
 
index e906c233eb8b3f5a1a15ce537b8d2ee51bd8510f..f738b9b059f2b130f8807e275f19c8fb510714b0 100644 (file)
@@ -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;
                }
 
index c9f88ad6d9cba9bbcd438cf6894f4d106b457b3b..3361fc9c73249bc479fe75a411df5d1673349fa0 100644 (file)
@@ -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);
index dde06d288bf904aebaf29999e8d9bf58bc7c8255..0d99f066fcb87130482e6b3501e66bd1c1c25894 100644 (file)
@@ -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);