]> granicus.if.org Git - php/commitdiff
Fixed bug #72543 (Different references behavior comparing to PHP 5)
authorDmitry Stogov <dmitry@zend.com>
Wed, 6 Jul 2016 17:46:43 +0000 (20:46 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 6 Jul 2016 17:46:43 +0000 (20:46 +0300)
NEWS
Zend/tests/bug72543.phpt [new file with mode: 0644]
Zend/tests/bug72543_1.phpt [new file with mode: 0644]
Zend/tests/bug72543_2.phpt [new file with mode: 0644]
Zend/tests/bug72543_3.phpt [new file with mode: 0644]
Zend/tests/bug72543_4.phpt [new file with mode: 0644]
Zend/tests/bug72543_5.phpt [new file with mode: 0644]
Zend/zend_types.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 470052bd2bc48d4624fb13c1d429e499be6ffeea..e3af5613f800d1e6f8e2dab2d36a586812d61a52 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2016, PHP 7.1.0beta1
 
+- Core:
+  . Fixed bug #72543 (Different references behavior comparing to PHP 5)
+    (Laruence, Dmitry, Nikita)
+
 - pcntl
   . Implemented asynchronous signal handling without TICKS. (Dmitry)
 
diff --git a/Zend/tests/bug72543.phpt b/Zend/tests/bug72543.phpt
new file mode 100644 (file)
index 0000000..4244b8c
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Bug #72543 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+function create_references(&$array) {
+    foreach ($array as $key => $value) {
+        create_references($array[$key]);
+    }
+}  
+
+function change_copy($copy) {
+        $copy['b']['z']['z'] = $copy['b'];
+}  
+
+$data = [
+    'a' => [
+        'b' => [],
+    ], 
+]; 
+create_references($data);
+$copy = $data['a'];
+var_dump($copy);
+
+change_copy($copy);
+var_dump($copy); //RECURSION
+?>
+--EXPECT--
+array(1) {
+  ["b"]=>
+  array(0) {
+  }
+}
+array(1) {
+  ["b"]=>
+  array(0) {
+  }
+}
diff --git a/Zend/tests/bug72543_1.phpt b/Zend/tests/bug72543_1.phpt
new file mode 100644 (file)
index 0000000..f63ee7f
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #72543.1 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [];
+$arr[0] = null;
+$ref =& $arr[0];
+unset($ref);
+$arr[0][0] = $arr[0];
+var_dump($arr);
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  array(1) {
+    [0]=>
+    NULL
+  }
+}
diff --git a/Zend/tests/bug72543_2.phpt b/Zend/tests/bug72543_2.phpt
new file mode 100644 (file)
index 0000000..2070d65
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #72543.2 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [];
+$arr[0] = null;
+$ref =& $arr[0];
+unset($ref);
+$arr[0][$arr[0]] = null;
+var_dump($arr);
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  array(1) {
+    [""]=>
+    NULL
+  }
+}
diff --git a/Zend/tests/bug72543_3.phpt b/Zend/tests/bug72543_3.phpt
new file mode 100644 (file)
index 0000000..3835faf
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Bug #72543.3 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$x = new stdClass;
+$x->a = 1;
+$ref =& $x->a;
+unset($ref);
+var_dump($x->a + ($x->a = 2));
+?>
+--EXPECT--
+int(3)
diff --git a/Zend/tests/bug72543_4.phpt b/Zend/tests/bug72543_4.phpt
new file mode 100644 (file)
index 0000000..3480c1c
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+Bug #72543.4 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [1];
+$ref =& $arr[0];
+unset($ref);
+var_dump($arr[0] + ($arr[0] = 2));
+?>
+--EXPECT--
+int(3)
diff --git a/Zend/tests/bug72543_5.phpt b/Zend/tests/bug72543_5.phpt
new file mode 100644 (file)
index 0000000..66b3b75
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Bug #72543.5 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [1];
+$ref =& $arr[0];
+var_dump($arr[0] + ($arr[0] = 2));
+?>
+--EXPECT--
+int(4)
index 95c4ef6e549fb05abc045b30966d783cfb3fd7fb..29dec8e97f84565595aba0939a3371e986753e40 100644 (file)
@@ -917,6 +917,23 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
                efree_size(ref, sizeof(zend_reference));                \
        } while (0)
 
