summaryrefslogtreecommitdiff
path: root/Zend/zend_interfaces.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2018-07-12 14:04:14 +0300
committerDmitry Stogov <dmitry@zend.com>2018-07-12 14:04:14 +0300
commit7d4e18b05dc962e923236a8d3df81fb0b10b113d (patch)
tree5e5e4301a9dc721a9ae2aa53a3db6ecf08f8ddf2 /Zend/zend_interfaces.c
parent0834679e40555bb8936a096cd7deda3841239985 (diff)
downloadphp-git-7d4e18b05dc962e923236a8d3df81fb0b10b113d.tar.gz
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.
Diffstat (limited to 'Zend/zend_interfaces.c')
-rw-r--r--Zend/zend_interfaces.c51
1 files changed, 36 insertions, 15 deletions
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;
}