Skip to content

Commit 278d651

Browse files
committed
Delay destructor for zend_assign_to_typed_ref
1 parent e7d032a commit 278d651

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
@@ -3592,7 +3592,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
35923592
}
35933593
}
35943594

3595-
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
3595+
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)
35963596
{
35973597
bool ret;
35983598
zval value;
@@ -3607,7 +3607,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui
36073607
ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict);
36083608
variable_ptr = Z_REFVAL_P(variable_ptr);
36093609
if (EXPECTED(ret)) {
3610-
i_zval_ptr_dtor_noref(variable_ptr);
3610+
if (Z_REFCOUNTED_P(variable_ptr)) {
3611+
*garbage_ptr = Z_COUNTED_P(variable_ptr);
3612+
}
36113613
ZVAL_COPY_VALUE(variable_ptr, &value);
36123614
} else {
36133615
zval_ptr_dtor_nogc(&value);
@@ -3625,6 +3627,20 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui
36253627
return variable_ptr;
36263628
}
36273629

3630+
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
3631+
{
3632+
zend_refcounted *garbage = NULL;
3633+
zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage);
3634+
if (garbage) {
3635+
if (GC_DELREF(garbage) == 0) {
3636+
rc_dtor_func(garbage);
3637+
} else {
3638+
gc_check_possible_root_no_ref(garbage);
3639+
}
3640+
}
3641+
return result;
3642+
}
3643+
36283644
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) {
36293645
zval *val = orig_val;
36303646
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)