]> granicus.if.org Git - php/commitdiff
Simplify call frame initialization
authorDmitry Stogov <dmitry@zend.com>
Wed, 10 Apr 2019 23:08:32 +0000 (02:08 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 10 Apr 2019 23:08:32 +0000 (02:08 +0300)
12 files changed:
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_generators.c
Zend/zend_types.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
ext/opcache/jit/zend_jit_helpers.c
ext/opcache/jit/zend_jit_x86.dasc
sapi/fpm/fpm/fpm_php_trace.c

index 3aa5e6c1138eabd639e5dd4ca8cf61e8fe8e7ce1..fefe566c58df32f8411614a37479011a0626365d 100644 (file)
@@ -497,25 +497,31 @@ struct _zend_execute_data {
 #endif
 };
 
-#define ZEND_CALL_FUNCTION           (0 << 0)
-#define ZEND_CALL_CODE               (1 << 0)
-#define ZEND_CALL_NESTED             (0 << 1)
-#define ZEND_CALL_TOP                (1 << 1)
-#define ZEND_CALL_FREE_EXTRA_ARGS    (1 << 2)
-#define ZEND_CALL_CTOR               (1 << 3)
-#define ZEND_CALL_HAS_SYMBOL_TABLE   (1 << 4)
-#define ZEND_CALL_CLOSURE            (1 << 5)
-#define ZEND_CALL_RELEASE_THIS       (1 << 6)
-#define ZEND_CALL_ALLOCATED          (1 << 7)
-#define ZEND_CALL_GENERATOR          (1 << 8)
-#define ZEND_CALL_DYNAMIC            (1 << 9)
-#define ZEND_CALL_FAKE_CLOSURE       (1 << 10)
-#define ZEND_CALL_SEND_ARG_BY_REF    (1 << 11)
-
-#define ZEND_CALL_INFO_SHIFT         16
+#define ZEND_CALL_HAS_THIS           IS_OBJECT_EX
+
+/* Top 16 bits of Z_TYPE_INFO(EX(This)) are used as call_info flags */
+#define ZEND_CALL_FUNCTION           (0 << 16)
+#define ZEND_CALL_CODE               (1 << 16)
+#define ZEND_CALL_NESTED             (0 << 17)
+#define ZEND_CALL_TOP                (1 << 17)
+#define ZEND_CALL_ALLOCATED          (1 << 18)
+#define ZEND_CALL_FREE_EXTRA_ARGS    (1 << 19)
+#define ZEND_CALL_HAS_SYMBOL_TABLE   (1 << 20)
+#define ZEND_CALL_RELEASE_THIS       (1 << 21)
+#define ZEND_CALL_CTOR               (1 << 22)
+#define ZEND_CALL_CLOSURE            (1 << 23)
+#define ZEND_CALL_FAKE_CLOSURE       (1 << 24)
+#define ZEND_CALL_GENERATOR          (1 << 25)
+#define ZEND_CALL_DYNAMIC            (1 << 26)
+#define ZEND_CALL_SEND_ARG_BY_REF    (1 << 31)
+
+#define ZEND_CALL_NESTED_FUNCTION    (ZEND_CALL_FUNCTION | ZEND_CALL_NESTED)
+#define ZEND_CALL_NESTED_CODE        (ZEND_CALL_CODE | ZEND_CALL_NESTED)
+#define ZEND_CALL_TOP_FUNCTION       (ZEND_CALL_TOP | ZEND_CALL_FUNCTION)
+#define ZEND_CALL_TOP_CODE           (ZEND_CALL_CODE | ZEND_CALL_TOP)
 
 #define ZEND_CALL_INFO(call) \
-       (Z_TYPE_INFO((call)->This) >> ZEND_CALL_INFO_SHIFT)
+       Z_TYPE_INFO((call)->This)
 
 #define ZEND_CALL_KIND_EX(call_info) \
        (call_info & (ZEND_CALL_CODE | ZEND_CALL_TOP))
@@ -523,16 +529,12 @@ struct _zend_execute_data {
 #define ZEND_CALL_KIND(call) \
        ZEND_CALL_KIND_EX(ZEND_CALL_INFO(call))
 
-#define ZEND_SET_CALL_INFO(call, object, info) do { \
-               Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << ZEND_CALL_INFO_SHIFT); \
-       } while (0)
-
 #define ZEND_ADD_CALL_FLAG_EX(call_info, flag) do { \
