]> granicus.if.org Git - php/commitdiff
Cheaper reference construction
authorDmitry Stogov <dmitry@zend.com>
Tue, 26 Dec 2017 10:30:25 +0000 (13:30 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 26 Dec 2017 10:30:25 +0000 (13:30 +0300)
Zend/zend_inheritance.c
Zend/zend_types.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/standard/array.c

index ef83622ba8632d733acdc624937fb827b7a408a8..47750b8f3c93e1edceebb92cc309f802a6d476f1 100644 (file)
@@ -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;
                                }
index 6e7a1f3eee1306116e87c6a8c361d7757283364f..0ccc92425caaf265cdc81d2fa8efb6e0284db89c 100644 (file)
@@ -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));              \
index 021e0153c3c6208e8efa267eddb80f27b0fc31af..287c36498f125ba37a43c2b91edbfb25d702a8e2 100644 (file)
@@ -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);
index 426877bf2c2df7cdd4590f98ab33c789c6544f3e..927bde994a81aecefb99b8047846f96e8d1c727b 100644 (file)
@@ -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 {
index 6eb71efa922d5932c29cc7e5e8f64abd25540ee4..afb2d2c153ddd7ad520cfe34836a109b2d4fd19e 100644 (file)
@@ -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++;
                }