From 1c0327cd7cb4389746095ff21530c08086969df2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 16 Feb 2023 22:33:37 +0100 Subject: [PATCH 1/5] Delay freeing of overwritten values in assignments Fixes GH-10168 --- Zend/zend_execute.c | 40 +- Zend/zend_execute.h | 22 + Zend/zend_gc.h | 8 + Zend/zend_vm_def.h | 82 ++- Zend/zend_vm_execute.h | 1175 ++++++++++++++++++++++++++++++++++------ 5 files changed, 1123 insertions(+), 204 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index abe3b8042c96..18dc966f6608 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -546,7 +546,7 @@ static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, zno return get_zval_ptr_ptr(op_type, node, type); } -static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr) +static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr) { zend_reference *ref; @@ -559,20 +559,12 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v ref = Z_REF_P(value_ptr); GC_ADDREF(ref); if (Z_REFCOUNTED_P(variable_ptr)) { - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); - - if (GC_DELREF(garbage) == 0) { - ZVAL_REF(variable_ptr, ref); - rc_dtor_func(garbage); - return; - } else { - gc_check_possible_root(garbage); - } + *garbage_ptr = Z_COUNTED_P(variable_ptr); } ZVAL_REF(variable_ptr, ref); } -static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr EXECUTE_DATA_DC) +static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr, zend_refcounted **garbage_ptr EXECUTE_DATA_DC) { if (!zend_verify_prop_assignable_by_ref(prop_info, value_ptr, EX_USES_STRICT_TYPES())) { return &EG(uninitialized_zval); @@ -580,12 +572,12 @@ static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_prop if (Z_ISREF_P(prop)) { ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(prop), prop_info); } - zend_assign_to_variable_reference(prop, value_ptr); + zend_assign_to_variable_reference(prop, value_ptr, garbage_ptr); ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(prop), prop_info); return prop; } -static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr OPLINE_DC EXECUTE_DATA_DC) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -594,7 +586,7 @@ static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference /* Use IS_TMP_VAR instead of IS_VAR to avoid ISREF check */ Z_TRY_ADDREF_P(value_ptr); - return zend_assign_to_variable(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + return zend_assign_to_variable_ex(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr); } ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg_num) @@ -957,7 +949,7 @@ static bool zend_check_and_resolve_property_class_type( if (zend_check_intersection_for_property_class_type( ZEND_TYPE_LIST(*list_type), info, object_ce)) { return true; - } + } continue; } ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); @@ -1005,7 +997,7 @@ ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_in return i_zend_verify_property_type(info, property, strict); } -static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value EXECUTE_DATA_DC) +static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value, zend_refcounted **garbage_ptr EXECUTE_DATA_DC) { zval tmp; @@ -1024,7 +1016,7 @@ static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *inf Z_PROP_FLAG_P(property_val) &= ~IS_PROP_REINITABLE; - return zend_assign_to_variable(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + return zend_assign_to_variable_ex(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr); } static zend_always_inline bool zend_value_instanceof_static(zval *zv) { @@ -3248,6 +3240,7 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container { zval variable, *variable_ptr = &variable; void **cache_addr = (prop_op_type == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL; + zend_refcounted *garbage = NULL; zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type, cache_addr, BP_VAR_W, 0, 0 OPLINE_CC EXECUTE_DATA_CC); @@ -3259,7 +3252,7 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { zend_property_info *prop_info = NULL; @@ -3271,9 +3264,9 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container } if (UNEXPECTED(prop_info)) { - variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr EXECUTE_DATA_CC); + variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr, &garbage EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } } } else if (Z_ISERROR_P(variable_ptr)) { @@ -3287,6 +3280,13 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } } static zend_never_inline void zend_assign_to_property_reference_this_const(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC) diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 323b6269ee55..45f5607edb86 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -184,6 +184,28 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval return variable_ptr; } +static zend_always_inline zval* zend_assign_to_variable_ex(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict, zend_refcounted **garbage_ptr) +{ + do { + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + if (Z_ISREF_P(variable_ptr)) { + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { + return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict); + } + + variable_ptr = Z_REFVAL_P(variable_ptr); + if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { + break; + } + } + *garbage_ptr = Z_COUNTED_P(variable_ptr); + } + } while (0); + + zend_copy_to_variable(variable_ptr, value, value_type); + return variable_ptr; +} + ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx); diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h index 762f3180637e..f4095e43bb69 100644 --- a/Zend/zend_gc.h +++ b/Zend/zend_gc.h @@ -89,6 +89,14 @@ static zend_always_inline void gc_check_possible_root(zend_refcounted *ref) } } +static zend_always_inline void gc_check_possible_root_no_ref(zend_refcounted *ref) +{ + ZEND_ASSERT(GC_TYPE_INFO(ref) != GC_REFERENCE); + if (UNEXPECTED(GC_MAY_LEAK(ref))) { + gc_possible_root(ref); + } +} + /* These APIs can be used to simplify object get_gc implementations * over heterogeneous structures. See zend_generator_get_gc() for * a usage example. */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 57d5cf887aca..a0b3386b85ba 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2381,6 +2381,7 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2410,11 +2411,11 @@ ZEND_VM_C_LABEL(assign_object): zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); ZEND_VM_C_GOTO(free_and_exit_assign_obj); } else { ZEND_VM_C_LABEL(fast_assign_obj): - value = zend_assign_to_variable(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -2498,6 +2499,13 @@ ZEND_VM_C_LABEL(free_and_exit_assign_obj): } FREE_OP_DATA(); ZEND_VM_C_LABEL(exit_assign_obj): + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } FREE_OP2(); FREE_OP1(); /* assign_obj has two opcodes! */ @@ -2510,6 +2518,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= USE_OPLINE zval *prop, *value; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -2522,16 +2531,24 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); FREE_OP_DATA(); } else { - value = zend_assign_to_variable(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -2543,6 +2560,7 @@ ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(O zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2598,11 +2616,18 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZEND_VM_C_GOTO(assign_dim_error); } value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); - value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -2695,9 +2720,22 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (!ZEND_VM_SPEC || UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); } FREE_OP1(); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -2710,6 +2748,7 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) USE_OPLINE zval *variable_ptr; zval *value_ptr; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); @@ -2725,15 +2764,23 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + FREE_OP2(); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -2781,6 +2828,7 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) USE_OPLINE zval *prop, *value_ptr; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -2793,19 +2841,27 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); + prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr, &garbage EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(prop, value_ptr); + zend_assign_to_variable_reference(prop, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), prop); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + FREE_OP_DATA(); ZEND_VM_NEXT_OPCODE_EX(1, 2); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 95e66b0cac3a..afe8f54656da 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -927,6 +927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT USE_OPLINE zval *prop, *value; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -939,16 +940,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = RT_CONSTANT((opline+1), (opline+1)->op1); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); } else { - value = zend_assign_to_variable(prop, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(prop, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -958,6 +967,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT USE_OPLINE zval *prop, *value; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -970,16 +980,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { - value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -989,6 +1007,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT USE_OPLINE zval *prop, *value; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -1001,16 +1020,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { - value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(prop, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -1020,6 +1047,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT USE_OPLINE zval *prop, *value; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -1032,16 +1060,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); } else { - value = zend_assign_to_variable(prop, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(prop, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -1051,6 +1087,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA USE_OPLINE zval *prop, *value_ptr; zend_property_info *prop_info; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); @@ -1063,19 +1100,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); + prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr, &garbage EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(prop, value_ptr); + zend_assign_to_variable_reference(prop, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), prop); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23271,6 +23316,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23300,11 +23346,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -23388,6 +23434,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -23401,6 +23454,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23430,11 +23484,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -23518,6 +23572,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -23531,6 +23592,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23560,11 +23622,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -23648,6 +23710,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -23661,6 +23730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23690,11 +23760,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -23778,6 +23848,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -23792,6 +23869,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23847,11 +23925,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -23940,6 +24025,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -23995,11 +24081,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -24089,6 +24182,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -24144,11 +24238,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -24238,6 +24339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -24293,11 +24395,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -24389,9 +24498,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -24409,9 +24531,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -26127,6 +26262,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26156,11 +26292,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -26244,6 +26380,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -26257,6 +26400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26286,11 +26430,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -26374,6 +26518,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -26387,6 +26538,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26416,11 +26568,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -26504,6 +26656,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -26517,6 +26676,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26546,11 +26706,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -26634,6 +26794,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -26648,6 +26815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26703,11 +26871,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -26796,6 +26971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -26851,11 +27027,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -26945,6 +27128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -27000,11 +27184,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -27094,6 +27285,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -27149,11 +27341,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -27875,9 +28074,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -27895,9 +28107,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -27959,9 +28184,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -27979,9 +28217,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -27994,6 +28245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE USE_OPLINE zval *variable_ptr; zval *value_ptr; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -28009,15 +28261,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -28179,6 +28439,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -28234,11 +28495,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -28327,6 +28595,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -28382,11 +28651,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -28476,6 +28752,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -28531,11 +28808,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -28625,6 +28909,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -28680,11 +28965,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -30330,6 +30622,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -30359,11 +30652,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -30447,6 +30740,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -30460,6 +30760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -30489,11 +30790,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -30577,6 +30878,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -30590,6 +30898,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -30619,11 +30928,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -30707,6 +31016,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -30720,6 +31036,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -30749,11 +31066,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -30837,6 +31154,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ @@ -30851,6 +31175,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -30906,11 +31231,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -30999,6 +31331,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -31054,11 +31387,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -31148,6 +31488,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -31203,11 +31544,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -31297,6 +31645,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -31352,11 +31701,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -31448,9 +31804,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -31468,9 +31837,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -31483,6 +31865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER USE_OPLINE zval *variable_ptr; zval *value_ptr; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); @@ -31498,15 +31881,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32908,6 +33299,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -32937,11 +33329,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -33025,6 +33417,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -33038,6 +33437,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -33067,11 +33467,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -33155,6 +33555,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -33168,6 +33575,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -33197,11 +33605,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -33285,6 +33693,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -33298,6 +33713,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -33327,11 +33743,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -33415,6 +33831,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -34926,6 +35349,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -34955,11 +35379,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -35043,6 +35467,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -35056,6 +35487,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -35085,11 +35517,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -35173,6 +35605,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -35186,6 +35625,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -35215,11 +35655,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -35303,6 +35743,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -35316,6 +35763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -35345,11 +35793,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -35433,6 +35881,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -37400,6 +37855,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -37429,11 +37885,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -37517,6 +37973,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -37530,6 +37993,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -37559,11 +38023,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -37647,6 +38111,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -37660,6 +38131,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -37689,11 +38161,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -37777,6 +38249,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -37790,6 +38269,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = &EX(This); @@ -37819,11 +38299,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -37907,6 +38387,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -41577,6 +42064,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -41606,11 +42094,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -41694,6 +42182,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -41707,6 +42202,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -41736,11 +42232,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -41824,6 +42320,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -41837,6 +42340,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -41866,11 +42370,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -41954,6 +42458,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -41967,6 +42478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -41996,11 +42508,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -42084,6 +42596,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -42098,6 +42617,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -42153,11 +42673,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -42246,6 +42773,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -42301,11 +42829,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -42395,6 +42930,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -42450,11 +42986,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -42544,6 +43087,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -42599,11 +43143,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -42695,9 +43246,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -42715,9 +43279,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -45366,6 +45943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -45395,11 +45973,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -45483,6 +46061,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -45496,6 +46081,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -45525,11 +46111,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -45613,6 +46199,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -45626,6 +46219,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -45655,11 +46249,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -45743,6 +46337,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -45756,6 +46357,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -45785,11 +46387,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -45873,6 +46475,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ @@ -45887,6 +46496,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -45942,11 +46552,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -46035,6 +46652,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -46090,11 +46708,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -46184,6 +46809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -46239,11 +46865,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -46333,6 +46966,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -46388,11 +47022,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -47407,9 +48048,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -47427,9 +48081,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -47477,9 +48144,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -47497,9 +48177,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -47512,6 +48205,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER USE_OPLINE zval *variable_ptr; zval *value_ptr; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -47527,15 +48221,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -47870,6 +48572,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -47925,11 +48628,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -48018,6 +48728,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -48073,11 +48784,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -48167,6 +48885,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -48222,11 +48941,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -48316,6 +49042,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -48371,11 +49098,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -50694,6 +51428,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -50723,11 +51458,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -50811,6 +51546,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -50824,6 +51566,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -50853,11 +51596,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -50941,6 +51684,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -50954,6 +51704,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -50983,11 +51734,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -51071,6 +51822,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -51084,6 +51842,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval *object, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -51113,11 +51872,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -51201,6 +51960,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } exit_assign_obj: + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } /* assign_obj has two opcodes! */ @@ -51215,6 +51981,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -51270,11 +52037,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -51363,6 +52137,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -51418,11 +52193,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -51512,6 +52294,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -51567,11 +52350,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -51661,6 +52451,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval *value; zval *variable_ptr; zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); @@ -51716,11 +52507,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { object_ptr = Z_REFVAL_P(object_ptr); @@ -51812,9 +52610,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -51832,9 +52643,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } /* zend_assign_to_variable() always takes care of op2, never free it! */ @@ -51847,6 +52671,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( USE_OPLINE zval *variable_ptr; zval *value_ptr; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); @@ -51862,15 +52687,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( UNEXPECTED(!Z_ISREF_P(value_ptr))) { variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root(garbage); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } From 47d3b6f1fe5db962985a9d16d3960049bb69b7ce Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Feb 2023 21:09:39 +0100 Subject: [PATCH 2/5] Add various tests for GH-10168 --- Zend/tests/gh10168/assign.phpt | 18 ++++++++++ Zend/tests/gh10168/assign_dim.phpt | 18 ++++++++++ Zend/tests/gh10168/assign_dim_ref.phpt | 19 ++++++++++ .../gh10168/assign_dim_ref_with_prop_ref.phpt | 22 ++++++++++++ .../gh10168/assign_dim_with_prop_ref.phpt | 21 +++++++++++ Zend/tests/gh10168/assign_prop.phpt | 33 +++++++++++++++++ Zend/tests/gh10168/assign_prop_ref.phpt | 33 +++++++++++++++++ .../assign_prop_ref_with_prop_ref.phpt | 36 +++++++++++++++++++ .../gh10168/assign_prop_with_prop_ref.phpt | 36 +++++++++++++++++++ Zend/tests/gh10168/assign_ref.phpt | 18 ++++++++++ .../gh10168/assign_ref_with_prop_ref.phpt | 20 +++++++++++ Zend/tests/gh10168/assign_static_prop.phpt | 20 +++++++++++ .../tests/gh10168/assign_static_prop_ref.phpt | 20 +++++++++++ .../assign_static_prop_ref_with_prop_ref.phpt | 23 ++++++++++++ .../assign_static_prop_with_prop_ref.phpt | 22 ++++++++++++ .../gh10168/assign_static_untyped_prop.phpt | 20 +++++++++++ .../assign_static_untyped_prop_ref.phpt | 20 +++++++++++ ...static_untyped_prop_ref_with_prop_ref.phpt | 23 ++++++++++++ ...ign_static_untyped_prop_with_prop_ref.phpt | 22 ++++++++++++ Zend/tests/gh10168/assign_untyped_prop.phpt | 33 +++++++++++++++++ .../gh10168/assign_untyped_prop_ref.phpt | 33 +++++++++++++++++ ...assign_untyped_prop_ref_with_prop_ref.phpt | 36 +++++++++++++++++++ .../assign_untyped_prop_with_prop_ref.phpt | 36 +++++++++++++++++++ Zend/tests/gh10168/assign_with_prop_ref.phpt | 21 +++++++++++ .../gh10168/wrong_assign_to_variable.phpt | 21 +++++++++++ 25 files changed, 624 insertions(+) create mode 100644 Zend/tests/gh10168/assign.phpt create mode 100644 Zend/tests/gh10168/assign_dim.phpt create mode 100644 Zend/tests/gh10168/assign_dim_ref.phpt create mode 100644 Zend/tests/gh10168/assign_dim_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_dim_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_prop.phpt create mode 100644 Zend/tests/gh10168/assign_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_prop_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_ref.phpt create mode 100644 Zend/tests/gh10168/assign_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_prop.phpt create mode 100644 Zend/tests/gh10168/assign_static_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_prop_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_prop_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_untyped_prop.phpt create mode 100644 Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_untyped_prop_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_static_untyped_prop_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_untyped_prop.phpt create mode 100644 Zend/tests/gh10168/assign_untyped_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_untyped_prop_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/assign_with_prop_ref.phpt create mode 100644 Zend/tests/gh10168/wrong_assign_to_variable.phpt diff --git a/Zend/tests/gh10168/assign.phpt b/Zend/tests/gh10168/assign.phpt new file mode 100644 index 000000000000..3c6740165d4a --- /dev/null +++ b/Zend/tests/gh10168/assign.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-10168: Assign +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_dim.phpt b/Zend/tests/gh10168/assign_dim.phpt new file mode 100644 index 000000000000..1a31cfdde3b7 --- /dev/null +++ b/Zend/tests/gh10168/assign_dim.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-10168: Assign dim +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_dim_ref.phpt b/Zend/tests/gh10168/assign_dim_ref.phpt new file mode 100644 index 000000000000..40ae4485d2cf --- /dev/null +++ b/Zend/tests/gh10168/assign_dim_ref.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-10168: Assign dim ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_dim_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_dim_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..8415df433686 --- /dev/null +++ b/Zend/tests/gh10168/assign_dim_ref_with_prop_ref.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10168: Assign dim ref with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_dim_with_prop_ref.phpt b/Zend/tests/gh10168/assign_dim_with_prop_ref.phpt new file mode 100644 index 000000000000..764d10d34658 --- /dev/null +++ b/Zend/tests/gh10168/assign_dim_with_prop_ref.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-10168: Assign dim with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_prop.phpt b/Zend/tests/gh10168/assign_prop.phpt new file mode 100644 index 000000000000..73aaab89755e --- /dev/null +++ b/Zend/tests/gh10168/assign_prop.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-10168: Assign prop +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + var_dump($box->value = new Test); +} + +$box = new Box(); +$box->value = new Test; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/tests/gh10168/assign_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref.phpt new file mode 100644 index 000000000000..e7bbe6f9eea7 --- /dev/null +++ b/Zend/tests/gh10168/assign_prop_ref.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-10168: Assign prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + $tmp = new Test; + var_dump($box->value = &$tmp); +} + +$box = new Box(); +$box->value = new Test; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..b56eedd701d0 --- /dev/null +++ b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168: Assign prop ref with prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + $tmp = new Test; + var_dump($box->value = &$tmp); +} + +$box = new Box(); +$box->value = new Test; +Test::$test = &$box->value; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +NULL diff --git a/Zend/tests/gh10168/assign_prop_with_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_with_prop_ref.phpt new file mode 100644 index 000000000000..1ba3e31b49cc --- /dev/null +++ b/Zend/tests/gh10168/assign_prop_with_prop_ref.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168: Assign prop with prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + var_dump($box->value = new Test); +} + +$box = new Box(); +$box->value = new Test; +Test::$test = &$box->value; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/tests/gh10168/assign_ref.phpt b/Zend/tests/gh10168/assign_ref.phpt new file mode 100644 index 000000000000..9f3be5619d1a --- /dev/null +++ b/Zend/tests/gh10168/assign_ref.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-10168: Assign ref +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..42ce94b3f83e --- /dev/null +++ b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10168: Assign ref with prop ref +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/gh10168/assign_static_prop.phpt b/Zend/tests/gh10168/assign_static_prop.phpt new file mode 100644 index 000000000000..900a69ae40aa --- /dev/null +++ b/Zend/tests/gh10168/assign_static_prop.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10168: Assign static prop +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_prop_ref.phpt b/Zend/tests/gh10168/assign_static_prop_ref.phpt new file mode 100644 index 000000000000..2e90be884ded --- /dev/null +++ b/Zend/tests/gh10168/assign_static_prop_ref.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10168: Assign static prop ref +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/gh10168/assign_static_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_static_prop_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..df11b17e2781 --- /dev/null +++ b/Zend/tests/gh10168/assign_static_prop_ref_with_prop_ref.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-10168: Assign static prop ref with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_prop_with_prop_ref.phpt b/Zend/tests/gh10168/assign_static_prop_with_prop_ref.phpt new file mode 100644 index 000000000000..c98233589c41 --- /dev/null +++ b/Zend/tests/gh10168/assign_static_prop_with_prop_ref.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10168: Assign static prop with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_untyped_prop.phpt b/Zend/tests/gh10168/assign_static_untyped_prop.phpt new file mode 100644 index 000000000000..cf1736b6c58d --- /dev/null +++ b/Zend/tests/gh10168/assign_static_untyped_prop.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10168: Assign static prop +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt new file mode 100644 index 000000000000..dfef8ead26f6 --- /dev/null +++ b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10168: Assign static prop ref +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/gh10168/assign_static_untyped_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_static_untyped_prop_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..337c9a8f1475 --- /dev/null +++ b/Zend/tests/gh10168/assign_static_untyped_prop_ref_with_prop_ref.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-10168: Assign static prop ref with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_untyped_prop_with_prop_ref.phpt b/Zend/tests/gh10168/assign_static_untyped_prop_with_prop_ref.phpt new file mode 100644 index 000000000000..1b46cafaa040 --- /dev/null +++ b/Zend/tests/gh10168/assign_static_untyped_prop_with_prop_ref.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10168: Assign static prop with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_untyped_prop.phpt b/Zend/tests/gh10168/assign_untyped_prop.phpt new file mode 100644 index 000000000000..898173283ca6 --- /dev/null +++ b/Zend/tests/gh10168/assign_untyped_prop.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-10168: Assign prop +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + var_dump($box->value = new Test); +} + +$box = new Box(); +$box->value = new Test; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt new file mode 100644 index 000000000000..c35e7a0663ee --- /dev/null +++ b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-10168: Assign prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + $tmp = new Test; + var_dump($box->value = &$tmp); +} + +$box = new Box(); +$box->value = new Test; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt new file mode 100644 index 000000000000..b48a0911e499 --- /dev/null +++ b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168: Assign prop ref with prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + $tmp = new Test; + var_dump($box->value = &$tmp); +} + +$box = new Box(); +$box->value = new Test; +Test::$test = &$box->value; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +NULL diff --git a/Zend/tests/gh10168/assign_untyped_prop_with_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_with_prop_ref.phpt new file mode 100644 index 000000000000..12acc1203c22 --- /dev/null +++ b/Zend/tests/gh10168/assign_untyped_prop_with_prop_ref.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168: Assign prop with prop ref +--XFAIL-- +--FILE-- +value = null; + } +} + +function test($box) { + var_dump($box->value = new Test); +} + +$box = new Box(); +$box->value = new Test; +Test::$test = &$box->value; +test($box); +// Second call tests the cache slot path +test($box); + +?> +--EXPECT-- +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/tests/gh10168/assign_with_prop_ref.phpt b/Zend/tests/gh10168/assign_with_prop_ref.phpt new file mode 100644 index 000000000000..f3e875651450 --- /dev/null +++ b/Zend/tests/gh10168/assign_with_prop_ref.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-10168: Assign with prop ref +--FILE-- + +--EXPECT-- +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/wrong_assign_to_variable.phpt b/Zend/tests/gh10168/wrong_assign_to_variable.phpt new file mode 100644 index 000000000000..36fdecdfefcd --- /dev/null +++ b/Zend/tests/gh10168/wrong_assign_to_variable.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-10168: Wrong assign to variable +--FILE-- + +--EXPECTF-- +Notice: Only variables should be assigned by reference in %s on line %d +int(42) From 481107809b56e171c65a5734aa528028998abf81 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Feb 2023 21:10:14 +0100 Subject: [PATCH 3/5] Delay destructor for zend_assign_to_typed_ref --- Zend/zend_execute.c | 20 ++++++++++++++++++-- Zend/zend_execute.h | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 18dc966f6608..0eb5d4412702 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3589,7 +3589,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { } } -ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict) +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) { bool ret; zval value; @@ -3604,7 +3604,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict); variable_ptr = Z_REFVAL_P(variable_ptr); if (EXPECTED(ret)) { - i_zval_ptr_dtor_noref(variable_ptr); + if (Z_REFCOUNTED_P(variable_ptr)) { + *garbage_ptr = Z_COUNTED_P(variable_ptr); + } ZVAL_COPY_VALUE(variable_ptr, &value); } else { zval_ptr_dtor_nogc(&value); @@ -3622,6 +3624,20 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui return variable_ptr; } +ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict) +{ + zend_refcounted *garbage = NULL; + zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage); + if (garbage) { + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } + return result; +} + 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) { zval *val = orig_val; if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 45f5607edb86..663e52956979 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -122,6 +122,7 @@ ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_l ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop); ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, uint8_t value_type, bool strict); +ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr); static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, uint8_t value_type) { @@ -190,7 +191,7 @@ static zend_always_inline zval* zend_assign_to_variable_ex(zval *variable_ptr, z if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { if (Z_ISREF_P(variable_ptr)) { if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { - return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict); + return zend_assign_to_typed_ref_ex(variable_ptr, value, value_type, strict, garbage_ptr); } variable_ptr = Z_REFVAL_P(variable_ptr); From 5116ca5b706fd7d5667551c8c9f0a803e23a55e1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 3 Mar 2023 00:02:42 +0100 Subject: [PATCH 4/5] Delay destructor for zend_std_write_property --- Zend/tests/gh10168/assign_prop.phpt | 1 - Zend/tests/gh10168/assign_prop_ref.phpt | 1 - .../assign_prop_ref_with_prop_ref.phpt | 1 - .../gh10168/assign_prop_with_prop_ref.phpt | 1 - Zend/tests/gh10168/assign_untyped_prop.phpt | 1 - .../gh10168/assign_untyped_prop_ref.phpt | 1 - ...assign_untyped_prop_ref_with_prop_ref.phpt | 1 - .../assign_untyped_prop_with_prop_ref.phpt | 1 - Zend/zend_object_handlers.c | 27 ++++++- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 72 +++++++++---------- ext/opcache/jit/zend_jit_helpers.c | 2 +- 12 files changed, 62 insertions(+), 49 deletions(-) diff --git a/Zend/tests/gh10168/assign_prop.phpt b/Zend/tests/gh10168/assign_prop.phpt index 73aaab89755e..ad7bb762f555 100644 --- a/Zend/tests/gh10168/assign_prop.phpt +++ b/Zend/tests/gh10168/assign_prop.phpt @@ -1,6 +1,5 @@ --TEST-- GH-10168: Assign prop ---XFAIL-- --FILE-- common.type) + && EX(opline) + && EX(opline)->opcode == ZEND_ASSIGN_OBJ + && EX(opline)->result_type) { + ZVAL_COPY_DEREF(EX_VAR(EX(opline)->result.var), variable_ptr); + variable_ptr = NULL; + } + rc_dtor_func(garbage); + } else { + gc_check_possible_root_no_ref(garbage); + } + } goto exit; } if (Z_PROP_FLAG_P(variable_ptr) & IS_PROP_UNINIT) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a0b3386b85ba..84b8a9973e3a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2494,7 +2494,7 @@ ZEND_VM_C_LABEL(fast_assign_obj): } ZEND_VM_C_LABEL(free_and_exit_assign_obj): - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } FREE_OP_DATA(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index afe8f54656da..1b77c381dd3e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23429,7 +23429,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -23567,7 +23567,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23705,7 +23705,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23843,7 +23843,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -26375,7 +26375,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -26513,7 +26513,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -26651,7 +26651,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -26789,7 +26789,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -30735,7 +30735,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -30873,7 +30873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -31011,7 +31011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -31149,7 +31149,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -33412,7 +33412,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -33550,7 +33550,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -33688,7 +33688,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -33826,7 +33826,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -35462,7 +35462,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -35600,7 +35600,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -35738,7 +35738,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -35876,7 +35876,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -37968,7 +37968,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -38106,7 +38106,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -38244,7 +38244,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -38382,7 +38382,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -42177,7 +42177,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -42315,7 +42315,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -42453,7 +42453,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -42591,7 +42591,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -46056,7 +46056,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -46194,7 +46194,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -46332,7 +46332,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -46470,7 +46470,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -51541,7 +51541,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } @@ -51679,7 +51679,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -51817,7 +51817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -51955,7 +51955,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 7c889a2ade8d..4da73d770f1c 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2496,7 +2496,7 @@ static void ZEND_FASTCALL zend_jit_assign_obj_helper(zend_object *zobj, zend_str ZVAL_DEREF(value); value = zobj->handlers->write_property(zobj, name, value, cache_slot); - if (result) { + if (result && value) { ZVAL_COPY_DEREF(result, value); } } From 94392ec648bc56a60dc0f63fcdd91eade7e95270 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 3 Mar 2023 12:13:27 +0100 Subject: [PATCH 5/5] Add GC_DTOR/GC_DTOR_NO_REF macros --- Zend/zend_execute.c | 18 +- Zend/zend_execute.h | 9 +- Zend/zend_refcounted.h | 18 ++ Zend/zend_vm_def.h | 42 +-- Zend/zend_vm_execute.h | 564 +++++++---------------------------------- 5 files changed, 123 insertions(+), 528 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0eb5d4412702..8384e5959dea 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3281,11 +3281,7 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } } @@ -3581,11 +3577,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { if (Z_REFCOUNTED_P(zval_ptr)) { zend_refcounted *ref = Z_COUNTED_P(zval_ptr); ZEND_ASSERT(Z_TYPE_P(zval_ptr) != IS_REFERENCE); - if (!GC_DELREF(ref)) { - rc_dtor_func(ref); - } else if (UNEXPECTED(GC_MAY_LEAK(ref))) { - gc_possible_root(ref); - } + GC_DTOR_NO_REF(ref); } } @@ -3629,11 +3621,7 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ui zend_refcounted *garbage = NULL; zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage); if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } return result; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 663e52956979..9f2ff58b7632 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -169,14 +169,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval } garbage = Z_COUNTED_P(variable_ptr); zend_copy_to_variable(variable_ptr, value, value_type); - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { /* we need to split */ - /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ - if (UNEXPECTED(GC_MAY_LEAK(garbage))) { - gc_possible_root(garbage); - } - } + GC_DTOR_NO_REF(garbage); return variable_ptr; } } while (0); diff --git a/Zend/zend_refcounted.h b/Zend/zend_refcounted.h index e4ffc9956853..b98e5a59604c 100644 --- a/Zend/zend_refcounted.h +++ b/Zend/zend_refcounted.h @@ -56,6 +56,24 @@ #define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc) #define GC_TRY_ADDREF(p) zend_gc_try_addref(&(p)->gc) #define GC_TRY_DELREF(p) zend_gc_try_delref(&(p)->gc) +#define GC_DTOR(p) \ + do { \ + zend_refcounted_h *_p = &(p)->gc; \ + if (zend_gc_delref(_p) == 0) { \ + rc_dtor_func((zend_refcounted *)_p); \ + } else { \ + gc_check_possible_root((zend_refcounted *)_p); \ + } \ + } while (0) +#define GC_DTOR_NO_REF(p) \ + do { \ + zend_refcounted_h *_p = &(p)->gc; \ + if (zend_gc_delref(_p) == 0) { \ + rc_dtor_func((zend_refcounted *)_p); \ + } else { \ + gc_check_possible_root_no_ref((zend_refcounted *)_p); \ + } \ + } while (0) #define GC_NULL (IS_NULL | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT)) #define GC_STRING (IS_STRING | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT)) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 84b8a9973e3a..46ebbde41786 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2500,11 +2500,7 @@ ZEND_VM_C_LABEL(free_and_exit_assign_obj): FREE_OP_DATA(); ZEND_VM_C_LABEL(exit_assign_obj): if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } FREE_OP2(); FREE_OP1(); @@ -2542,11 +2538,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } /* assign_static_prop has two opcodes! */ @@ -2622,11 +2614,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -2728,11 +2716,7 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); @@ -2774,11 +2758,7 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } FREE_OP2(); @@ -2855,11 +2835,7 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } FREE_OP_DATA(); @@ -6479,11 +6455,7 @@ ZEND_VM_HANDLER(153, ZEND_UNSET_CV, CV, UNUSED) ZVAL_UNDEF(var); SAVE_OPLINE(); - if (!GC_DELREF(garbage)) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZVAL_UNDEF(var); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1b77c381dd3e..de1c6eb37921 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -951,11 +951,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } /* assign_static_prop has two opcodes! */ @@ -991,11 +987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } /* assign_static_prop has two opcodes! */ @@ -1031,11 +1023,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } /* assign_static_prop has two opcodes! */ @@ -1071,11 +1059,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } /* assign_static_prop has two opcodes! */ @@ -1114,11 +1098,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -23435,11 +23415,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -23573,11 +23549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -23711,11 +23683,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -23849,11 +23817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -23931,11 +23895,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24087,11 +24047,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24244,11 +24200,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24401,11 +24353,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24506,11 +24454,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); @@ -24539,11 +24483,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); @@ -26381,11 +26321,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -26519,11 +26455,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -26657,11 +26589,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -26795,11 +26723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -26877,11 +26801,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27033,11 +26953,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27190,11 +27106,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27347,11 +27259,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28082,11 +27990,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); @@ -28115,11 +28019,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); @@ -28192,11 +28092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); @@ -28225,11 +28121,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); @@ -28271,11 +28163,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -28501,11 +28389,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28657,11 +28541,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28814,11 +28694,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28971,11 +28847,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30741,11 +30613,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -30879,11 +30747,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -31017,11 +30881,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -31155,11 +31015,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -31237,11 +31093,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -31393,11 +31245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -31550,11 +31398,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -31707,11 +31551,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -31812,11 +31652,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); @@ -31845,11 +31681,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); @@ -31891,11 +31723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -33418,11 +33246,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -33556,11 +33380,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -33694,11 +33514,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -33832,11 +33648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -35468,11 +35280,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -35606,11 +35414,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -35744,11 +35548,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -35882,11 +35682,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -37974,11 +37770,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -38112,11 +37904,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -38250,11 +38038,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -38388,11 +38172,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -42183,11 +41963,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -42321,11 +42097,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -42459,11 +42231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -42597,11 +42365,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -42679,11 +42443,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -42835,11 +42595,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -42992,11 +42748,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -43149,11 +42901,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -43254,11 +43002,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); @@ -43287,11 +43031,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); @@ -46062,11 +45802,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -46200,11 +45936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -46338,11 +46070,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -46476,11 +46204,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -46558,11 +46282,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -46714,11 +46434,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -46871,11 +46587,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47028,11 +46740,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -48056,11 +47764,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); @@ -48089,11 +47793,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); @@ -48152,11 +47852,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); @@ -48185,11 +47881,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); @@ -48231,11 +47923,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -48634,11 +48322,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -48790,11 +48474,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -48947,11 +48627,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -49104,11 +48780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -49592,11 +49264,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLE ZVAL_UNDEF(var); SAVE_OPLINE(); - if (!GC_DELREF(garbage)) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZVAL_UNDEF(var); @@ -51547,11 +51215,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -51685,11 +51349,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -51823,11 +51483,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -51961,11 +51617,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ exit_assign_obj: if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } @@ -52043,11 +51695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -52199,11 +51847,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -52356,11 +52000,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -52513,11 +52153,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -52618,11 +52254,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); @@ -52651,11 +52283,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ ZVAL_COPY(EX_VAR(opline->result.var), value); } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root_no_ref(garbage); - } + GC_DTOR_NO_REF(garbage); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); @@ -52697,11 +52325,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( } if (garbage) { - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { - gc_check_possible_root(garbage); - } + GC_DTOR(garbage); }