-               call_info |= ((flag) << ZEND_CALL_INFO_SHIFT); \
+               call_info |= (flag); \
        } while (0)
 
 #define ZEND_DEL_CALL_FLAG_EX(call_info, flag) do { \
-               call_info &= ~((flag) << ZEND_CALL_INFO_SHIFT); \
+               call_info &= ~(flag); \
        } while (0)
 
 #define ZEND_ADD_CALL_FLAG(call, flag) do { \
index c596be73a6c64b95ba8bc5c73682881503c90c81..1d626a0def2eb073f85bce60cbf6e0e135f717c5 100644 (file)
@@ -3854,13 +3854,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
        }
 
        return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC,
-               fbc, num_args, called_scope, NULL);
+               fbc, num_args, called_scope);
 }
 /* }}} */
 
 static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */
 {
        zend_function *fbc;
+       void *object_or_called_scope;
        zend_class_entry *called_scope;
        zend_object *object;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
@@ -3868,6 +3869,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o
        if (EXPECTED(function->handlers->get_closure) &&
            EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object) == SUCCESS)) {
 
+           object_or_called_scope = called_scope;
                if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc));
@@ -3875,9 +3877,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o
                        if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
                                call_info |= ZEND_CALL_FAKE_CLOSURE;
                        }
+                       if (object) {
+                               call_info |= ZEND_CALL_HAS_THIS;
+                               object_or_called_scope = object;
+                       }
                } else if (object) {
-                       call_info |= ZEND_CALL_RELEASE_THIS;
+                       call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                        GC_ADDREF(object); /* For $this pointer */
+                       object_or_called_scope = object;
                }
        } else {
                zend_throw_error(NULL, "Function name must be a string");
@@ -3889,15 +3896,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o
        }
 
        return zend_vm_stack_push_call_frame(call_info,
-               fbc, num_args, called_scope, object);
+               fbc, num_args, object_or_called_scope);
 }
 /* }}} */
 
 static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */
 {
        zend_function *fbc;
-       zend_class_entry *called_scope;
-       zend_object *object;
+       void *object_or_called_scope;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
 
        if (zend_hash_num_elements(function) == 2) {
@@ -3924,8 +3930,8 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
                }
 
                if (Z_TYPE_P(obj) == IS_STRING) {
-                       object = NULL;
-                       called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+                       zend_class_entry *called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+
                        if (UNEXPECTED(called_scope == NULL)) {
                                return NULL;
                        }
@@ -3945,9 +3951,9 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
                                zend_non_static_method_call(fbc);
                                return NULL;
                        }
+                       object_or_called_scope = called_scope;
                } else {
-                       called_scope = Z_OBJCE_P(obj);
-                       object = Z_OBJ_P(obj);
+                       zend_object *object = Z_OBJ_P(obj);
 
                        fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
                        if (UNEXPECTED(fbc == NULL)) {
@@ -3958,10 +3964,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
                        }
 
                        if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                               object = NULL;
+                               object_or_called_scope = object->ce;
                        } else {
-                               call_info |= ZEND_CALL_RELEASE_THIS;
+                               call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                                GC_ADDREF(object); /* For $this pointer */
+                               object_or_called_scope = object;
                        }
                }
        } else {
@@ -3974,7 +3981,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
        }
 
        return zend_vm_stack_push_call_frame(call_info,
-               fbc, num_args, called_scope, object);
+               fbc, num_args, object_or_called_scope);
 }
 /* }}} */
 
index 78b33171dfbc29198cfb54dce656bba348e35c2e..4abdaca9fdd7f42faf060718330e0e3b27c2aa23 100644 (file)
@@ -206,20 +206,15 @@ ZEND_API void zend_vm_stack_init_ex(size_t page_size);
 ZEND_API void zend_vm_stack_destroy(void);
 ZEND_API void* zend_vm_stack_extend(size_t size);
 
