]> granicus.if.org Git - php/commitdiff
Optimized unset()
authorDmitry Stogov <dmitry@zend.com>
Mon, 22 Sep 2014 10:41:44 +0000 (14:41 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 22 Sep 2014 10:41:44 +0000 (14:41 +0400)
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 4931972c5c742e72baec7adfd7d05a1029b79090..873c9f478db0d114c05b1a16b6693003e8239805 100644 (file)
@@ -4251,29 +4251,37 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (OP1_TYPE == IS_CV &&
            OP2_TYPE == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
 
+       ZVAL_UNDEF(&tmp);
        if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (OP2_TYPE != IS_UNUSED) {
@@ -4285,10 +4293,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (OP1_TYPE != IS_CONST && tmp_is_dup) {
+                                       if (OP1_TYPE != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        FREE_OP1();
                                        HANDLE_EXCEPTION();
@@ -4307,10 +4313,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (OP1_TYPE != IS_CONST && tmp_is_dup) {
+       if (OP1_TYPE != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        FREE_OP1();
        CHECK_EXCEPTION();
@@ -4351,12 +4355,9 @@ ZEND_VM_C_LABEL(num_index_dim):
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (OP2_TYPE != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       ZEND_VM_C_GOTO(numeric_index_dim);
+                                                       ZEND_VM_C_GOTO(num_index_dim);
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -4364,15 +4365,6 @@ ZEND_VM_C_LABEL(num_index_dim):
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-ZEND_VM_C_LABEL(numeric_index_dim):
-                                       zend_hash_index_del(ht, hval);
-                                       if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
index 7b6cc11d8349a290b8aa6ae6bfceb4d30201d99a..a2b547544dc0616985a282ba77ae3b254d77297a 100644 (file)
@@ -4440,29 +4440,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CONST == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = opline->op1.zv;
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_CONST != IS_UNUSED) {
@@ -4474,10 +4482,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CONST != IS_CONST && tmp_is_dup) {
+                                       if (IS_CONST != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -4496,10 +4502,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CONST != IS_CONST && tmp_is_dup) {
+       if (IS_CONST != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -6834,29 +6838,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CONST == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = opline->op1.zv;
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_VAR != IS_UNUSED) {
@@ -6868,10 +6880,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CONST != IS_CONST && tmp_is_dup) {
+                                       if (IS_CONST != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -6890,10 +6900,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CONST != IS_CONST && tmp_is_dup) {
+       if (IS_CONST != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -7699,29 +7707,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CONST == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = opline->op1.zv;
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_UNUSED != IS_UNUSED) {
@@ -7733,10 +7749,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CONST != IS_CONST && tmp_is_dup) {
+                                       if (IS_CONST != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -7755,10 +7769,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CONST != IS_CONST && tmp_is_dup) {
+       if (IS_CONST != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -11028,29 +11040,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_TMP_VAR == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_CONST != IS_UNUSED) {
@@ -11062,10 +11082,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_TMP_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_dtor(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -11084,10 +11102,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_TMP_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_dtor(free_op1.var);
        CHECK_EXCEPTION();
@@ -13303,29 +13319,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_TMP_VAR == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_VAR != IS_UNUSED) {
@@ -13337,10 +13361,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_TMP_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_dtor(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -13359,10 +13381,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_TMP_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_dtor(free_op1.var);
        CHECK_EXCEPTION();
@@ -14052,29 +14072,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_TMP_VAR == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_UNUSED != IS_UNUSED) {
@@ -14086,10 +14114,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_TMP_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_dtor(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -14108,10 +14134,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_TMP_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_dtor(free_op1.var);
        CHECK_EXCEPTION();
@@ -18822,29 +18846,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_VAR == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_CONST != IS_UNUSED) {
@@ -18856,10 +18888,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_ptr_dtor_nogc(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -18878,10 +18908,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_ptr_dtor_nogc(free_op1.var);
        CHECK_EXCEPTION();
@@ -18922,12 +18950,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CONST != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -18935,15 +18960,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -20984,12 +21000,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_TMP_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -20997,15 +21010,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -23155,29 +23159,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_VAR == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_VAR != IS_UNUSED) {
@@ -23189,10 +23201,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_ptr_dtor_nogc(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -23211,10 +23221,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_ptr_dtor_nogc(free_op1.var);
        CHECK_EXCEPTION();
@@ -23255,12 +23263,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -23268,15 +23273,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -24614,29 +24610,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
        zval tmp, *varname;
        HashTable *target_symbol_table;
        zend_free_op free_op1;
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_VAR == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_UNUSED != IS_UNUSED) {
@@ -24648,10 +24652,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_VAR != IS_CONST && tmp_is_dup) {
+                                       if (IS_VAR != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
                                        zval_ptr_dtor_nogc(free_op1.var);
                                        HANDLE_EXCEPTION();
@@ -24670,10 +24672,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_VAR != IS_CONST && tmp_is_dup) {
+       if (IS_VAR != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
        zval_ptr_dtor_nogc(free_op1.var);
        CHECK_EXCEPTION();
@@ -26559,12 +26559,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CV != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -26572,15 +26569,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -28024,12 +28012,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CONST != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -28037,15 +28022,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -29309,12 +29285,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_TMP_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -29322,15 +29295,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -30596,12 +30560,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -30609,15 +30570,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -32392,12 +32344,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CV != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -32405,15 +32354,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -35789,29 +35729,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CV == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_CONST != IS_UNUSED) {
@@ -35823,10 +35771,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CV != IS_CONST && tmp_is_dup) {
+                                       if (IS_CV != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -35845,10 +35791,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CV != IS_CONST && tmp_is_dup) {
+       if (IS_CV != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -35889,12 +35833,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CONST != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -35902,15 +35843,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -37889,12 +37821,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_TMP_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -37902,15 +37831,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -39940,29 +39860,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CV == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_VAR != IS_UNUSED) {
@@ -39974,10 +39902,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CV != IS_CONST && tmp_is_dup) {
+                                       if (IS_CV != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -39996,10 +39922,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CV != IS_CONST && tmp_is_dup) {
+       if (IS_CV != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -40040,12 +39964,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_VAR != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -40053,15 +39974,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());
@@ -41281,29 +41193,37 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
        zval tmp, *varname;
        HashTable *target_symbol_table;
 
-       zend_bool tmp_is_dup = 0;
 
        SAVE_OPLINE();
        if (IS_CV == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-           ZVAL_COPY_VALUE(&tmp, EX_VAR(opline->op1.var));
-               ZVAL_UNDEF(EX_VAR(opline->op1.var));
-               zval_ptr_dtor(&tmp);
+               zval *var = EX_VAR(opline->op1.var);
+
+               if (Z_REFCOUNTED_P(var)) {
+                       zend_refcounted *garbage = Z_COUNTED_P(var);
+
+                       if (!--GC_REFCOUNT(garbage)) {
+                               ZVAL_UNDEF(var);
+                               _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
+                       } else {
+                               GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
+                               ZVAL_UNDEF(var);
+                       }
+               } else {
+                       ZVAL_UNDEF(var);
+               }
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
 
        varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
 
+       ZVAL_UNDEF(&tmp);
        if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
                ZVAL_DUP(&tmp, varname);
                convert_to_string(&tmp);
                varname = &tmp;
-               tmp_is_dup = 1;
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               ZVAL_COPY(&tmp, varname);
-               varname = &tmp;
        }
 
        if (IS_UNUSED != IS_UNUSED) {
@@ -41315,10 +41235,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
                        } else {
                                ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
-                                       if (IS_CV != IS_CONST && tmp_is_dup) {
+                                       if (IS_CV != IS_CONST) {
                                                zval_dtor(&tmp);
-                                       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-                                               zval_ptr_dtor(&tmp);
                                        }
 
                                        HANDLE_EXCEPTION();
@@ -41337,10 +41255,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
                zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
-       if (IS_CV != IS_CONST && tmp_is_dup) {
+       if (IS_CV != IS_CONST) {
                zval_dtor(&tmp);
-       } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-               zval_ptr_dtor(&tmp);
        }
 
        CHECK_EXCEPTION();
@@ -43088,12 +43004,9 @@ num_index_dim:
                                        zend_hash_index_del(ht, hval);
                                        break;
                                case IS_STRING:
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               if (Z_REFCOUNTED_P(offset)) Z_ADDREF_P(offset);
-                                       }
                                        if (IS_CV != IS_CONST) {
                                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
-                                                       goto numeric_index_dim;
+                                                       goto num_index_dim;
                                                }
                                        }
                                        if (ht == &EG(symbol_table).ht) {
@@ -43101,15 +43014,6 @@ num_index_dim:
                                        } else {
                                                zend_hash_del(ht, Z_STR_P(offset));
                                        }
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
-                                       break;
-numeric_index_dim:
-                                       zend_hash_index_del(ht, hval);
-                                       if (IS_CV == IS_CV || IS_CV == IS_VAR) {
-                                               zval_ptr_dtor(offset);
-                                       }
                                        break;
                                case IS_NULL:
                                        zend_hash_del(ht, STR_EMPTY_ALLOC());