diff options
author | Dmitry Stogov <dmitry@zend.com> | 2018-07-12 14:04:14 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2018-07-12 14:04:14 +0300 |
commit | 7d4e18b05dc962e923236a8d3df81fb0b10b113d (patch) | |
tree | 5e5e4301a9dc721a9ae2aa53a3db6ecf08f8ddf2 /ext/spl | |
parent | 0834679e40555bb8936a096cd7deda3841239985 (diff) | |
download | php-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 'ext/spl')
-rw-r--r-- | ext/spl/spl_array.c | 22 | ||||
-rw-r--r-- | ext/spl/spl_fixedarray.c | 22 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 42 | ||||
-rw-r--r-- | ext/spl/spl_observer.c | 12 |
4 files changed, 47 insertions, 51 deletions
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); |