-static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
+static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope)
 {
        call->func = func;
-       if (object) {
-               Z_OBJ(call->This) = object;
-               ZEND_SET_CALL_INFO(call, 1, call_info);
-       } else {
-               Z_CE(call->This) = called_scope;
-               ZEND_SET_CALL_INFO(call, 0, call_info);
-       }
+       Z_PTR(call->This) = object_or_called_scope;
+       ZEND_CALL_INFO(call) = call_info;
        ZEND_CALL_NUM_ARGS(call) = num_args;
 }
 
-static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope)
 {
        zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top);
 
@@ -228,11 +223,11 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui
        if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
                call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
                ZEND_ASSERT_VM_STACK_GLOBAL;
-               zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, called_scope, object);
+               zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope);
                return call;
        } else {
                EG(vm_stack_top) = (zval*)((char*)call + used_stack);
-               zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object);
+               zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope);
                return call;
        }
 }
@@ -247,12 +242,12 @@ static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, ze
        return used_stack * sizeof(zval);
 }
 
-static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope)
 {
        uint32_t used_stack = zend_vm_calc_used_stack(num_args, func);
 
        return zend_vm_stack_push_call_frame_ex(used_stack, call_info,
-               func, num_args, called_scope, object);
+               func, num_args, object_or_called_scope);
 }
 
 static zend_always_inline void zend_vm_stack_free_extra_args_ex(uint32_t call_info, zend_execute_data *call)
index 07113bf69eaaaa11babb154b75b40fe63a1e1c0f..0c55abaa2e9061768e3b1bb84daea8335ffa4162 100644 (file)
@@ -634,6 +634,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
        zend_execute_data *call, dummy_execute_data;
        zend_fcall_info_cache fci_cache_local;
        zend_function *func;
+       uint32_t call_info;
+       void *object_or_called_scope;
 
        ZVAL_UNDEF(fci->retval);
 
@@ -695,11 +697,18 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
        }
 
        func = fci_cache->function_handler;
-       fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ?
-               NULL : fci_cache->object;
+       if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) {
+               fci->object = NULL;
+               object_or_called_scope = fci_cache->called_scope;
+               call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC;
+       } else {
+               fci->object = fci_cache->object;
+               object_or_called_scope = fci->object;
+               call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS;
+       }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC,
-               func, fci->param_count, fci_cache->called_scope, fci->object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               func, fci->param_count, object_or_called_scope);
 
        if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) {
                zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
index 958cf94202bdcf0bde8b56df8c6147e44c45a8ab..841489eca7fa0a54c3332feb54a016d4b114035c 100644 (file)
@@ -40,10 +40,7 @@ ZEND_API void zend_generator_restore_call_stack(zend_generator *generator) /* {{
                        (ZEND_CALL_INFO(call) & ~ZEND_CALL_ALLOCATED),
                        call->func,
                        ZEND_CALL_NUM_ARGS(call),
-                       (Z_TYPE(call->This) == IS_UNDEF) ?
-                               (zend_class_entry*)Z_OBJ(call->This) : NULL,
-                       (Z_TYPE(call->This) != IS_UNDEF) ?
-                               Z_OBJ(call->This) : NULL);
+                       Z_PTR(call->This));
                memcpy(((zval*)new_call) + ZEND_CALL_FRAME_SLOT, ((zval*)call) + ZEND_CALL_FRAME_SLOT, ZEND_CALL_NUM_ARGS(call) * sizeof(zval));
                new_call->prev_execute_data = prev_call;
                prev_call = new_call;
index f1e959f0e28f3fc8dbffba4f36da4c5ea035f624..6ba488d88b05b6a85c2fd608b22b1fbb13708639 100644 (file)
@@ -201,7 +201,6 @@ struct _zval_struct {
                                zend_uchar    type,                     /* active type */
                                zend_uchar    type_flags,
                                union {
-                                       uint16_t  call_info;    /* call info for EX(This) */
                                        uint16_t  extra;        /* not further specified */
                                } u)
                } v;
