Initialize iterator_funcs_ptr upfront

Same as we do for the IteratorAggregate case, initialize the
Iterator methods upfront. This is preparation for an upcoming
change to automatically determine whether get_iterator can be
reused in a child class, in the same way we already do for
IteratorAggregate.
This commit is contained in:
Nikita Popov 2021-09-24 12:52:37 +02:00
parent 51cf97d7eb
commit d0dbf7296b
3 changed files with 29 additions and 21 deletions

View File

@ -124,10 +124,9 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter)
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = &iter->it.data;
zval more;
bool result;
zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more);
result = i_zend_is_true(&more);
zend_call_known_instance_method_with_0_params(iter->ce->iterator_funcs_ptr->zf_valid, Z_OBJ_P(object), &more);
bool result = i_zend_is_true(&more);
zval_ptr_dtor(&more);
return result ? SUCCESS : FAILURE;
}
@ -142,7 +141,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(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value);
zend_call_known_instance_method_with_0_params(iter->ce->iterator_funcs_ptr->zf_current, Z_OBJ_P(object), &iter->value);
}
return &iter->value;
}
@ -153,7 +152,7 @@ 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;
zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", key);
zend_call_known_instance_method_with_0_params(iter->ce->iterator_funcs_ptr->zf_key, Z_OBJ_P(object), key);
if (UNEXPECTED(Z_ISREF_P(key))) {
zend_unwrap_reference(key);
}
@ -167,7 +166,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(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL);
zend_call_known_instance_method_with_0_params(iter->ce->iterator_funcs_ptr->zf_next, Z_OBJ_P(object), NULL);
}
/* }}} */
@ -178,7 +177,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(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL);
zend_call_known_instance_method_with_0_params(iter->ce->iterator_funcs_ptr->zf_rewind, Z_OBJ_P(object), NULL);
}
/* }}} */
@ -317,6 +316,16 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
ZSTR_VAL(class_type->name));
}
zend_function *zf_rewind = zend_hash_str_find_ptr(
&class_type->function_table, "rewind", sizeof("rewind") - 1);
zend_function *zf_valid = zend_hash_str_find_ptr(
&class_type->function_table, "valid", sizeof("valid") - 1);
zend_function *zf_key = zend_hash_str_find_ptr(
&class_type->function_table, "key", sizeof("key") - 1);
zend_function *zf_current = zend_hash_str_find_ptr(
&class_type->function_table, "current", sizeof("current") - 1);
zend_function *zf_next = zend_hash_str_find_ptr(
&class_type->function_table, "next", sizeof("next") - 1);
if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
if (!class_type->parent || class_type->parent->get_iterator != class_type->get_iterator) {
/* get_iterator was explicitly assigned for an internal class. */
@ -337,9 +346,15 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
zend_class_iterator_funcs *funcs_ptr = class_type->type == ZEND_INTERNAL_CLASS
? pemalloc(sizeof(zend_class_iterator_funcs), 1)
: zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
class_type->iterator_funcs_ptr = funcs_ptr;
memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
funcs_ptr->zf_rewind = zf_rewind;
funcs_ptr->zf_valid = zf_valid;
funcs_ptr->zf_key = zf_key;
funcs_ptr->zf_current = zf_current;
funcs_ptr->zf_next = zf_next;
return SUCCESS;
}
/* }}} */

View File

@ -234,13 +234,6 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o
if (intern->std.handlers == &spl_handler_ArrayIterator) {
zend_class_iterator_funcs *funcs_ptr = class_type->iterator_funcs_ptr;
if (!funcs_ptr->zf_current) {
funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
}
if (inherited) {
if (funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND;
if (funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID;

View File

@ -1017,7 +1017,7 @@ PHP_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_object *it = element->obj;
zend_call_method_with_0_params(it, it->ce, &it->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_rewind, it, NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
@ -1038,7 +1038,7 @@ PHP_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_object *it = element->obj;
zend_call_method_with_0_params(it, it->ce, &it->ce->iterator_funcs_ptr->zf_next, "next", NULL);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_next, it, NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
@ -1067,7 +1067,7 @@ PHP_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_object *it = element->obj;
zend_call_method_with_0_params(it, it->ce, &it->ce->iterator_funcs_ptr->zf_valid, "valid", &retval);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_valid, it, &retval);
if (!Z_ISUNDEF(retval)) {
valid = (Z_TYPE(retval) == IS_TRUE);
@ -1105,7 +1105,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)) {
zend_object *it = element->obj;
zend_call_method_with_0_params(it, it->ce, &it->ce->iterator_funcs_ptr->zf_valid, "valid", &retval);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_valid, it, &retval);
if (!Z_ISUNDEF(retval)) {
valid = Z_TYPE(retval) == IS_TRUE;
@ -1116,9 +1116,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, it->ce, &it->ce->iterator_funcs_ptr->zf_current, "current", &retval);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_current, it, &retval);
} else {
zend_call_method_with_0_params(it, it->ce, &it->ce->iterator_funcs_ptr->zf_key, "key", &retval);
zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_key, it, &retval);
}
if (Z_ISUNDEF(retval)) {
zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0);