]> granicus.if.org Git - php/commitdiff
Improved fast path locality
authorDmitry Stogov <dmitry@zend.com>
Thu, 7 May 2015 14:26:35 +0000 (17:26 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 7 May 2015 14:26:35 +0000 (17:26 +0300)
Zend/zend_execute.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 9e8dde5c3c505a1aff32bf21f53039ec1108e83a..312a6eb447ff611c01b48aea6f7afc87797fc512 100644 (file)
@@ -180,7 +180,7 @@ static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, ze
 {
        uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args;
 
-       if (ZEND_USER_CODE(func->type)) {
+       if (EXPECTED(ZEND_USER_CODE(func->type))) {
                used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
        }
        return used_stack * sizeof(zval);
@@ -304,7 +304,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data);
        } while (0)
 
 #define CACHED_POLYMORPHIC_PTR(num, ce) \
-       ((((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[0] == (void*)(ce)) ? \
+       (EXPECTED(((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[0] == (void*)(ce)) ? \
                ((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[1] : \
                NULL)
 
@@ -322,7 +322,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data);
        } while (0)
 
 #define CACHED_POLYMORPHIC_PTR_EX(slot, ce) \
-       (((slot)[0] == (ce)) ? (slot)[1] : NULL)
+       (EXPECTED((slot)[0] == (ce)) ? (slot)[1] : NULL)
 
 #define CACHE_POLYMORPHIC_PTR_EX(slot, ce, ptr) do { \
                (slot)[0] = (ce); \
index 3cbd5143a50a4fc3ad501de5e8cb641714da3eec..95022ac2ccb8871ecbaed1cbad08717005d971db 100644 (file)
@@ -2401,7 +2401,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
                        OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
                }
-               if (call_info & ZEND_CALL_RELEASE_THIS) {
+               if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
                        object = Z_OBJ(old_execute_data->This);
 #if 0
                        if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
@@ -2921,16 +2921,23 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
        }
 
        if (OP1_TYPE != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+                               FREE_OP2();
+                               FREE_OP1();
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-                       FREE_OP2();
-                       FREE_OP1();
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -3760,7 +3767,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
        }
 
 ZEND_VM_C_LABEL(fcall_end_change_scope):
-       if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
+       if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
                object = Z_OBJ(call->This);
 #if 0
                if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
@@ -8004,7 +8011,7 @@ ZEND_VM_C_LABEL(call_trampoline_end):
 
        opline = EX(opline);
 
-       if (call_info & ZEND_CALL_RELEASE_THIS) {
+       if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
                object = Z_OBJ(call->This);
                OBJ_RELEASE(object);
        }
index 73e2a4a6ca5ee3a1a8d7c80d6ea15e62408a8631..f4bdf0d882f777ac1f54a118ccaa9c463d0a2e55 100644 (file)
@@ -452,7 +452,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
                if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
                        OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
                }
-               if (call_info & ZEND_CALL_RELEASE_THIS) {
+               if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
                        object = Z_OBJ(old_execute_data->This);
 #if 0
                        if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
@@ -882,7 +882,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC
        }
 
 fcall_end_change_scope:
-       if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
+       if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
                object = Z_OBJ(call->This);
 #if 0
                if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
@@ -1950,7 +1950,7 @@ call_trampoline_end:
 
        opline = EX(opline);
 
-       if (call_info & ZEND_CALL_RELEASE_THIS) {
+       if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
                object = Z_OBJ(call->This);
                OBJ_RELEASE(object);
        }
@@ -5434,16 +5434,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
        }
 
        if (IS_CONST != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -9074,16 +9081,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
        }
 
        if (IS_CONST != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -10802,16 +10816,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
        }
 
        if (IS_CONST != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+                               zval_ptr_dtor_nogc(free_op2);
+
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-                       zval_ptr_dtor_nogc(free_op2);
-
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -23658,16 +23679,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
        }
 
        if (IS_UNUSED != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -26052,16 +26080,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
        }
 
        if (IS_UNUSED != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -27568,16 +27603,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
        }
 
        if (IS_UNUSED != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+                               zval_ptr_dtor_nogc(free_op2);
+
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-                       zval_ptr_dtor_nogc(free_op2);
-
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -31848,16 +31890,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
        }
 
        if (IS_CV != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -36908,16 +36957,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
        }
 
        if (IS_CV != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
 
 
-                       HANDLE_EXCEPTION();
-               }
+                               HANDLE_EXCEPTION();
+                       }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -39469,16 +39525,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
        }
 
        if (IS_CV != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+                               if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
+                                       object = Z_REFVAL_P(object);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+                               zval_ptr_dtor_nogc(free_op2);
+
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-                       zval_ptr_dtor_nogc(free_op2);
-
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -41613,16 +41676,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
        }
 
        if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (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);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+
+                               zval_ptr_dtor_nogc(free_op1);
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-
-                       zval_ptr_dtor_nogc(free_op1);
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -43675,16 +43745,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
        }
 
        if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (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);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+
+                               zval_ptr_dtor_nogc(free_op1);
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-
-                       zval_ptr_dtor_nogc(free_op1);
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);
@@ -44725,16 +44802,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
        }
 
        if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
-               ZVAL_DEREF(object);
-               if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
-                       if (UNEXPECTED(EG(exception) != NULL)) {
+               do {
+                       if (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);
+                                       if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
+                                               break;
+                                       }
+                               }
+                               if (UNEXPECTED(EG(exception) != NULL)) {
+                                       HANDLE_EXCEPTION();
+                               }
+                               zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+                               zval_ptr_dtor_nogc(free_op2);
+                               zval_ptr_dtor_nogc(free_op1);
                                HANDLE_EXCEPTION();
                        }
-                       zend_error(E_EXCEPTION | E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
-                       zval_ptr_dtor_nogc(free_op2);
-                       zval_ptr_dtor_nogc(free_op1);
-                       HANDLE_EXCEPTION();
-               }
+               } while (0);
        }
 
        obj = Z_OBJ_P(object);