+#define ZVAL_COPY_UNREF(z, v) do {                                             \
+               zval *_z3 = (v);                                                                \
+               if (Z_REFCOUNTED_P(_z3)) {                                              \
+                       if (UNEXPECTED(Z_ISREF_P(_z3))                          \
+                        && UNEXPECTED(Z_REFCOUNT_P(_z3) == 1)) {       \
+                               ZVAL_UNREF(_z3);                                                \
+                               if (Z_REFCOUNTED_P(_z3)) {                              \
+                                       Z_ADDREF_P(_z3);                                        \
+                               }                                                                               \
+                       } else {                                                                        \
+                               Z_ADDREF_P(_z3);                                                \
+                       }                                                                                       \
+               }                                                                                               \
+               ZVAL_COPY_VALUE(z, _z3);                                                \
+       } while (0)
+
+
 #define SEPARATE_STRING(zv) do {                                               \
                zval *_zv = (zv);                                                               \
                if (Z_REFCOUNTED_P(_zv) &&                                              \
index f8082f91cf617b3e678fba3364da345881310354..f39ce0ec6ad892886411837b9c7b6a9d2553909f 100644 (file)
@@ -1557,10 +1557,7 @@ ZEND_VM_C_LABEL(fetch_this):
 
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -1698,10 +1695,7 @@ ZEND_VM_HELPER(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR,
 ZEND_VM_C_LABEL(fetch_static_prop_return):
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -1758,7 +1752,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
 ZEND_VM_C_LABEL(fetch_dim_r_array):
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -1928,13 +1922,13 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -1948,7 +1942,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_no_object):
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -4886,14 +4880,6 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
        SAVE_OPLINE();
        if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((OP1_TYPE & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -8537,7 +8523,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_array):
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, ZEND_VM_C_LABEL(fetch_dim_r_index_undef));
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
                        FREE_OP1();
index a495b59000298aa920505459057aabba6c88b4af..803414ac9da6ae10fbbd5766977820bf5468e280 100644 (file)
@@ -4816,10 +4816,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -4876,7 +4873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_H
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -4992,13 +4989,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_H
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -5012,7 +5009,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -5605,14 +5602,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(
        SAVE_OPLINE();
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CONST & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -6330,7 +6319,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CONST & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -6661,10 +6650,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -7100,10 +7086,7 @@ fetch_this:
 
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -7239,10 +7222,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -8728,7 +8708,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -8844,13 +8824,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HAND
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -8864,7 +8844,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -9507,14 +9487,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEN
        SAVE_OPLINE();
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CONST & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -9979,7 +9951,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CONST & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -10625,7 +10597,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -10741,13 +10713,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -10761,7 +10733,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -11358,14 +11330,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER
        SAVE_OPLINE();
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CONST & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -11696,7 +11660,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CONST & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -13196,13 +13160,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HAN
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -13216,7 +13180,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -14415,13 +14379,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLE
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -14435,7 +14399,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -14936,13 +14900,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HA
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -14956,7 +14920,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -18286,13 +18250,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HAN
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -18306,7 +18270,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -23044,13 +23008,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLE
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -23064,7 +23028,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -25988,13 +25952,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HA
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -26008,7 +25972,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -28189,13 +28153,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -28209,7 +28173,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -30879,13 +30843,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -30899,7 +30863,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -32768,13 +32732,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -32788,7 +32752,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -37609,10 +37573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -37669,7 +37630,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -37839,13 +37800,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HAND
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -37859,7 +37820,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -39357,14 +39318,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEN
        SAVE_OPLINE();
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CV & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -40288,7 +40241,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CV & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -40675,10 +40628,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -41592,10 +41542,7 @@ fetch_this:
 
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -41731,10 +41678,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -44515,7 +44459,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -44685,13 +44629,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -44705,7 +44649,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -46256,14 +46200,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_O
        SAVE_OPLINE();
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CV & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -46857,7 +46793,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CV & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -48524,7 +48460,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -48694,13 +48630,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN
                        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
                                retval = OBJ_PROP(zobj, prop_offset);
                                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        } else if (EXPECTED(zobj->properties != NULL)) {
                                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
                                if (EXPECTED(retval)) {
-                                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                                       ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                                        break;
                                }
                        }
@@ -48714,7 +48650,7 @@ fetch_obj_r_no_object:
                        retval = zobj->handlers->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
 
                        if (retval != EX_VAR(opline->result.var)) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+                               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
                        }
                }
        } while (0);
@@ -50159,14 +50095,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZE
        SAVE_OPLINE();
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if ((IS_CV & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -50628,7 +50556,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if (IS_CV & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
 
@@ -51887,10 +51815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -51947,7 +51872,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -52313,14 +52238,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER
        SAVE_OPLINE();
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if (((IS_TMP_VAR|IS_VAR) & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -52720,7 +52637,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
                        zval_ptr_dtor_nogc(free_op1);
@@ -52846,10 +52763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -53202,10 +53116,7 @@ fetch_this:
 
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -53343,10 +53254,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
 fetch_static_prop_return:
        ZEND_ASSERT(retval != NULL);
        if (type == BP_VAR_R || type == BP_VAR_IS) {
-               if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
-                       ZVAL_UNREF(retval);
-               }
-               ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
        } else {
                ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
        }
@@ -54310,7 +54218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HAN
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -54676,14 +54584,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE
        SAVE_OPLINE();
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if (((IS_TMP_VAR|IS_VAR) & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -54890,7 +54790,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
                        zval_ptr_dtor_nogc(free_op1);
@@ -55536,7 +55436,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR
 fetch_dim_r_array:
                        value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R);
                        result = EX_VAR(opline->result.var);
-                       ZVAL_COPY(result, value);
+                       ZVAL_COPY_UNREF(result, value);
                } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
                        container = Z_REFVAL_P(container);
                        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -55904,14 +55804,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE
        SAVE_OPLINE();
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
                op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
-       } else if (((IS_TMP_VAR|IS_VAR) & IS_VAR) && UNEXPECTED(Z_ISREF_P(op1))) {
-               /* Don't keep lock on reference, lock the value instead */
-               if (UNEXPECTED(Z_REFCOUNT_P(op1) == 1)) {
-                       ZVAL_UNREF(op1);
-               } else {
-                       Z_DELREF_P(op1);
-                       ZVAL_COPY(op1, Z_REFVAL_P(op1));
-               }
        }
        if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
                op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
@@ -56119,7 +56011,7 @@ fetch_dim_r_index_array:
                        offset = zval_get_long(dim);
                }
                ZEND_HASH_INDEX_FIND(Z_ARRVAL_P(container), offset, value, fetch_dim_r_index_undef);
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
+               ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value);
                if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) {
                        SAVE_OPLINE();
                        zval_ptr_dtor_nogc(free_op1);