@@ -2984,6 +2984,22 @@ 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+ static zend_always_inline void zend_ctor_clear_promoted_readonly_reinitable (zend_execute_data * ex , uint32_t call_info )
2990+ {
2991+ if ((call_info & ZEND_CALL_HAS_THIS ) && (ex -> func -> common .fn_flags & ZEND_ACC_CTOR )) {
2992+ zend_object * obj = Z_OBJ (ex -> This );
2993+ zend_property_info * ctor_prop_info ;
2994+ ZEND_HASH_MAP_FOREACH_PTR (& ex -> func -> common .scope -> properties_info , ctor_prop_info ) {
2995+ if ((ctor_prop_info -> flags & (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )) == (ZEND_ACC_READONLY | ZEND_ACC_PROMOTED )
2996+ && IS_VALID_PROPERTY_OFFSET (ctor_prop_info -> offset )) {
2997+ Z_PROP_FLAG_P (OBJ_PROP (obj , ctor_prop_info -> offset )) &= ~IS_PROP_REINITABLE ;
2998+ }
2999+ } ZEND_HASH_FOREACH_END ();
3000+ }
3001+ }
3002+
29873003ZEND_VM_HOT_HELPER (zend_leave_helper , ANY , ANY )
29883004{
29893005 zend_execute_data * old_execute_data ;
@@ -3000,19 +3016,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30003016#ifdef ZEND_PREFER_RELOAD
30013017 call_info = EX_CALL_INFO ();
30023018#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- }
3019+ zend_ctor_clear_promoted_readonly_reinitable (execute_data , call_info );
30163020 if (UNEXPECTED (call_info & ZEND_CALL_RELEASE_THIS )) {
30173021 OBJ_RELEASE (Z_OBJ (execute_data -> This ));
30183022 } else if (UNEXPECTED (call_info & ZEND_CALL_CLOSURE )) {
@@ -3047,19 +3051,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30473051 * as that may free the op_array. */
30483052 zend_vm_stack_free_extra_args_ex (call_info , execute_data );
30493053
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- }
3054+ zend_ctor_clear_promoted_readonly_reinitable (execute_data , call_info );
30633055 if (UNEXPECTED (call_info & ZEND_CALL_RELEASE_THIS )) {
30643056 OBJ_RELEASE (Z_OBJ (execute_data -> This ));
30653057 } else if (UNEXPECTED (call_info & ZEND_CALL_CLOSURE )) {
0 commit comments