Skip to content

Commit 4c580af

Browse files
committed
Delay destructor for zend_assign_to_typed_ref
1 parent 32fd796 commit 4c580af

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

Zend/zend_execute.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3587,7 +3587,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
35873587
}
35883588
}
35893589

3590-
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict)
3590+
ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zend_refcounted **garbage_ptr)
35913591
{
35923592
bool ret;
35933593
zval value;
@@ -3602,7 +3602,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze
36023602
ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict);
36033603
variable_ptr = Z_REFVAL_P(variable_ptr);
36043604
if (EXPECTED(ret)) {
3605-
i_zval_ptr_dtor_noref(variable_ptr);
3605+
if (Z_REFCOUNTED_P(variable_ptr)) {
3606+
*garbage_ptr = Z_COUNTED_P(variable_ptr);
3607+
}
36063608
ZVAL_COPY_VALUE(variable_ptr, &value);
36073609
} else {
36083610
zval_ptr_dtor_nogc(&value);
@@ -3620,6 +3622,20 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze
36203622
return variable_ptr;
36213623
}
36223624

3625+
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict)
3626+
{
3627+
zend_refcounted *garbage = NULL;
3628+
zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage);
3629+
if (garbage) {
3630+
if (GC_DELREF(garbage) == 0) {
3631+
rc_dtor_func(garbage);
3632+
} else {
3633+
gc_check_possible_root_no_ref(garbage);
3634+
}
3635+
}
3636+
return result;
3637+
}
3638+
36233639
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(const zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context) {
36243640
zval *val = orig_val;
36253641
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {

Zend/zend_execute.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_l
119119
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop);
120120

121121
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict);
122+
ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict, zend_refcounted **garbage_ptr);
122123

123124
static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type)
124125
{
@@ -187,7 +188,7 @@ static zend_always_inline zval* zend_assign_to_variable_ex(zval *variable_ptr, z
187188
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
188189
if (Z_ISREF_P(variable_ptr)) {
189190
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
190-
return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict);
191+
return zend_assign_to_typed_ref_ex(variable_ptr, value, value_type, strict, garbage_ptr);
191192
}
192193

193194
variable_ptr = Z_REFVAL_P(variable_ptr);

0 commit comments

Comments
 (0)