index 0a69450326e475f27fc3593ce823c7e3f859f6da..917cf16f24f899f4e2c78513907b22309d22bd12 100644 (file)
@@ -3507,27 +3507,29 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
                FREE_OP2();
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
                FREE_OP1();
 
                if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (OP1_TYPE == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
                        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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3539,7 +3541,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -3639,31 +3641,30 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (OP1_TYPE == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (OP1_TYPE == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3691,7 +3692,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
                CACHE_PTR(opline->result.num, fbc);
        }
        call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3763,8 +3764,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
        zend_fcall_info_cache fcc;
        char *error = NULL;
        zend_function *func;
-       zend_class_entry *called_scope;
-       zend_object *object;
+       void *object_or_called_scope;
        zend_execute_data *call;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
 
@@ -3773,8 +3773,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                ZEND_ASSERT(!error);
                func = fcc.function_handler;
-               called_scope = fcc.called_scope;
-               object = fcc.object;
+               object_or_called_scope = fcc.called_scope;
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
@@ -3782,9 +3781,14 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
                        if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
                                call_info |= ZEND_CALL_FAKE_CLOSURE;
                        }
-               } else if (object) {
-                       call_info |= ZEND_CALL_RELEASE_THIS;
-                       GC_ADDREF(object); /* For $this pointer */
+                       if (fcc.object) {
+                               object_or_called_scope = fcc.object;
+                               call_info |= ZEND_CALL_HAS_THIS;
+                       }
+               } else if (fcc.object) {
+                       GC_ADDREF(fcc.object); /* For $this pointer */
+                       object_or_called_scope = fcc.object;
+                       call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                }
 
                FREE_OP2();
@@ -3793,7 +3797,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
                                zend_object_release(ZEND_CLOSURE_OBJECT(func));
                        }
                        if (call_info & ZEND_CALL_RELEASE_THIS) {
-                               zend_object_release(object);
+                               zend_object_release(fcc.object);
                        }
                        HANDLE_EXCEPTION();
                }
@@ -3809,7 +3813,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               func, opline->extended_value, called_scope, object);
+               func, opline->extended_value, object_or_called_scope);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3842,7 +3846,7 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
        }
 
        call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3873,7 +3877,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
 
        call = zend_vm_stack_push_call_frame_ex(
                opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -4357,7 +4361,7 @@ ZEND_VM_HANDLER(41, ZEND_GENERATOR_CREATE, ANY, ANY)
                gen_execute_data->return_value = (zval*)generator;
                call_info = Z_TYPE_INFO(EX(This));
                if ((call_info & Z_TYPE_MASK) == IS_OBJECT
-                && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT))
+                && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS))
                         /* Bug #72523 */
                        || UNEXPECTED(zend_execute_ex != execute_ex))) {
                        ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS);
@@ -5345,17 +5349,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
                /* Perform a dummy function call */
                call = zend_vm_stack_push_call_frame(
                        ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
-                       opline->extended_value, NULL, NULL);
+                       opline->extended_value, NULL);
        } else {
                if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
                        init_func_run_time_cache(&constructor->op_array);
                }
                /* We are not handling overloaded classes right now */
                call = zend_vm_stack_push_call_frame(
-                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
+                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS,
                        constructor,
                        opline->extended_value,
-                       ce,
                        Z_OBJ_P(result));
                Z_ADDREF_P(result);
        }
@@ -5764,10 +5767,10 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
 
                new_op_array->scope = EX(func)->op_array.scope;
 
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+               call = zend_vm_stack_push_call_frame(
+                   (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
                        (zend_function*)new_op_array, 0,
-                       Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
-                       Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
+                       Z_PTR(EX(This)));
 
                if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
                        call->symbol_table = EX(symbol_table);
index fa3dac4aa6210d32d4cacf05a829b011f445eb22..0138bac77f26d99dbd48d4e3308a8f2c7e58481a 100644 (file)
@@ -1459,7 +1459,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER(
                gen_execute_data->return_value = (zval*)generator;
                call_info = Z_TYPE_INFO(EX(This));
                if ((call_info & Z_TYPE_MASK) == IS_OBJECT
-                && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT))
+                && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS))
                         /* Bug #72523 */
                        || UNEXPECTED(zend_execute_ex != execute_ex))) {
                        ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS);
@@ -2307,7 +2307,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME
                CACHE_PTR(opline->result.num, fbc);
        }
        call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -2396,7 +2396,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N
        }
 
        call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -2427,7 +2427,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO
 
        call = zend_vm_stack_push_call_frame_ex(
                opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, NULL, NULL);
