From 629ee93ea2663cd942b95ae61570ed179b2ff4a3 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 4 Aug 2024 15:15:41 +0200 Subject: [PATCH] Remove IS_STATIC_VAR_UNINITIALIZED This flag was never necessary. We know a static variable is uninitialized (i.e. the initializer has never been called) iff the zval in the static variable array does not contain a reference. Prompted by a related issue in ext-uopz reported by Christoph. --- UPGRADING.INTERNALS | 3 +++ ...static_variables_throwing_initializer.phpt | 21 +++++++++++++++++++ Zend/zend_compile.c | 1 - Zend/zend_types.h | 5 ----- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 2 +- 6 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 Zend/tests/static_variables_throwing_initializer.phpt diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index d04d7a5b2787d..236b9b980265b 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -99,6 +99,9 @@ PHP 8.4 INTERNALS UPGRADE NOTES zend_std_get_properties(). Use zend_std_get_properties_ex() or zend_std_get_properties() instead. +* Removed IS_STATIC_VAR_UNINITIALIZED constant. Check for IS_NULL in the + static_variables array instead. + ======================== 2. Build system changes ======================== diff --git a/Zend/tests/static_variables_throwing_initializer.phpt b/Zend/tests/static_variables_throwing_initializer.phpt new file mode 100644 index 0000000000000..9e4752c24f5cb --- /dev/null +++ b/Zend/tests/static_variables_throwing_initializer.phpt @@ -0,0 +1,21 @@ +--TEST-- +Static variable with throwing initializer +--FILE-- +getMessage(), "\n"; +} +var_dump(foo(false)); + +?> +--EXPECT-- +Throwing from foo() +int(42) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9253cb9708ce5..307bcab819c40 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5483,7 +5483,6 @@ static void zend_compile_static_var(zend_ast *ast) /* {{{ */ zend_op *opline; zval *placeholder_ptr = zend_hash_update(CG(active_op_array)->static_variables, var_name, &EG(uninitialized_zval)); - Z_TYPE_EXTRA_P(placeholder_ptr) |= IS_STATIC_VAR_UNINITIALIZED; uint32_t placeholder_offset = (uint32_t)((char*)placeholder_ptr - (char*)CG(active_op_array)->static_variables->arData); uint32_t static_def_jmp_opnum = get_next_op_number(); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index d1db25a8f2bda..d33f8a33bcbe6 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -791,11 +791,6 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { /* zval.u1.v.type_flags */ #define IS_TYPE_REFCOUNTED (1<<0) #define IS_TYPE_COLLECTABLE (1<<1) -/* Used for static variables to check if they have been initialized. We can't use IS_UNDEF because - * we can't store IS_UNDEF zvals in the static_variables HashTable. This needs to live in type_info - * so that the ZEND_ASSIGN overrides it but is moved to extra to avoid breaking the Z_REFCOUNTED() - * optimization that only checks for Z_TYPE_FLAGS() without `& (IS_TYPE_COLLECTABLE|IS_TYPE_REFCOUNTED)`. */ -#define IS_STATIC_VAR_UNINITIALIZED (1<<0) #if 1 /* This optimized version assumes that we have a single "type_flag" */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 77c1487b65c62..7c3a22ddb119e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9110,7 +9110,7 @@ ZEND_VM_HANDLER(203, ZEND_BIND_INIT_STATIC_OR_JMP, CV, JMP_ADDR) ZEND_ASSERT(GC_REFCOUNT(ht) == 1); value = (zval*)((char*)ht->arData + opline->extended_value); - if (Z_TYPE_EXTRA_P(value) & IS_STATIC_VAR_UNINITIALIZED) { + if (Z_TYPE_P(value) == IS_NULL) { ZEND_VM_NEXT_OPCODE(); } else { SAVE_OPLINE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b32ef2a6cc132..f234bb149a280 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -41635,7 +41635,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_C ZEND_ASSERT(GC_REFCOUNT(ht) == 1); value = (zval*)((char*)ht->arData + opline->extended_value); - if (Z_TYPE_EXTRA_P(value) & IS_STATIC_VAR_UNINITIALIZED) { + if (Z_TYPE_P(value) == IS_NULL) { ZEND_VM_NEXT_OPCODE(); } else { SAVE_OPLINE();