Skip to content

Commit b39107c

Browse files
committed
Delay destructor for zend_assign_to_typed_ref
1 parent f43fa59 commit b39107c

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
@@ -3589,7 +3589,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
35893589
}
35903590
}
35913591

3592-
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
3592+
ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr)
35933593
{
35943594
bool ret;
35953595
zval value;
@@ -3604,7 +3604,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui
36043604
ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict);
36053605
variable_ptr = Z_REFVAL_P(variable_ptr);
36063606
if (EXPECTED(ret)) {
3607-
i_zval_ptr_dtor_noref(variable_ptr);
3607+
if (Z_REFCOUNTED_P(variable_ptr)) {
3608+
*garbage_ptr = Z_COUNTED_P(variable_ptr);
3609+
}
36083610
ZVAL_COPY_VALUE(variable_ptr, &value);
36093611
} else {
36103612
zval_ptr_dtor_nogc(&value);
@@ -3622,6 +3624,20 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui
36223624
return variable_ptr;
36233625
}
36243626

3627+
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
3628+
{
3629+
zend_refcounted *garbage = NULL;
3630+
zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage);
3631+
if (garbage) {
3632+
if (GC_DELREF(garbage) == 0) {
3633+
rc_dtor_func(garbage);
3634+
} else {
3635+
gc_check_possible_root_no_ref(garbage);
3636+
}
3637+
}
3638+
return result;
3639+
}
3640+
36253641
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) {
36263642
zval *val = orig_val;
36273643
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
@@ -122,6 +122,7 @@ ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_l
122122
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop);
123123

124124
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, uint8_t value_type, bool strict);
125+
ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr);
125126

126127
static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, uint8_t value_type)
127128
{
@@ -190,7 +191,7 @@ static zend_always_inline zval* zend_assign_to_variable_ex(zval *variable_ptr, z
190191
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
191192
if (Z_ISREF_P(variable_ptr)) {
192193
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
193-
return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict);
194+
return zend_assign_to_typed_ref_ex(variable_ptr, value, value_type, strict, garbage_ptr);
194195
}
195196

196197
variable_ptr = Z_REFVAL_P(variable_ptr);

0 commit comments

Comments
 (0)