+               fbc, opline->extended_value, NULL);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -3470,10 +3470,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN
 
                new_op_array->scope = EX(func)->op_array.scope;
 
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+               call = zend_vm_stack_push_call_frame(
+                   (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
                        (zend_function*)new_op_array, 0,
-                       Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
-                       Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
+                       Z_PTR(EX(This)));
 
                if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
                        call->symbol_table = EX(symbol_table);
@@ -5445,26 +5445,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -5476,7 +5478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -5576,31 +5578,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_CONST == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_CONST == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -5615,8 +5616,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
        zend_fcall_info_cache fcc;
        char *error = NULL;
        zend_function *func;
-       zend_class_entry *called_scope;
-       zend_object *object;
+       void *object_or_called_scope;
        zend_execute_data *call;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
 
@@ -5625,8 +5625,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                ZEND_ASSERT(!error);
                func = fcc.function_handler;
-               called_scope = fcc.called_scope;
-               object = fcc.object;
+               object_or_called_scope = fcc.called_scope;
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
@@ -5634,9 +5633,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
                        if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
                                call_info |= ZEND_CALL_FAKE_CLOSURE;
                        }
-               } else if (object) {
-                       call_info |= ZEND_CALL_RELEASE_THIS;
-                       GC_ADDREF(object); /* For $this pointer */
+                       if (fcc.object) {
+                               object_or_called_scope = fcc.object;
+                               call_info |= ZEND_CALL_HAS_THIS;
+                       }
+               } else if (fcc.object) {
+                       GC_ADDREF(fcc.object); /* For $this pointer */
+                       object_or_called_scope = fcc.object;
+                       call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                }
 
                if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
@@ -5644,7 +5648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
                                zend_object_release(ZEND_CLOSURE_OBJECT(func));
                        }
                        if (call_info & ZEND_CALL_RELEASE_THIS) {
-                               zend_object_release(object);
+                               zend_object_release(fcc.object);
                        }
                        HANDLE_EXCEPTION();
                }
@@ -5660,7 +5664,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               func, opline->extended_value, called_scope, object);
+               func, opline->extended_value, object_or_called_scope);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -7703,26 +7707,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                zval_ptr_dtor_nogc(free_op2);
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -7734,7 +7740,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -7834,31 +7840,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_CONST == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_CONST == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -7873,8 +7878,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
        zend_fcall_info_cache fcc;
        char *error = NULL;
        zend_function *func;
-       zend_class_entry *called_scope;
-       zend_object *object;
+       void *object_or_called_scope;
        zend_execute_data *call;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
 
@@ -7883,8 +7887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                ZEND_ASSERT(!error);
                func = fcc.function_handler;
-               called_scope = fcc.called_scope;
-               object = fcc.object;
+               object_or_called_scope = fcc.called_scope;
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
@@ -7892,9 +7895,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
                        if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
                                call_info |= ZEND_CALL_FAKE_CLOSURE;
                        }
-               } else if (object) {
-                       call_info |= ZEND_CALL_RELEASE_THIS;
-                       GC_ADDREF(object); /* For $this pointer */
+                       if (fcc.object) {
+                               object_or_called_scope = fcc.object;
+                               call_info |= ZEND_CALL_HAS_THIS;
+                       }
+               } else if (fcc.object) {
+                       GC_ADDREF(fcc.object); /* For $this pointer */
+                       object_or_called_scope = fcc.object;
+                       call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                }
 
                zval_ptr_dtor_nogc(free_op2);
@@ -7903,7 +7911,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
                                zend_object_release(ZEND_CLOSURE_OBJECT(func));
                        }
                        if (call_info & ZEND_CALL_RELEASE_THIS) {
-                               zend_object_release(object);
+                               zend_object_release(fcc.object);
                        }
                        HANDLE_EXCEPTION();
                }
@@ -7919,7 +7927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               func, opline->extended_value, called_scope, object);
+               func, opline->extended_value, object_or_called_scope);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -8880,7 +8888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -8980,31 +8988,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_CONST == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_CONST == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -9113,17 +9120,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(
                /* Perform a dummy function call */
                call = zend_vm_stack_push_call_frame(
                        ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
-                       opline->extended_value, NULL, NULL);
+                       opline->extended_value, NULL);
        } else {
                if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
                        init_func_run_time_cache(&constructor->op_array);
                }
                /* We are not handling overloaded classes right now */
                call = zend_vm_stack_push_call_frame(
-                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
+                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS,
                        constructor,
                        opline->extended_value,
-                       ce,
                        Z_OBJ_P(result));
                Z_ADDREF_P(result);
        }
