]> granicus.if.org Git - php/commitdiff
micro-optimization
authorDmitry Stogov <dmitry@zend.com>
Thu, 20 Aug 2020 12:02:12 +0000 (15:02 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 20 Aug 2020 12:02:12 +0000 (15:02 +0300)
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index f06713d5ac8abfbf835111d6dd19e768454a62ba..55a1e9ba8671c90de8cdf72ff9b87a1bb4fc5842 100644 (file)
@@ -3428,8 +3428,17 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
                do {
                        if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (OP1_TYPE & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -3473,7 +3482,9 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
                        FREE_OP2();
-                       FREE_OP1();
+                       if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (OP2_TYPE == IS_CONST &&
@@ -3482,8 +3493,10 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -3496,10 +3509,11 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               FREE_OP1();
-
-               if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -3507,12 +3521,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
        } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (OP1_TYPE == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
index f103e91d331a523319386c38fa40ac8420c7d6ac..70506a6e1417b97dab8e5ab6b8507b775feeb82d 100644 (file)
@@ -5743,8 +5743,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                do {
                        if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CONST & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -5788,7 +5797,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CONST == IS_CONST &&
@@ -5797,8 +5808,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -5811,9 +5824,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -5821,12 +5836,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -8018,8 +8027,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                do {
                        if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CONST & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -8063,7 +8081,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
                        zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
+                       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
@@ -8072,8 +8092,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -8086,9 +8108,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -8096,12 +8120,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -10386,8 +10404,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                do {
                        if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CONST & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -10431,7 +10458,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CV == IS_CONST &&
@@ -10440,8 +10469,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -10454,9 +10485,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -10464,12 +10497,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -14746,8 +14773,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                do {
                        if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if ((IS_TMP_VAR|IS_VAR) & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -14791,7 +14827,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-                       zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
+                       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CONST == IS_CONST &&
@@ -14800,8 +14838,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -14814,10 +14854,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
-
-               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -14825,12 +14866,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -16153,8 +16188,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                do {
                        if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if ((IS_TMP_VAR|IS_VAR) & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -16198,7 +16242,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
                        zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-                       zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
+                       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
@@ -16207,8 +16253,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -16221,10 +16269,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
-
-               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -16232,12 +16281,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -17453,8 +17496,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                do {
                        if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if ((IS_TMP_VAR|IS_VAR) & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -17498,7 +17550,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-                       zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
+                       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CV == IS_CONST &&
@@ -17507,8 +17561,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -17521,10 +17577,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
-
-               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -17532,12 +17589,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -31478,8 +31529,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                do {
                        if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_UNUSED & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -31523,7 +31583,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CONST == IS_CONST &&
@@ -31532,8 +31594,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -31546,9 +31610,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -31556,12 +31622,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -33374,8 +33434,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                do {
                        if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_UNUSED & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -33419,7 +33488,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
                        zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
+                       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
@@ -33428,8 +33499,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -33442,9 +33515,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -33452,12 +33527,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -35848,8 +35917,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                do {
                        if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_UNUSED & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -35893,7 +35971,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CV == IS_CONST &&
@@ -35902,8 +35982,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -35916,9 +35998,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -35926,12 +36010,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -40514,8 +40592,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                do {
                        if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CV & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -40559,7 +40646,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CONST == IS_CONST &&
@@ -40568,8 +40657,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -40582,9 +40673,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -40592,12 +40685,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -44086,8 +44173,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                do {
                        if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CV & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -44131,7 +44227,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
                        zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
+                       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
@@ -44140,8 +44238,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -44154,9 +44254,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -44164,12 +44266,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
@@ -49195,8 +49291,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
                do {
                        if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                                if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
-                                       object = Z_REFVAL_P(object);
+                                       zend_reference *ref = Z_REF_P(object);
+
+                                       object = &ref->val;
                                        if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               if (IS_CV & IS_VAR) {
+                                                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                                                               efree_size(ref, sizeof(zend_reference));
+                                                       } else {
+                                                               Z_ADDREF_P(object);
+                                                       }
+                                               }
                                                break;
                                        }
                                }
@@ -49240,7 +49345,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
                                zend_undefined_method(obj->ce, Z_STR_P(function_name));
                        }
 
-
+                       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                        HANDLE_EXCEPTION();
                }
                if (IS_CV == IS_CONST &&
@@ -49249,8 +49356,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
-                       /* Reset "object" to trigger reference counting */
-                       object = NULL;
+                       GC_ADDREF(obj); /* For $this pointer */
+                       if (GC_DELREF(orig_obj) == 0) {
+                               zend_objects_store_del(orig_obj);
+                       }
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
                        init_func_run_time_cache(&fbc->op_array);
@@ -49263,9 +49372,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
 
        call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-
-               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
-                       HANDLE_EXCEPTION();
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
+                       zend_objects_store_del(obj);
+                       if (UNEXPECTED(EG(exception))) {
+                               HANDLE_EXCEPTION();
+                       }
                }
                /* call static method */
                obj = (zend_object*)called_scope;
@@ -49273,12 +49384,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
-               } else {
-                       zval *free_op1 = EX_VAR(opline->op1.var);
-                       if (free_op1 != object) {
-                               GC_ADDREF(obj); /* For $this pointer */
-                               zval_ptr_dtor_nogc(free_op1);
-                       }
                }
                /* CV may be changed indirectly (e.g. when it's a reference) */
                call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;