diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-02-17 10:47:30 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-02-18 11:18:19 +0100 |
commit | 5d160e309ed207e618d49029e51c9c2dc2c5e61c (patch) | |
tree | a6f1deb6f582e42792a8dccedb117a26decd3e65 /ext/opcache | |
parent | e03284739f4a3a1052dfe5497fbf06c1b206f895 (diff) | |
download | php-git-5d160e309ed207e618d49029e51c9c2dc2c5e61c.tar.gz |
Fix static variable behavior with inheritance
When a method is inherited, the static variables will now always
use the initial values, rather than the values at the time of
inheritance. As such, behavior no longer depends on whether
inheritance happens before or after a method has been called.
This is implemented by always keeping static_variables as the
original values, and static_variables_ptr as the modified copy.
Closes GH-6705.
Diffstat (limited to 'ext/opcache')
-rw-r--r-- | ext/opcache/ZendAccelerator.c | 64 | ||||
-rw-r--r-- | ext/opcache/tests/preload_method_static_vars.phpt | 2 | ||||
-rw-r--r-- | ext/opcache/zend_accelerator_util_funcs.c | 1 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 8 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 9 |
5 files changed, 11 insertions, 73 deletions
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 49efc3a431..c2e5690273 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2323,27 +2323,6 @@ static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, return NULL; } -static bool is_array_cacheable(zval *zv) -{ - zval *p; - - ZEND_HASH_FOREACH_VAL(Z_ARR_P(zv), p) { - if (Z_REFCOUNTED_P(p)) { - if (Z_TYPE_P(p) == IS_ARRAY) { - if (!is_array_cacheable(p)) { - /* Can't cache */ - return 0; - } - } else if (Z_TYPE_P(p) == IS_OBJECT || Z_TYPE_P(p) == IS_RESOURCE || Z_TYPE_P(p) == IS_REFERENCE) { - /* Can't cache */ - return 0; - } - } - } ZEND_HASH_FOREACH_END(); - - return 1; -} - static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) { zend_persistent_script dummy; @@ -2369,44 +2348,6 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, } } - if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { - zend_op_array *op_array; - zval *zv; - - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { - if (op_array->type == ZEND_USER_FUNCTION - && op_array->static_variables - && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - if (UNEXPECTED(GC_REFCOUNT(op_array->static_variables) > 1)) { - GC_DELREF(op_array->static_variables); - op_array->static_variables = zend_array_dup(op_array->static_variables); - } - ZEND_HASH_FOREACH_VAL(op_array->static_variables, zv) { - if (Z_ISREF_P(zv)) { - zend_reference *ref = Z_REF_P(zv); - - ZVAL_COPY_VALUE(zv, &ref->val); - if (GC_DELREF(ref) == 0) { - efree_size(ref, sizeof(zend_reference)); - } - } - if (Z_REFCOUNTED_P(zv)) { - if (Z_TYPE_P(zv) == IS_ARRAY) { - if (!is_array_cacheable(zv)) { - /* Can't cache */ - return NULL; - } - SEPARATE_ARRAY(zv); - } else if (Z_TYPE_P(zv) == IS_OBJECT || Z_TYPE_P(zv) == IS_RESOURCE) { - /* Can't cache */ - return NULL; - } - } - } ZEND_HASH_FOREACH_END(); - } - } ZEND_HASH_FOREACH_END(); - } - SHM_UNPROTECT(); zend_shared_alloc_lock(); @@ -3692,11 +3633,6 @@ static zend_op_array *preload_compile_file(zend_file_handle *file_handle, int ty //??? efree(op_array->refcount); op_array->refcount = NULL; - if (op_array->static_variables && - !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(op_array->static_variables); - } - zend_hash_add_ptr(preload_scripts, script->script.filename, script); } diff --git a/ext/opcache/tests/preload_method_static_vars.phpt b/ext/opcache/tests/preload_method_static_vars.phpt index f3d211793c..05716c91e5 100644 --- a/ext/opcache/tests/preload_method_static_vars.phpt +++ b/ext/opcache/tests/preload_method_static_vars.phpt @@ -18,8 +18,8 @@ Bar::test(); --EXPECT-- int(1) int(2) +int(1) int(2) -int(3) int(1) int(1) diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index f17f7e8076..327e8a4d55 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -219,7 +219,6 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); *op_array = persistent_script->script.main_op_array; - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) { zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 4ebb23fb84..7948797864 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -1234,12 +1234,16 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr if (op_array->static_variables) { ZEND_MAP_PTR_NEW(op_array->static_variables_ptr); } else { - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL); } ZEND_MAP_PTR_NEW(op_array->run_time_cache); } else { op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE; - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); + if (op_array->static_variables) { + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, + zend_arena_alloc(&CG(arena), sizeof(HashTable *))); + ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL); + } if (op_array != &script->script.main_op_array) { ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*))); ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index ea6fa096b6..5e406ec4b6 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -686,8 +686,6 @@ static void zend_persist_op_array(zval *zv) if (op_array->static_variables) { ZEND_MAP_PTR_NEW(op_array->static_variables_ptr); } - } else { - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); } } @@ -757,8 +755,8 @@ static void zend_persist_class_method(zval *zv, zend_class_entry *ce) } else { if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL); + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL); } - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); } } @@ -1277,9 +1275,10 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script zend_persist_op_array_ex(&script->script.main_op_array, script); if (!script->corrupted) { ZEND_MAP_PTR_INIT(script->script.main_op_array.run_time_cache, NULL); + if (script->script.main_op_array.static_variables) { + ZEND_MAP_PTR_NEW(script->script.main_op_array.static_variables_ptr); + } } - ZEND_MAP_PTR_INIT(script->script.main_op_array.static_variables_ptr, - &script->script.main_op_array.static_variables); zend_persist_warnings(script); if (for_shm) { |