@@ -10656,26 +10662,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CONST == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -10687,7 +10695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -10787,31 +10795,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_CONST == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_CONST == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -10826,8 +10833,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
        zend_fcall_info_cache fcc;
        char *error = NULL;
        zend_function *func;
-       zend_class_entry *called_scope;
-       zend_object *object;
+       void *object_or_called_scope;
        zend_execute_data *call;
        uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
 
@@ -10836,8 +10842,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                ZEND_ASSERT(!error);
                func = fcc.function_handler;
-               called_scope = fcc.called_scope;
-               object = fcc.object;
+               object_or_called_scope = fcc.called_scope;
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
@@ -10845,9 +10850,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
                        if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
                                call_info |= ZEND_CALL_FAKE_CLOSURE;
                        }
-               } else if (object) {
-                       call_info |= ZEND_CALL_RELEASE_THIS;
-                       GC_ADDREF(object); /* For $this pointer */
+                       if (fcc.object) {
+                               object_or_called_scope = fcc.object;
+                               call_info |= ZEND_CALL_HAS_THIS;
+                       }
+               } else if (fcc.object) {
+                       GC_ADDREF(fcc.object); /* For $this pointer */
+                       object_or_called_scope = fcc.object;
+                       call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
                }
 
                if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
@@ -10855,7 +10865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
                                zend_object_release(ZEND_CLOSURE_OBJECT(func));
                        }
                        if (call_info & ZEND_CALL_RELEASE_THIS) {
-                               zend_object_release(object);
+                               zend_object_release(fcc.object);
                        }
                        HANDLE_EXCEPTION();
                }
@@ -10871,7 +10881,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               func, opline->extended_value, called_scope, object);
+               func, opline->extended_value, object_or_called_scope);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -12970,10 +12980,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA
 
                new_op_array->scope = EX(func)->op_array.scope;
 
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+               call = zend_vm_stack_push_call_frame(
+                   (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
                        (zend_function*)new_op_array, 0,
-                       Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
-                       Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
+                       Z_PTR(EX(This)));
 
                if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
                        call->symbol_table = EX(symbol_table);
@@ -14404,27 +14414,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
                zval_ptr_dtor_nogc(free_op1);
 
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -16066,27 +16078,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                zval_ptr_dtor_nogc(free_op2);
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
                zval_ptr_dtor_nogc(free_op1);
 
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -17756,27 +17770,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
                zval_ptr_dtor_nogc(free_op1);
 
                if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -24744,7 +24760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -24844,31 +24860,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_VAR == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_VAR == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -27534,7 +27549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -27634,31 +27649,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_VAR == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_VAR == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -29220,7 +29234,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -29320,31 +29334,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_VAR == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_VAR == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -29453,17 +29466,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE
                /* Perform a dummy function call */
                call = zend_vm_stack_push_call_frame(
                        ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
-                       opline->extended_value, NULL, NULL);
+                       opline->extended_value, NULL);
        } else {
                if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
                        init_func_run_time_cache(&constructor->op_array);
                }
                /* We are not handling overloaded classes right now */
                call = zend_vm_stack_push_call_frame(
-                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
+                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS,
                        constructor,
                        opline->extended_value,
-                       ce,
                        Z_OBJ_P(result));
                Z_ADDREF_P(result);
        }
@@ -32032,7 +32044,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -32132,31 +32144,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_VAR == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_VAR == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -34413,26 +34424,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -34444,7 +34457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -34544,31 +34557,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_UNUSED == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_UNUSED == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -36479,26 +36491,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                zval_ptr_dtor_nogc(free_op2);
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -36510,7 +36524,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -36610,31 +36624,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_UNUSED == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_UNUSED == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -37059,7 +37072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -37159,31 +37172,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_UNUSED == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_UNUSED == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -37292,17 +37304,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER
                /* Perform a dummy function call */
                call = zend_vm_stack_push_call_frame(
                        ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
-                       opline->extended_value, NULL, NULL);
+                       opline->extended_value, NULL);
        } else {
                if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
                        init_func_run_time_cache(&constructor->op_array);
                }
                /* We are not handling overloaded classes right now */
                call = zend_vm_stack_push_call_frame(
-                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
+                       ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS,
                        constructor,
                        opline->extended_value,
-                       ce,
                        Z_OBJ_P(result));
                Z_ADDREF_P(result);
        }
