]> granicus.if.org Git - php/commitdiff
Revert "Speed up self::method() calls (no ZEND_FETCH_CLASS)"
authorDmitry Stogov <dmitry@zend.com>
Tue, 6 Oct 2015 20:48:08 +0000 (23:48 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 6 Oct 2015 20:48:08 +0000 (23:48 +0300)
This reverts commit 8c33bdb976e957ea67ebffd424e0a133a79c6ebe.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 6d8f794ae42cb0db5b4ac453448b36567ee00e65..d30db31bd95b4706ec1cf92f734cc4b864e83de7 100644 (file)
@@ -3301,22 +3301,14 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
 
        znode class_node, method_node;
        zend_op *opline;
-       uint32_t op_off;
-       uint32_t fetch_type = class_ast->kind == ZEND_AST_ZVAL ? zend_get_class_fetch_type_ast(class_ast) : -1;
+       zend_ulong extended_value = 0;
 
-       if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+       if (zend_is_const_default_class_ref(class_ast)) {
                class_node.op_type = IS_CONST;
                ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
        } else {
-               /* we do not have any reference to the extends_ast/name of parent at compile-time, hence only resolving self:: for now */
-               if (zend_is_scope_known() && fetch_type == ZEND_FETCH_CLASS_SELF) {
-                       zend_ensure_valid_class_fetch_type(fetch_type);
-
-                       class_node.op_type = IS_CONST;
-                       ZVAL_STR_COPY(&class_node.u.constant, CG(active_class_entry)->name);
-               } else {
-                       opline = zend_compile_class_ref(&class_node, class_ast, 1);
-               }
+               opline = zend_compile_class_ref(&class_node, class_ast, 1);
+               extended_value = opline->extended_value;
        }
 
        zend_compile_expr(&method_node, method_ast);
@@ -3333,7 +3325,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
 
        opline = get_next_op(CG(active_op_array));
        opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
-       op_off = opline - CG(active_op_array)->opcodes;
+       opline->extended_value = extended_value;
 
        zend_set_class_name_op1(opline, &class_node);
 
@@ -3351,10 +3343,6 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
        }
 
        zend_compile_call_common(result, args_ast, NULL);
-
-       if (fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT) {
-               CG(active_op_array)->opcodes[op_off].extended_value |= ZEND_FETCH_CLASS_FORWARD;
-       }
 }
 /* }}} */
 
index 1e749a595ed3abd4541910c7928c219c57dd8837..865340738aee10b574068360219a9e2e761dda7e 100644 (file)
@@ -791,18 +791,17 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
 /* END: OPCODES */
 
 /* class fetches */
-#define ZEND_FETCH_CLASS_DEFAULT     0
-#define ZEND_FETCH_CLASS_SELF        1
-#define ZEND_FETCH_CLASS_PARENT      2
-#define ZEND_FETCH_CLASS_STATIC      3
-#define ZEND_FETCH_CLASS_AUTO        4
-#define ZEND_FETCH_CLASS_INTERFACE   5
-#define ZEND_FETCH_CLASS_TRAIT       6
+#define ZEND_FETCH_CLASS_DEFAULT       0
+#define ZEND_FETCH_CLASS_SELF          1
+#define ZEND_FETCH_CLASS_PARENT                2
+#define ZEND_FETCH_CLASS_STATIC                3
+#define ZEND_FETCH_CLASS_AUTO          4
+#define ZEND_FETCH_CLASS_INTERFACE     5
+#define ZEND_FETCH_CLASS_TRAIT         6
 #define ZEND_FETCH_CLASS_MASK        0x0f
 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
 #define ZEND_FETCH_CLASS_SILENT      0x0100
 #define ZEND_FETCH_CLASS_EXCEPTION   0x0200
-#define ZEND_FETCH_CLASS_FORWARD     (1<<31)
 
 /* variable parsing type (compile-time) */
 #define ZEND_PARSED_MEMBER                             (1<<0)
index 7d9153f27b068322324bc76c3d673bcb9ac63ef3..a4b082b7b54c4b5dcd969da1e2bb533f301c7951 100644 (file)
@@ -3024,7 +3024,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -3127,11 +3127,16 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (OP1_TYPE != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || 
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
index 758dde5dc66c71fa4e562f647b021fd58246e5aa..e2a4fa94b05891cfafa054ed6338607186bf90a1 100644 (file)
@@ -5618,7 +5618,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -5721,11 +5721,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -7586,7 +7591,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -7689,11 +7694,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -9324,7 +9334,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -9427,11 +9437,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -11127,7 +11142,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -11230,11 +11245,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -17481,7 +17501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -17584,11 +17604,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -19116,7 +19141,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -19219,11 +19244,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -20738,7 +20768,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -20841,11 +20871,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -22303,7 +22338,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                /* no function found. try a static method in class */
                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
                if (UNEXPECTED(ce == NULL)) {
-                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT |  ZEND_FETCH_CLASS_EXCEPTION);
                        if (UNEXPECTED(ce == NULL)) {
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        HANDLE_EXCEPTION();
@@ -22406,11 +22441,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       if (opline->extended_value & ZEND_FETCH_CLASS_FORWARD) {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value & ~ZEND_FETCH_CLASS_FORWARD, EX(called_scope), object);
-       } else {
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object);
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                   ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+                       ce = EX(called_scope);
+               }
        }
+
+       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+               fbc, opline->extended_value, ce, object);
        call->prev_execute_data = EX(call);
        EX(call) = call;