@@ -2984,6 +2984,26 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC)
29842984 ZEND_VM_NEXT_OPCODE_EX (1 , 2 );
29852985}
29862986
2987+ /* Clear IS_PROP_REINITABLE from all promoted readonly properties of the exiting
2988+ * constructor's scope. Called for both 'new Foo()' and 'parent::__construct()'.
2989+ * Guarded against redefinition because the generator emits this into each VM-kind section. */
2990+ #ifndef ZEND_CTOR_CLEAR_PROMOTED_READONLY_REINITABLE_DEFINED
2991+ #define ZEND_CTOR_CLEAR_PROMOTED_READONLY_REINITABLE_DEFINED
2992+ static zend_always_inline void zend_ctor_clear_promoted_readonly_reinitable (zend_execute_data * ex , uint32_t call_info )
2993+ {
2994+ if ((call_info & ZEND_CALL_HAS_THIS ) && (ex -> func -> common .fn_flags & ZEND_ACC_CTOR )) {
2995+ zend_object * obj = Z_OBJ (ex -> This );
2996+ zend_property_info * ctor_prop_info ;
2997+ ZEND_HASH_MAP_FOREACH_PTR (& ex -> func -> common .scope -> properties_info , ctor_prop_info ) {
2998+ if ((ctor_prop_info -> flags & (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )) == (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )
2999+ && IS_VALID_PROPERTY_OFFSET (ctor_prop_info -> offset )) {
3000+ Z_PROP_FLAG_P (OBJ_PROP (obj , ctor_prop_info -> offset )) &= ~IS_PROP_REINITABLE ;
3001+ }
3002+ } ZEND_HASH_FOREACH_END ();
3003+ }
3004+ }
3005+ #endif
3006+
29873007ZEND_VM_HOT_HELPER (zend_leave_helper , ANY , ANY )
29883008{
29893009 zend_execute_data * old_execute_data ;
@@ -3000,19 +3020,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30003020#ifdef ZEND_PREFER_RELOAD
30013021 call_info = EX_CALL_INFO ();
30023022#endif
3003- /* When a constructor exits, clear IS_PROP_REINITABLE from all promoted readonly
3004- * properties of the declaring class. Runs for both 'new Foo()' (RELEASE_THIS set)
3005- * and 'parent::__construct()' (only HAS_THIS set, no RELEASE_THIS). */
3006- if ((call_info & ZEND_CALL_HAS_THIS ) && (EX (func )-> common .fn_flags & ZEND_ACC_CTOR )) {
3007- zend_object * obj = Z_OBJ (execute_data -> This );
3008- zend_property_info * ctor_prop_info ;
3009- ZEND_HASH_MAP_FOREACH_PTR (& EX (func )-> common .scope -> properties_info , ctor_prop_info ) {
3010- if ((ctor_prop_info -> flags & (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )) == (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )
3011- && IS_VALID_PROPERTY_OFFSET (ctor_prop_info -> offset )) {
3012- Z_PROP_FLAG_P (OBJ_PROP (obj , ctor_prop_info -> offset )) &= ~IS_PROP_REINITABLE ;
3013- }
3014- } ZEND_HASH_FOREACH_END ();
3015- }
3023+ zend_ctor_clear_promoted_readonly_reinitable (execute_data , call_info );
30163024 if (UNEXPECTED (call_info & ZEND_CALL_RELEASE_THIS )) {
30173025 OBJ_RELEASE (Z_OBJ (execute_data -> This ));
30183026 } else if (UNEXPECTED (call_info & ZEND_CALL_CLOSURE )) {
@@ -3047,19 +3055,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30473055 * as that may free the op_array. */
30483056 zend_vm_stack_free_extra_args_ex (call_info , execute_data );
30493057
3050- /* When a constructor exits, clear IS_PROP_REINITABLE from all promoted readonly
3051- * properties of the declaring class. Runs for both 'new Foo()' (RELEASE_THIS set)
3052- * and 'parent::__construct()' (only HAS_THIS set, no RELEASE_THIS). */
3053- if ((call_info & ZEND_CALL_HAS_THIS ) && (EX (func )-> common .fn_flags & ZEND_ACC_CTOR )) {
3054- zend_object * obj = Z_OBJ (execute_data -> This );
3055- zend_property_info * ctor_prop_info ;
3056- ZEND_HASH_MAP_FOREACH_PTR (& EX (func )-> common .scope -> properties_info , ctor_prop_info ) {
3057- if ((ctor_prop_info -> flags & (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )) == (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )
3058- && IS_VALID_PROPERTY_OFFSET (ctor_prop_info -> offset )) {
3059- Z_PROP_FLAG_P (OBJ_PROP (obj , ctor_prop_info -> offset )) &= ~IS_PROP_REINITABLE ;
3060- }
3061- } ZEND_HASH_FOREACH_END ();
3062- }
3058+ zend_ctor_clear_promoted_readonly_reinitable (execute_data , call_info );
30633059 if (UNEXPECTED (call_info & ZEND_CALL_RELEASE_THIS )) {
30643060 OBJ_RELEASE (Z_OBJ (execute_data -> This ));
30653061 } else if (UNEXPECTED (call_info & ZEND_CALL_CLOSURE )) {
0 commit comments