@@ -39187,26 +39198,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_UNUSED == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -39218,7 +39231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       zend_object *object;
+       uint32_t call_info;
        zend_function *fbc;
        zend_execute_data *call;
 
@@ -39318,31 +39331,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
                }
        }
 
-       object = NULL;
        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
-                       object = Z_OBJ(EX(This));
-                       ce = object->ce;
+                       ce = (zend_class_entry*)Z_OBJ(EX(This));
+                       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
                } else {
                        zend_non_static_method_call(fbc);
                        HANDLE_EXCEPTION();
                }
-       }
-
-       if (IS_UNUSED == IS_UNUSED) {
+       } else {
                /* previous opcode is ZEND_FETCH_CLASS */
-               if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
-                   (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+               if (IS_UNUSED == IS_UNUSED
+                && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+                    (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
                        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                                ce = Z_OBJCE(EX(This));
                        } else {
                                ce = Z_CE(EX(This));
                        }
                }
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        }
 
-       call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
-               fbc, opline->extended_value, ce, object);
+       call = zend_vm_stack_push_call_frame(call_info,
+               fbc, opline->extended_value, ce);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -40712,10 +40724,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE
 
                new_op_array->scope = EX(func)->op_array.scope;
 
-               call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+               call = zend_vm_stack_push_call_frame(
+                   (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
                        (zend_function*)new_op_array, 0,
-                       Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
-                       Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
+                       Z_PTR(EX(This)));
 
                if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
                        call->symbol_table = EX(symbol_table);
@@ -44754,26 +44766,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -48982,26 +48996,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                zval_ptr_dtor_nogc(free_op2);
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -55178,26 +55194,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
 
        }
 
-       call_info = ZEND_CALL_NESTED_FUNCTION;
+       call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
-               obj = NULL;
 
                if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
                        HANDLE_EXCEPTION();
                }
+               /* call static method */
+               obj = (zend_object*)called_scope;
+               call_info = ZEND_CALL_NESTED_FUNCTION;
        } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
-               /* CV may be changed indirectly (e.g. when it's a reference) */
-               call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
                if (IS_CV == IS_CV) {
                        GC_ADDREF(obj); /* For $this pointer */
                } else if (free_op1 != object) {
                        GC_ADDREF(obj); /* For $this pointer */
 
                }
