From: Dmitry Stogov Date: Tue, 26 Dec 2017 10:30:25 +0000 (+0300) Subject: Cheaper reference construction X-Git-Tag: php-7.3.0alpha1~737 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=efcbea43455ca4e27ec6fc5ce2f3a740a981247e;p=php Cheaper reference construction --- diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index ef83622ba8..47750b8f3c 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -896,18 +896,24 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent do { dst--; src--; - ZVAL_MAKE_REF(src); - ZVAL_COPY_VALUE(dst, src); - Z_ADDREF_P(dst); + if (Z_ISREF_P(src)) { + Z_ADDREF_P(src); + } else { + ZVAL_MAKE_REF_EX(src, 2); + } + ZVAL_REF(dst, Z_REF_P(src)); } while (dst != end); } else if (ce->type == ZEND_USER_CLASS) { src = parent_ce->default_static_members_table + parent_ce->default_static_members_count; do { dst--; src--; - ZVAL_MAKE_REF(src); - ZVAL_COPY_VALUE(dst, src); - Z_ADDREF_P(dst); + if (Z_ISREF_P(src)) { + Z_ADDREF_P(src); + } else { + ZVAL_MAKE_REF_EX(src, 2); + } + ZVAL_REF(dst, Z_REF_P(src)); if (Z_TYPE_P(Z_REFVAL_P(dst)) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 6e7a1f3eee..0ccc92425c 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -808,6 +808,17 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \ } while (0) +#define ZVAL_MAKE_REF_EX(z, refcount) do { \ + zval *_z = (z); \ + zend_reference *_ref = \ + (zend_reference *) emalloc(sizeof(zend_reference)); \ + GC_SET_REFCOUNT(_ref, (refcount)); \ + GC_TYPE_INFO(_ref) = IS_REFERENCE; \ + ZVAL_COPY_VALUE(&_ref->val, _z); \ + Z_REF_P(_z) = _ref; \ + Z_TYPE_INFO_P(_z) = IS_REFERENCE_EX; \ + } while (0) + #define ZVAL_NEW_PERSISTENT_REF(z, r) do { \ zend_reference *_ref = \ (zend_reference *) malloc(sizeof(zend_reference)); \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 021e0153c3..287c36498f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3914,8 +3914,11 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) } if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } @@ -4305,12 +4308,10 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM) if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); } else { - ZVAL_NEW_REF(arg, varptr); - Z_ADDREF_P(arg); - ZVAL_REF(varptr, Z_REF_P(arg)); + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -4411,8 +4412,11 @@ ZEND_VM_C_LABEL(send_again): top = ZEND_CALL_ARG(EX(call), arg_num); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { if (Z_REFCOUNT_P(args) == 1) { - ZVAL_MAKE_REF(arg); - Z_ADDREF_P(arg); + if (Z_ISREF_P(arg)) { + Z_ADDREF_P(arg); + } else { + ZVAL_MAKE_REF_EX(arg, 2); + } ZVAL_REF(top, Z_REF_P(arg)); } else { ZVAL_DUP(top, arg); @@ -5116,8 +5120,11 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } FREE_OP1_VAR_PTR(); } else { expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -7266,10 +7273,15 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); FREE_OP1_VAR_PTR(); } @@ -7568,12 +7580,8 @@ ZEND_VM_C_LABEL(check_indirect): } if (UNEXPECTED(!Z_ISREF_P(value))) { - ref = (zend_reference*)emalloc(sizeof(zend_reference)); - GC_SET_REFCOUNT(ref, 2); - GC_TYPE_INFO(ref) = IS_REFERENCE; - ZVAL_COPY_VALUE(&ref->val, value); - Z_REF_P(value) = ref; - Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; + ZVAL_MAKE_REF_EX(value, 2); + ref = Z_REF_P(value); } else { ref = Z_REF_P(value); GC_ADDREF(ref); @@ -7912,8 +7920,11 @@ ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF) if (opline->extended_value) { /* By-ref binding */ var = GET_OP2_ZVAL_PTR(BP_VAR_W); - ZVAL_MAKE_REF(var); - Z_ADDREF_P(var); + if (Z_ISREF_P(var)) { + Z_ADDREF_P(var); + } else { + ZVAL_MAKE_REF_EX(var, 2); + } } else { var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (UNEXPECTED(Z_ISUNDEF_P(var))) { @@ -8034,15 +8045,20 @@ ZEND_VM_HANDLER(51, ZEND_MAKE_REF, VAR|CV, UNUSED) ZVAL_NULL(Z_REFVAL_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { - ZVAL_MAKE_REF(op1); - ZVAL_COPY(EX_VAR(opline->result.var), op1); + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); + } else { + ZVAL_MAKE_REF_EX(op1, 2); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { - ZVAL_MAKE_REF(op1); + ZVAL_MAKE_REF_EX(op1, 2); + } else { + GC_ADDREF(Z_REF_P(op1)); } - GC_ADDREF(Z_REF_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 426877bf2c..927bde994a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1235,8 +1235,11 @@ send_again: top = ZEND_CALL_ARG(EX(call), arg_num); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { if (Z_REFCOUNT_P(args) == 1) { - ZVAL_MAKE_REF(arg); - Z_ADDREF_P(arg); + if (Z_ISREF_P(arg)) { + Z_ADDREF_P(arg); + } else { + ZVAL_MAKE_REF_EX(arg, 2); + } ZVAL_REF(top, Z_REF_P(arg)); } else { ZVAL_DUP(top, arg); @@ -3012,8 +3015,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL } if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } @@ -5830,8 +5836,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = RT_CONSTANT(opline, opline->op1); @@ -6339,10 +6348,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -8014,8 +8028,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = RT_CONSTANT(opline, opline->op1); @@ -8391,10 +8408,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -8743,10 +8765,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -9300,8 +9327,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = RT_CONSTANT(opline, opline->op1); @@ -9700,10 +9730,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -11240,8 +11275,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = RT_CONSTANT(opline, opline->op1); @@ -11568,10 +11606,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -18625,8 +18668,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER } if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } @@ -19601,8 +19647,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -19753,10 +19802,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -20030,8 +20084,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -20218,10 +20275,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -20354,10 +20416,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -20527,8 +20594,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -20679,10 +20749,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -21012,8 +21087,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -21164,10 +21242,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -21261,8 +21344,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDL if (opline->extended_value) { /* By-ref binding */ var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); - ZVAL_MAKE_REF(var); - Z_ADDREF_P(var); + if (Z_ISREF_P(var)) { + Z_ADDREF_P(var); + } else { + ZVAL_MAKE_REF_EX(var, 2); + } } else { var = _get_zval_ptr_cv_undef(opline->op2.var EXECUTE_DATA_CC); if (UNEXPECTED(Z_ISUNDEF_P(var))) { @@ -21613,8 +21699,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER } if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } @@ -21865,12 +21954,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); } else { - ZVAL_NEW_REF(arg, varptr); - Z_ADDREF_P(arg); - ZVAL_REF(varptr, Z_REF_P(arg)); + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; ZEND_VM_NEXT_OPCODE(); @@ -25137,8 +25224,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25416,10 +25506,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } @@ -27436,8 +27531,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -27809,10 +27907,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } @@ -28096,10 +28199,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } @@ -28994,8 +29102,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29161,10 +29272,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } @@ -29260,15 +29376,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL ZVAL_NULL(Z_REFVAL_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { - ZVAL_MAKE_REF(op1); - ZVAL_COPY(EX_VAR(opline->result.var), op1); + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); + } else { + ZVAL_MAKE_REF_EX(op1, 2); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { - ZVAL_MAKE_REF(op1); + ZVAL_MAKE_REF_EX(op1, 2); + } else { + GC_ADDREF(Z_REF_P(op1)); } - GC_ADDREF(Z_REF_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); @@ -31373,8 +31494,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -31652,10 +31776,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } @@ -33754,10 +33883,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -35467,10 +35601,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -35603,10 +35742,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -35944,10 +36088,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -37807,10 +37956,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -38461,8 +38615,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( } if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } @@ -38613,12 +38770,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_ if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); } else { - ZVAL_NEW_REF(arg, varptr); - Z_ADDREF_P(arg); - ZVAL_REF(varptr, Z_REF_P(arg)); + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); ZEND_VM_NEXT_OPCODE(); } @@ -42750,8 +42905,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS if ((IS_CV == IS_VAR || IS_CV == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -43403,10 +43561,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -43540,12 +43703,8 @@ check_indirect: } if (UNEXPECTED(!Z_ISREF_P(value))) { - ref = (zend_reference*)emalloc(sizeof(zend_reference)); - GC_SET_REFCOUNT(ref, 2); - GC_TYPE_INFO(ref) = IS_REFERENCE; - ZVAL_COPY_VALUE(&ref->val, value); - Z_REF_P(value) = ref; - Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; + ZVAL_MAKE_REF_EX(value, 2); + ref = Z_REF_P(value); } else { ref = Z_REF_P(value); GC_ADDREF(ref); @@ -46718,8 +46877,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV if ((IS_CV == IS_VAR || IS_CV == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -47316,10 +47478,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -47866,10 +48033,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -48837,8 +49009,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS if ((IS_CV == IS_VAR || IS_CV == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -49305,10 +49480,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { @@ -49416,15 +49596,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE ZVAL_NULL(Z_REFVAL_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { - ZVAL_MAKE_REF(op1); - ZVAL_COPY(EX_VAR(opline->result.var), op1); + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); + } else { + ZVAL_MAKE_REF_EX(op1, 2); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { - ZVAL_MAKE_REF(op1); + ZVAL_MAKE_REF_EX(op1, 2); + } else { + GC_ADDREF(Z_REF_P(op1)); } - GC_ADDREF(Z_REF_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); @@ -52608,8 +52793,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H if ((IS_CV == IS_VAR || IS_CV == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -53063,10 +53251,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); } else { - ZVAL_MAKE_REF(value_ptr); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } - ZVAL_COPY(&generator->value, value_ptr); } } else { diff --git a/ext/standard/array.c b/ext/standard/array.c index 6eb71efa92..afb2d2c153 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1763,10 +1763,13 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t } continue; } - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); count++; } } ZEND_HASH_FOREACH_END(); @@ -1848,13 +1851,19 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t if (zend_string_equals_literal(var_name, "GLOBALS")) { continue; } - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } zend_hash_add_new(symbol_table, var_name, entry); } count++; @@ -1925,9 +1934,12 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); if (Z_TYPE_P(orig_var) == IS_UNDEF) { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); - ZVAL_COPY_VALUE(orig_var, entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } + ZVAL_REF(orig_var, Z_REF_P(entry)); count++; continue; } @@ -1940,14 +1952,17 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s zend_throw_error(NULL, "Cannot re-assign $this"); } } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); } else { zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } @@ -2034,9 +2049,12 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); if (Z_TYPE_P(orig_var) == IS_UNDEF) { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); - ZVAL_COPY_VALUE(orig_var, entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } + ZVAL_REF(orig_var, Z_REF_P(entry)); count++; continue; } @@ -2049,14 +2067,17 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol zend_throw_error(NULL, "Cannot re-assign $this"); } } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); } else { zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } @@ -2075,8 +2096,11 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol } continue; } - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } zend_hash_add_new(symbol_table, var_name, entry); count++; } @@ -2183,14 +2207,17 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ zend_throw_error(NULL, "Cannot re-assign $this"); } } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); } else { zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } @@ -2286,14 +2313,17 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym zend_throw_error(NULL, "Cannot re-assign $this"); } } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); - ZVAL_COPY_VALUE(orig_var, entry); + ZVAL_REF(orig_var, Z_REF_P(entry)); } else { zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } @@ -2387,15 +2417,21 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); if (Z_TYPE_P(orig_var) == IS_UNDEF) { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); - ZVAL_COPY_VALUE(orig_var, entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } + ZVAL_REF(orig_var, Z_REF_P(entry)); count++; } } } else { - ZVAL_MAKE_REF(entry); - Z_ADDREF_P(entry); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); + } else { + ZVAL_MAKE_REF_EX(entry, 2); + } zend_hash_add_new(symbol_table, var_name, entry); count++; }