Reverted back ce->iterator_funcs_ptr. Initialize ce->iterator_funcs_ptr fields in immutable classes.

This commit is contained in:
Dmitry Stogov 2018-10-17 14:12:28 +03:00
parent ad7a78b253
commit 4740dabb84
15 changed files with 125 additions and 192 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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; \
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
/* }}} */

View File

@ -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);

View File

@ -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)

View File

@ -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));
}
}

View File

@ -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 */

View File

@ -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));
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);