+               /* 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;
        }
 
        call = zend_vm_stack_push_call_frame(call_info,
-               fbc, opline->extended_value, called_scope, obj);
+               fbc, opline->extended_value, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
@@ -66622,13 +66640,22 @@ zend_leave_helper_SPEC_LABEL:
 ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
 {
        zend_execute_data *execute_data;
+       void *object_or_called_scope;
+       uint32_t call_info;
 
        if (EG(exception) != NULL) {
                return;
        }
 
-       execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
-               (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
+       object_or_called_scope = zend_get_this_object(EG(current_execute_data));
+       if (EXPECTED(!object_or_called_scope)) {
+               object_or_called_scope = zend_get_called_scope(EG(current_execute_data));
+               call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE;
+       } else {
+               call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS;
+       }
+       execute_data = zend_vm_stack_push_call_frame(call_info,
+               (zend_function*)op_array, 0, object_or_called_scope);
        if (EG(current_execute_data)) {
                execute_data->symbol_table = zend_rebuild_symbol_table();
        } else {
index 30f0017cbdd9d8ee05e95dfebbb195e9ca94a800..5e6e98bb24e76ba7d19b938c3e1193772e2837ec 100644 (file)
@@ -24,13 +24,22 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex)
 ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value)
 {
        zend_execute_data *execute_data;
+       void *object_or_called_scope;
+       uint32_t call_info;
 
        if (EG(exception) != NULL) {
                return;
        }
 
-       execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
-               (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
+       object_or_called_scope = zend_get_this_object(EG(current_execute_data));
+       if (EXPECTED(!object_or_called_scope)) {
+               object_or_called_scope = zend_get_called_scope(EG(current_execute_data));
+               call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE;
+       } else {
+               call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS;
+       }
+       execute_data = zend_vm_stack_push_call_frame(call_info,
+               (zend_function*)op_array, 0, object_or_called_scope);
        if (EG(current_execute_data)) {
                execute_data->symbol_table = zend_rebuild_symbol_table();
        } else {
index c2cac6f7d28ebff3b40abc543d71bc28ddd28373..8df29adce09ff38f54d71bbbb461c9198550e951 100644 (file)
@@ -61,14 +61,14 @@ static zend_execute_data* ZEND_FASTCALL zend_jit_extend_stack_helper(uint32_t us
 {
        zend_execute_data *call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
        call->func = fbc;
-       ZEND_SET_CALL_INFO(call, 0, ZEND_CALL_NESTED_FUNCTION|ZEND_CALL_ALLOCATED);
+       ZEND_CALL_INFO(call) = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_ALLOCATED;
        return call;
 }
 
 static zend_execute_data* ZEND_FASTCALL zend_jit_int_extend_stack_helper(uint32_t used_stack)
 {
        zend_execute_data *call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
-       ZEND_SET_CALL_INFO(call, 0, ZEND_CALL_NESTED_FUNCTION|ZEND_CALL_ALLOCATED);
+       ZEND_CALL_INFO(call) = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_ALLOCATED;
        return call;
 }
 
index 01f88c031c8bec39201d30dd916d318c068379f2..6f230dc6784d9c68dcc572c993448ceb6f2a1996 100644 (file)
@@ -7077,7 +7077,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zen
        }
        |       // zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object);
        |       // ZEND_SET_CALL_INFO(call, 0, call_info);
-       |       mov dword EX:RX->This.u1.type_info, (IS_UNDEF | (ZEND_CALL_NESTED_FUNCTION << ZEND_CALL_INFO_SHIFT))
+       |       mov dword EX:RX->This.u1.type_info, (IS_UNDEF | ZEND_CALL_NESTED_FUNCTION)
        |       // call->func = func;
 #ifdef _WIN32
        if (0) {
@@ -7726,7 +7726,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
                if (opline->opcode == ZEND_DO_FCALL) {
                        // TODO: optimize ???
                        |       // if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS))
-                       |       test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], ZEND_CALL_RELEASE_THIS
+                       |       test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], (ZEND_CALL_RELEASE_THIS >> 16)
                        |       jnz >1
                        |.cold_code
                        |1:
@@ -7750,7 +7750,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
                }
 
                |       // zend_vm_stack_free_call_frame(call);
-               |       test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], ZEND_CALL_ALLOCATED
+               |       test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], (ZEND_CALL_ALLOCATED >> 16)
                |       jnz >1
                |.cold_code
                |1:
@@ -8591,7 +8591,7 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, zend_op_
                return 0;
        }
 
-       |       movzx FCARG1d, word [FP + offsetof(zend_execute_data, This.u1.type_info) + 2]
+       |       mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)]
        |       test FCARG1d, (ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_FAKE_CLOSURE)
        |       jnz ->leave_function_handler
 
index 3174eef2fbe12338069f8cccd72ce90b2c600e51..cfdcf6509457b68594db0f054fb9ba930966c036 100644 (file)
@@ -99,9 +99,9 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog) /* {{{ *
                                        return -1;
                                }
 
-                               if (ZEND_CALL_KIND_EX((*call_info) >> ZEND_CALL_INFO_SHIFT) == ZEND_CALL_TOP_CODE) {
+                               if (ZEND_CALL_KIND_EX(*call_info) == ZEND_CALL_TOP_CODE) {
                                        return 0;
-                               } else if (ZEND_CALL_KIND_EX(*(call_info) >> ZEND_CALL_INFO_SHIFT) == ZEND_CALL_NESTED_CODE) {
+                               } else if (ZEND_CALL_KIND_EX(*call_info) == ZEND_CALL_NESTED_CODE) {
                                        memcpy(buf, "[INCLUDE_OR_EVAL]", sizeof("[INCLUDE_OR_EVAL]"));
                                } else {
                                        ZEND_ASSERT(0);