]> granicus.if.org Git - php/commitdiff
Refactoring: use call_frames instead of call_slots
authorDmitry Stogov <dmitry@zend.com>
Mon, 23 Jun 2014 22:17:16 +0000 (02:17 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 23 Jun 2014 22:17:16 +0000 (02:17 +0400)
23 files changed:
Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_closures.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_generators.c
Zend/zend_object_handlers.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.c
Zend/zend_vm_opcodes.h
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/compact_literals.c
ext/opcache/Optimizer/optimize_func_calls.c
ext/opcache/Optimizer/pass1_5.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer_internal.h
sapi/cli/php_cli.c
sapi/fpm/fpm/fpm_php_trace.c

index ea333632be9363255017e4b22af02b6a6185b2cc..ab38bc2c453a2a9da3b466ad20854a7aa36d62dd 100644 (file)
@@ -44,14 +44,13 @@ static zend_class_entry  **class_cleanup_handlers;
 /* this function doesn't check for too many parameters */
 ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
 {
-       zval *p;
        int arg_count;
        va_list ptr;
        zval **param, *param_ptr;
        TSRMLS_FETCH();
 
-       p = zend_vm_stack_top(TSRMLS_C) - 1;
-       arg_count = Z_LVAL_P(p);
+       param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (param_count>arg_count) {
                return FAILURE;
@@ -61,7 +60,6 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
 
        while (param_count-->0) {
                param = va_arg(ptr, zval **);
-               param_ptr = (p-arg_count);
                if (!Z_ISREF_P(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
                        zval new_tmp;
 
@@ -70,7 +68,7 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
                        ZVAL_COPY_VALUE(param_ptr, &new_tmp);
                }
                *param = param_ptr;
-               arg_count--;
+               param_ptr++;
        }
        va_end(ptr);
 
@@ -80,19 +78,17 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
 
 ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
 {
-       zval *p;
        int arg_count;
        zval *param_ptr;
 
-       p = zend_vm_stack_top(TSRMLS_C) - 1;
-       arg_count = Z_LVAL_P(p);
+       param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (param_count>arg_count) {
                return FAILURE;
        }
 
        while (param_count-->0) {
-               param_ptr = (p-arg_count);
                if (Z_REFCOUNTED_P(param_ptr) && 
                    !Z_ISREF_P(param_ptr) &&                
                    Z_REFCOUNT_P(param_ptr) > 1) {
@@ -105,7 +101,7 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_
                        ZVAL_COPY_VALUE(argument_array, param_ptr);
                }
                argument_array++;
-               arg_count--;
+               param_ptr++;
        }
 
        return SUCCESS;
@@ -116,14 +112,13 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_
 /* this function doesn't check for too many parameters */
 ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
 {
-       zval *p;
        int arg_count;
        va_list ptr;
-       zval **param;
+       zval **param, *param_ptr;
        TSRMLS_FETCH();
 
-       p = zend_vm_stack_top(TSRMLS_C) - 1;
-       arg_count = Z_LVAL_P(p);
+       param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (param_count>arg_count) {
                return FAILURE;
@@ -132,7 +127,8 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
        va_start(ptr, param_count);
        while (param_count-->0) {
                param = va_arg(ptr, zval **);
-               *param = p-(arg_count--);
+               *param = param_ptr;
+               param_ptr++;
        }
        va_end(ptr);
 
@@ -142,22 +138,20 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
 
 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
 {
-       zval *p;
+       zval *param_ptr;
        int arg_count;
 
-       p = zend_vm_stack_top(TSRMLS_C) - 1;
-       arg_count = Z_LVAL_P(p);
+       param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (param_count>arg_count) {
                return FAILURE;
        }
 
        while (param_count-->0) {
-               zval *value = (p-arg_count);
-
-               ZVAL_COPY_VALUE(argument_array, value);
+               ZVAL_COPY_VALUE(argument_array, param_ptr);
                argument_array++;
-               arg_count--;
+               param_ptr++;
        }
 
        return SUCCESS;
@@ -166,22 +160,22 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array
 
 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
 {
-       zval *p;
+       zval *param_ptr;
        int arg_count;
 
-       p = zend_vm_stack_top(TSRMLS_C) - 1;
-       arg_count = Z_LVAL_P(p);
+       param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (param_count>arg_count) {
                return FAILURE;
        }
 
        while (param_count-->0) {
-               zval *param = p-(arg_count--);
-               if (Z_REFCOUNTED_P(param)) {
-                       Z_ADDREF_P(param);
+               if (Z_REFCOUNTED_P(param_ptr)) {
+                       Z_ADDREF_P(param_ptr);
                }
-               add_next_index_zval(argument_array, param);
+               add_next_index_zval(argument_array, param_ptr);
+               param_ptr++;
        }
 
        return SUCCESS;
@@ -841,7 +835,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                        case '+':
                                if (have_varargs) {
                                        if (!quiet) {
-                                               zend_function *active_function = EG(current_execute_data)->function_state.function;
+                                               zend_function *active_function = EG(current_execute_data)->call->func;
                                                const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
                                                zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
                                                                class_name,
@@ -861,7 +855,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
 
                        default:
                                if (!quiet) {
-                                       zend_function *active_function = EG(current_execute_data)->function_state.function;
+                                       zend_function *active_function = EG(current_execute_data)->call->func;
                                        const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
                                        zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
                                                        class_name,
@@ -884,7 +878,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
 
        if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
                if (!quiet) {
-                       zend_function *active_function = EG(current_execute_data)->function_state.function;
+                       zend_function *active_function = EG(current_execute_data)->call->func;
                        const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
                        zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
                                        class_name,
@@ -898,7 +892,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                return FAILURE;
        }
 
-       arg_count = Z_LVAL_P(zend_vm_stack_top(TSRMLS_C) - 1);
+       arg_count = EG(current_execute_data)->call->num_args;
 
        if (num_args > arg_count) {
                zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
@@ -922,7 +916,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
 
                        if (num_varargs > 0) {
                                *n_varargs = num_varargs;
-                               *varargs = (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
+                               *varargs = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
                                /* adjust how many args we have left and restart loop */
                                num_args += 1 - num_varargs;
                                i += num_varargs;
@@ -933,7 +927,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                        }
                }
 
-               arg = zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i);
+               arg = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
 
                if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
                        /* clean up varargs array if it was used */
@@ -1004,7 +998,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
         * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
         * In that case EG(This) would still be the $this from the calling code and we'd take the
         * wrong branch here. */
-       zend_bool is_method = EG(current_execute_data)->function_state.function->common.scope != NULL;
+       zend_bool is_method = EG(current_execute_data)->call->func->common.scope != NULL;
        if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
                RETURN_IF_ZERO_ARGS(num_args, p, 0);
 
index cb2205b82cc6f3a6f7c3b5ca6e4288eef14b78c4..f0ed68b703925c403d71154924c6928089cad47e 100644 (file)
@@ -396,8 +396,8 @@ ZEND_FUNCTION(func_num_args)
 {
        zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
 
-       if (ex && ex->function_state.arguments) {
-               RETURN_LONG(Z_LVAL_P(ex->function_state.arguments));
+       if (ex && ex->call) {
+               RETURN_LONG(ex->call->num_args);
        } else {
                zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
                RETURN_LONG(-1);
@@ -409,7 +409,6 @@ ZEND_FUNCTION(func_num_args)
    Get the $arg_num'th argument that was passed to the function */
 ZEND_FUNCTION(func_get_arg)
 {
-       zval *p;
        int arg_count;
        zval *arg;
        long requested_offset;
@@ -424,20 +423,19 @@ ZEND_FUNCTION(func_get_arg)
                RETURN_FALSE;
        }
 
-       if (!ex || !ex->function_state.arguments) {
+       if (!ex || !ex->call) {
                zend_error(E_WARNING, "func_get_arg():  Called from the global scope - no function context");
                RETURN_FALSE;
        }
 
-       p = ex->function_state.arguments;
-       arg_count = Z_LVAL_P(p);                /* this is the amount of arguments passed to func_get_arg(); */
+       arg_count = ex->call->num_args;
 
        if (requested_offset >= arg_count) {
                zend_error(E_WARNING, "func_get_arg():  Argument %ld not passed to function", requested_offset);
                RETURN_FALSE;
        }
 
-       arg = p-(arg_count-requested_offset);
+       arg = ZEND_CALL_ARG(ex->call, requested_offset + 1);
        RETURN_ZVAL_FAST(arg);
 }
 /* }}} */
@@ -451,19 +449,18 @@ ZEND_FUNCTION(func_get_args)
        int i;
        zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
 
-       if (!ex || !ex->function_state.arguments) {
+       if (!ex || !ex->call) {
                zend_error(E_WARNING, "func_get_args():  Called from the global scope - no function context");
                RETURN_FALSE;
        }
 
-       p = ex->function_state.arguments;
-       arg_count = Z_LVAL_P(p);                /* this is the amount of arguments passed to func_get_args(); */
+       arg_count = ex->call->num_args;
 
        array_init_size(return_value, arg_count);
        if (arg_count) {
                Bucket *q;              
 
-               p -= arg_count;
+               p = ZEND_CALL_ARG(ex->call, 1);
                zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
                q = Z_ARRVAL_P(return_value)->arData;
                for (i=0; i<arg_count; i++) {
@@ -1957,22 +1954,24 @@ ZEND_FUNCTION(get_defined_constants)
 /* }}} */
 
 
-static void debug_backtrace_get_args(zval *curpos, zval *arg_array TSRMLS_DC)
+static void debug_backtrace_get_args(zend_call_frame *call, zval *arg_array TSRMLS_DC)
 {
-       zval *p = curpos;
+       zval *p;
        zval *arg;
-       int arg_count = Z_LVAL_P(p);
+       int arg_count = call->num_args;
 
        array_init_size(arg_array, arg_count);
-       p -= arg_count;
-
-       while (--arg_count >= 0) {
-               arg = p++;
-               if (arg) {
-                       if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
-                       add_next_index_zval(arg_array, arg);
-               } else {
-                       add_next_index_null(arg_array);
+       if (arg_count > 0) {
+               p = ZEND_CALL_ARG(call, 1);
+
+               while (--arg_count >= 0) {
+                       arg = p++;
+                       if (arg) {
+                               if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
+                               add_next_index_zval(arg_array, arg);
+                       } else {
+                               add_next_index_null(arg_array);
+                       }
                }
        }
 }
@@ -1996,6 +1995,7 @@ ZEND_FUNCTION(debug_print_backtrace)
        zend_execute_data *ptr, *skip;
        zend_object *object;
        int lineno, frameno = 0;
+       zend_function *func;
        const char *function_name;
        const char *filename;
        zend_string *class_name = NULL;
@@ -2029,7 +2029,6 @@ ZEND_FUNCTION(debug_print_backtrace)
                    skip->prev_execute_data &&
                    skip->prev_execute_data->opline &&
                    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
-                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
                    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
                        skip = skip->prev_execute_data;
                }
@@ -2044,41 +2043,47 @@ ZEND_FUNCTION(debug_print_backtrace)
 
                /* $this may be passed into regular internal functions */
                if (object &&
-                   ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
-                   !ptr->function_state.function->common.scope) {
+                       ptr->call &&
+                   ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
+                   !ptr->call->func->common.scope) {
                        object = NULL;
                }
 
-               function_name = (ptr->function_state.function->common.scope &&
-                       ptr->function_state.function->common.scope->trait_aliases) ?
+               if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
+                       func = ptr->call->func;
+                       function_name = (func->common.scope &&
+                                        func->common.scope->trait_aliases) ?
                                zend_resolve_method_name(
-                                       object ?
+                                       (object ?
                                                zend_get_class_entry(object TSRMLS_CC) : 
-                                               ptr->function_state.function->common.scope,
-                                       ptr->function_state.function)->val :
-                               (ptr->function_state.function->common.function_name ?
-                                ptr->function_state.function->common.function_name->val :
-                                NULL);
+                                               func->common.scope), func)->val :
+                               (func->common.function_name ? 
+                                       func->common.function_name->val : NULL);
+               } else {
+                       func = (zend_function*)(ptr->op_array);
+                       function_name = func && func->common.function_name ? 
+                               func->common.function_name->val : NULL;
+               }
 
                if (function_name) {
                        if (object) {
-                               if (ptr->function_state.function->common.scope) {
-                                       class_name = ptr->function_state.function->common.scope->name;
+                               if (func->common.scope) {
+                                       class_name = func->common.scope->name;
                                } else {
                                        class_name = zend_get_object_classname(object TSRMLS_CC);
                                }
 
                                call_type = "->";
-                       } else if (ptr->function_state.function->common.scope) {
-                               class_name = ptr->function_state.function->common.scope->name;
+                       } else if (func->common.scope) {
+                               class_name = func->common.scope->name;
                                call_type = "::";
                        } else {
                                class_name = NULL;
                                call_type = NULL;
                        }
-                       if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
-                               if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
-                                       debug_backtrace_get_args(ptr->function_state.arguments, &arg_array TSRMLS_CC);
+                       if (!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL) {
+                               if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
+                                       debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
                                }
                        }
                } else {
@@ -2137,8 +2142,9 @@ ZEND_FUNCTION(debug_print_backtrace)
                        zend_execute_data *prev = skip->prev_execute_data;
 
                        while (prev) {
-                               if (prev->function_state.function &&
-                                       prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
+                               if (prev->call &&
+                                   prev->call->func &&
+                                       prev->call->func->common.type != ZEND_USER_FUNCTION) {
                                        prev = NULL;
                                        break;
                                }                                   
@@ -2166,6 +2172,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
        zend_execute_data *ptr, *skip;
        zend_object *object = Z_OBJ(EG(This));
        int lineno, frameno = 0;
+       zend_function *func;
        const char *function_name;
        const char *filename;
        zend_string *class_name;
@@ -2198,7 +2205,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                    skip->prev_execute_data &&
                    skip->prev_execute_data->opline &&
                    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
-                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
                    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
                        skip = skip->prev_execute_data;
                }
@@ -2216,10 +2222,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                        zend_execute_data *prev = skip->prev_execute_data;
 
                        while (prev) {
-                               if (prev->function_state.function &&
-                                       prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
-                                       !(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
-                                               (prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
+                               if (prev->call &&
+                                   prev->call->func &&
+                                       prev->call->func->common.type != ZEND_USER_FUNCTION &&
+                                       !(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
+                                               (prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
                                        break;
                                }                                   
                                if (prev->op_array) {
@@ -2235,28 +2242,34 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                /* $this may be passed into regular internal functions */
                if (object &&
-                   ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
-                   !ptr->function_state.function->common.scope) {
+                       ptr->call &&
+                   ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
+                   !ptr->call->func->common.scope) {
                        object = NULL;
                }
 
-               function_name = (ptr->function_state.function->common.scope &&
-                       ptr->function_state.function->common.scope->trait_aliases) ?
+               if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
+                       func = ptr->call->func;
+                       function_name = (func->common.scope &&
+                                        func->common.scope->trait_aliases) ?
                                zend_resolve_method_name(
-                                       object ?
+                                       (object ?
                                                zend_get_class_entry(object TSRMLS_CC) : 
-                                               ptr->function_state.function->common.scope,
-                                       ptr->function_state.function)->val :
-                               (ptr->function_state.function->common.function_name ?
-                                ptr->function_state.function->common.function_name->val : 
-                                NULL);
+                                               func->common.scope), func)->val :
+                               (func->common.function_name ? 
+                                       func->common.function_name->val : NULL);
+               } else {
+                       func = (zend_function*)(ptr->op_array);
+                       function_name = func && func->common.function_name ? 
+                               func->common.function_name->val : NULL;
+               }
 
                if (function_name) {
                        add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
 
                        if (object) {
-                               if (ptr->function_state.function->common.scope) {
-                                       add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
+                               if (func->common.scope) {
+                                       add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
                                } else {
                                        class_name = zend_get_object_classname(object TSRMLS_CC);
                                        add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
@@ -2270,16 +2283,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                }
 
                                add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
-                       } else if (ptr->function_state.function->common.scope) {
-                               add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
+                       } else if (func->common.scope) {
+                               add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
                                add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
                        }
 
                        if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && 
-                               ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
-                               if (ptr->function_state.arguments) {
+                               (!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL)) {
+                               if (ptr->call) {
                                        zval args;
-                                       debug_backtrace_get_args(ptr->function_state.arguments, &args TSRMLS_CC);
+                                       debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
                                        add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
                                }
                        }
index 3c2921f53cd630859dcad08752eb62bfa06ea874..85056d3cd559d92ae7ae9c22958d528b85eeffcd 100644 (file)
@@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers;
 
 ZEND_METHOD(Closure, __invoke) /* {{{ */
 {
-       zend_function *func = EG(current_execute_data)->function_state.function;
+       zend_function *func = EG(current_execute_data)->call->func;
        zval *arguments;
 
        arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
index c6116693b7679f1a0717b806c06c5deff55e99f8..690020a67d22fbaebeea628845fb2169398fba71 100644 (file)
@@ -182,7 +182,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
        CG(context).literals_size = 0;
        CG(context).current_brk_cont = -1;
        CG(context).backpatch_count = 0;
-       CG(context).nested_calls = 0;
        CG(context).used_stack = 0;
        CG(context).in_finally = 0;
        CG(context).labels = NULL;
@@ -1949,6 +1948,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
 
 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
 {
+       zend_op *opline;
        zend_function *function;
        zend_string *lcname;
        char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
@@ -1977,10 +1977,14 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
        STR_RELEASE(Z_STR(function_name->u.constant));
        Z_STR(function_name->u.constant) = lcname;
 
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       opline->opcode = ZEND_INIT_FCALL;
+       SET_UNUSED(opline->op1);
+       SET_NODE(opline->op2, function_name);
+       GET_CACHE_SLOT(opline->op2.constant);
+
        zend_push_function_call_entry(function TSRMLS_CC);
-       if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
-       }
+       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 0;
 }
@@ -2017,12 +2021,10 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
                }
                last_op->opcode = ZEND_INIT_METHOD_CALL;
                last_op->result_type = IS_UNUSED;
-               last_op->result.num = CG(context).nested_calls;
                Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
        } else {
                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
-               opline->result.num = CG(context).nested_calls;
                SET_UNUSED(opline->op1);
                if (left_bracket->op_type == IS_CONST) {
                        opline->op2_type = IS_CONST;
@@ -2034,9 +2036,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
        }
 
        zend_push_function_call_entry(NULL TSRMLS_CC);
-       if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls;
-       }
+       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2063,14 +2063,12 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
                /* In run-time PHP will check for function with full name and
                   internal function with short name */
                opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
-               opline->result.num = CG(context).nested_calls;
                SET_UNUSED(opline->op1);
                opline->op2_type = IS_CONST;
                opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
                GET_CACHE_SLOT(opline->op2.constant);
        } else {
                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
-               opline->result.num = CG(context).nested_calls;
                SET_UNUSED(opline->op1);
                if (function_name->op_type == IS_CONST) {
                        opline->op2_type = IS_CONST;
@@ -2082,9 +2080,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
        }
 
        zend_push_function_call_entry(NULL TSRMLS_CC);
-       if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls;
-       }
+       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2508,7 +2504,6 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
                opline->extended_value = class_node.EA  ;
        }
        opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
-       opline->result.num = CG(context).nested_calls;
        if (class_node.op_type == IS_CONST) {
                opline->op1_type = IS_CONST;
                opline->op1.constant =
@@ -2530,9 +2525,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
        }
 
        zend_push_function_call_entry(NULL TSRMLS_CC);
-       if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls;
-       }
+       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 1; /* Dynamic */
 }
@@ -2551,25 +2544,9 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
                opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
        } else {
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-               if (fcall->fbc) {
-                       opline->opcode = ZEND_DO_FCALL;
-                       SET_NODE(opline->op1, function_name);
-                       SET_UNUSED(opline->op2);
-                       opline->op2.num = CG(context).nested_calls;
-                       GET_CACHE_SLOT(opline->op1.constant);
-               } else {
-                       opline->opcode = ZEND_DO_FCALL_BY_NAME;
-                       SET_UNUSED(opline->op1);
-                       SET_UNUSED(opline->op2);
-                       opline->op2.num = --CG(context).nested_calls;
-
-                       /* This would normally be a ZEND_DO_FCALL, but was forced to use
-                        * ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
-                        * free the function_name */
-                       if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
-                               zval_dtor(&function_name->u.constant);
-                       }
-               }
+               opline->opcode = ZEND_DO_FCALL;
+               SET_UNUSED(opline->op1);
+               SET_UNUSED(opline->op2);
        }
 
        opline->result.var = get_temporary_variable(CG(active_op_array));
@@ -2577,10 +2554,10 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
        GET_NODE(result, opline->result);
        opline->extended_value = fcall->arg_num;
 
-       if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
-               CG(active_op_array)->used_stack = CG(context).used_stack + 1;
+       if (CG(context).used_stack > CG(active_op_array)->used_stack) {
+               CG(active_op_array)->used_stack = CG(context).used_stack;
        }
-       CG(context).used_stack -= fcall->arg_num;
+       CG(context).used_stack -= ZEND_CALL_FRAME_SLOT + fcall->arg_num;
        zend_stack_del_top(&CG(function_call_stack));
 }
 /* }}} */
@@ -2682,9 +2659,7 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
                }
        } else {
                if (function_ptr) {
-                       opline->extended_value = ZEND_DO_FCALL;
-               } else {
-                       opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+                       opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
                }
        }
        opline->opcode = op;
@@ -2692,9 +2667,7 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
        opline->op2.opline_num = fcall->arg_num;
        SET_UNUSED(opline->op2);
 
-       if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
-               CG(active_op_array)->used_stack = CG(context).used_stack;
-       }
+       CG(context).used_stack++;
 }
 /* }}} */
 
@@ -2705,25 +2678,6 @@ void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
 
        fcall->uses_argument_unpacking = 1;
 
-       if (fcall->fbc) {
-               /* If argument unpacking is used argument numbers and sending modes can no longer be
-                * computed at compile time, thus we need access to EX(call). In order to have it we
-                * retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
-               zval func_name;
-               ZVAL_STR(&func_name, STR_COPY(fcall->fbc->common.function_name));
-
-               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-               opline->opcode = ZEND_INIT_FCALL_BY_NAME;
-               opline->result.num = CG(context).nested_calls;
-               SET_UNUSED(opline->op1);
-               opline->op2_type = IS_CONST;
-               opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
-               GET_CACHE_SLOT(opline->op2.constant);
-
-               ++CG(context).nested_calls;
-               fcall->fbc = NULL;
-       }
-
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_SEND_UNPACK;
        SET_NODE(opline->op1, params);
@@ -5619,16 +5573,13 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
        new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_NEW;
-       opline->extended_value = CG(context).nested_calls;
        opline->result_type = IS_VAR;
        opline->result.var = get_temporary_variable(CG(active_op_array));
        SET_NODE(opline->op1, class_type);
        SET_UNUSED(opline->op2);
 
        zend_push_function_call_entry(NULL TSRMLS_CC);
-       if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls;
-       }
+       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
 }
 /* }}} */
 
@@ -5819,6 +5770,13 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
 {
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
+       opline->opcode = ZEND_INIT_FCALL;
+       SET_UNUSED(opline->op1);
+       opline->op2_type = IS_CONST;
+       LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
+       GET_CACHE_SLOT(opline->op2.constant);
+
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        switch (cmd->op_type) {
                case IS_CONST:
                case IS_TMP_VAR:
@@ -5830,27 +5788,21 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
        }
        SET_NODE(opline->op1, cmd);
        opline->op2.opline_num = 1;
-       opline->extended_value = ZEND_DO_FCALL;
+       opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
        SET_UNUSED(opline->op2);
 
        /* FIXME: exception support not added to this op2 */
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_DO_FCALL;
+       opline->extended_value = 1;
        opline->result.var = get_temporary_variable(CG(active_op_array));
        opline->result_type = IS_VAR;
-       LITERAL_STR(opline->op1, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
-       opline->op1_type = IS_CONST;
-       GET_CACHE_SLOT(opline->op1.constant);
-       opline->extended_value = 1;
+       SET_UNUSED(opline->op1);
        SET_UNUSED(opline->op2);
-       opline->op2.num = CG(context).nested_calls;
        GET_NODE(result, opline->result);
 
-       if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
-               CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
-       }
-       if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
-               CG(active_op_array)->used_stack = CG(context).used_stack + 2;
+       if (CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1 > CG(active_op_array)->used_stack) {
+               CG(active_op_array)->used_stack = CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1;
        }
 }
 /* }}} */
index 5b5397844ffdc21e4d60dd8fe9acdf814f6f645e..35be52f2f70bedf30f32e4e78a77b61d55e86ab0 100644 (file)
@@ -59,7 +59,6 @@ typedef struct _zend_compiler_context {
        int        literals_size;
        int        current_brk_cont;
        int        backpatch_count;
-       int        nested_calls;
        int        used_stack;
        int        in_finally;
        HashTable *labels;
@@ -266,7 +265,6 @@ struct _zend_op_array {
 
        zend_uint T;
 
-       zend_uint nested_calls;
        zend_uint used_stack;
 
        zend_brk_cont_element *brk_cont_array;
@@ -336,12 +334,6 @@ union _zend_function {
        zend_internal_function internal_function;
 };
 
-
-typedef struct _zend_function_state {
-       zend_function *function;
-       zval *arguments;
-} zend_function_state;
-
 typedef struct _zend_function_call_entry {
        zend_function *fbc;
        zend_uint arg_num;
@@ -361,14 +353,26 @@ typedef struct _list_llist_element {
        znode value;
 } list_llist_element;
 
-typedef struct _call_slot {
-       zend_function     *fbc;
-       zend_class_entry  *called_scope;
-       zend_object       *object;
-       zend_uint          num_additional_args;
-       zend_bool          is_ctor_call;
-       zend_bool          is_ctor_result_used;
-} call_slot;
+typedef struct _zend_call_frame zend_call_frame;
+
+struct _zend_call_frame {
+       zend_function         *func;
+       zend_uint              num_args;
+       zend_uint              flags;
+       zend_class_entry      *called_scope;
+       zend_object           *object;
+       zend_call_frame       *prev;
+};
+
+#define ZEND_CALL_CTOR               (1 << 0)
+#define ZEND_CALL_CTOR_RESULT_USED   (1 << 1)
+#define ZEND_CALL_DONE               (1 << 2)
+
+#define ZEND_CALL_FRAME_SLOT \
+       ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_call_frame)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
+
+#define ZEND_CALL_ARG(call, n) \
+       (((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
 
 typedef enum _vm_frame_kind {
        VM_FRAME_NESTED_FUNCTION,       /* stackless VM call to function */
@@ -380,7 +384,7 @@ typedef enum _vm_frame_kind {
 struct _zend_execute_data {
        struct _zend_op     *opline;           /* executed opline                */
        zend_op_array       *op_array;         /* executed op_array              */
-       zend_function_state  function_state;   /* called function and arguments  */
+       zend_call_frame     *call;             /* current call                   */
        zend_object         *object;           /* current $this                  */
        zend_class_entry    *scope;            /* function scope (self)          */
        zend_class_entry    *called_scope;     /* function called scope (static) */
@@ -393,8 +397,6 @@ struct _zend_execute_data {
        zval old_error_reporting;
        struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
        zend_object *delayed_exception;
-       call_slot *call_slots;
-       call_slot *call;
 };
 
 #define EX(element) execute_data.element
@@ -877,7 +879,7 @@ END_EXTERN_C()
 /* call op_array handler of extendions */
 #define ZEND_COMPILE_HANDLE_OP_ARRAY            (1<<1)
 
-/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of ZEND_DO_FCALL */
+/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
 #define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
 
 /* don't perform early binding for classes inherited form internal ones;
index a6f6d65d725871ad5ab8470f8522f0f9ea63b0c2..4e5b811d7e0e11d49c929e9bb207d725e0c2dde7 100644 (file)
@@ -1468,13 +1468,13 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC)
 {
        if (fci != NULL) {
-               execute_data_ptr->function_state.function->internal_function.handler(
+               execute_data_ptr->call->func->internal_function.handler(
                        fci->param_count, fci->retval TSRMLS_CC
                );
        } else {
                zval *return_value = EX_VAR_2(execute_data_ptr, execute_data_ptr->opline->result.var);
-               execute_data_ptr->function_state.function->internal_function.handler(
-                       execute_data_ptr->opline->extended_value + execute_data_ptr->call->num_additional_args, return_value TSRMLS_CC
+               execute_data_ptr->call->func->internal_function.handler(
+                       execute_data_ptr->call->num_args, return_value TSRMLS_CC
                );
        }
 }
@@ -1536,12 +1536,10 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
  *                             | VAR[op_array->last_var]                |
  *                             | ...                                    |
  *                             | VAR[op_array->last_var+op_array->T-1]  |
+ * zend_vm_stack_frame_base -> +----------------------------------------+
+ *           EX(call_slot)  -> | CALL_SLOT                              |
  *                             +----------------------------------------+
- *           EX(call_slots) -> | CALL_SLOT[0]                           |
- *                             | ...                                    |
- *                             | CALL_SLOT[op_array->nested_calls-1]    |
- *                             +----------------------------------------+
- * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0]                    |
+ *                             | ARGUMENTS STACK [0]                    |
  *                             | ...                                    |
  * zend_vm_stack_top --------> | ...                                    |
  *                             | ...                                    |
@@ -1566,9 +1564,8 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
         */
        size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
        size_t vars_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (op_array->last_var + op_array->T);
-       size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
        size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * op_array->used_stack;
-       size_t total_size = execute_data_size + vars_size + call_slots_size + stack_size;
+       size_t total_size = execute_data_size + vars_size + stack_size;
 
        /*
         * Normally the execute_data is allocated on the VM stack (because it does
@@ -1585,7 +1582,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
                 * and the passed arguments
                 */
                int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
-               size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (args_count + 1);
+               size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (ZEND_CALL_FRAME_SLOT + args_count);
 
                total_size += args_size + execute_data_size;
 
@@ -1596,11 +1593,15 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
                /* copy prev_execute_data */
                EX(prev_execute_data) = (zend_execute_data*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
                memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
-               EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
-               EX(prev_execute_data)->function_state.arguments = (zval*)(((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size - sizeof(zval)));
+               EX(prev_execute_data)->call = (zend_call_frame*)(((char*)EX(prev_execute_data)) + sizeof(zend_execute_data));
+               EX(prev_execute_data)->call->func = (zend_function*)op_array;
+               EX(prev_execute_data)->call->num_args = args_count;
+               EX(prev_execute_data)->call->flags = ZEND_CALL_DONE;
+               EX(prev_execute_data)->call->called_scope = NULL;
+               EX(prev_execute_data)->call->object = NULL;
+               EX(prev_execute_data)->call->prev = NULL;
 
                /* copy arguments */
-               ZVAL_LONG(EX(prev_execute_data)->function_state.arguments, args_count);
                if (args_count > 0) {
                        zval *arg_src = zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
                        zval *arg_dst = zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
@@ -1619,13 +1620,10 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
        EX(frame_kind) = frame_kind;
        ZVAL_UNDEF(&EX(old_error_reporting));
        EX(delayed_exception) = NULL;
-       EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + vars_size);
        EX(call) = NULL;
 
        EG(opline_ptr) = &EX(opline);
        EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
-       EX(function_state).function = (zend_function *) op_array;
-       EX(function_state).arguments = NULL;
        EX(op_array) = op_array;
        EX(object) = Z_OBJ(EG(This));
        EX(scope) = EG(scope);
@@ -1674,24 +1672,28 @@ ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array
 }
 /* }}} */
 
-static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, call_slot *call TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, zend_call_frame *call TSRMLS_DC) /* {{{ */
 {
        zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
-       return ARG_SHOULD_BE_SENT_BY_REF(call->fbc, arg_num);
+       return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
 }
 /* }}} */
 
-static zval *zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
+static zend_call_frame *zend_vm_stack_copy_call_frame(zend_call_frame *call TSRMLS_DC) /* {{{ */
 {
+       zend_uint count;
+       zend_call_frame *new_call;
        zend_vm_stack p = EG(argument_stack);
 
-       zend_vm_stack_extend(count + 1 TSRMLS_CC);
+       zend_vm_stack_extend(ZEND_CALL_FRAME_SLOT + call->num_args TSRMLS_CC);
 
-       EG(argument_stack)->top += count;
-       ZVAL_LONG(EG(argument_stack)->top, count);
+       new_call = (zend_call_frame*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
+       *new_call = *call;
+       EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT + call->num_args;
+       count = call->num_args;
        while (count-- > 0) {
                zval *data = --p->top;
-               ZVAL_COPY_VALUE(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count, data);
+               ZVAL_COPY_VALUE(ZEND_CALL_ARG(new_call, count), data);
 
                if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
                        zend_vm_stack r = p;
@@ -1701,18 +1703,16 @@ static zval *zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
                        efree(r);
                }
        }
-       return EG(argument_stack)->top++;
+       return new_call;
 }
 /* }}} */
 
-static zend_always_inline zval *zend_vm_stack_push_args(int count TSRMLS_DC) /* {{{ */
+static zend_always_inline void zend_vm_stack_adjust_call_frame(zend_call_frame **call TSRMLS_DC) /* {{{ */
 {
-       if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
+       if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < ZEND_CALL_FRAME_SLOT + (*call)->num_args)
                || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
-               return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
+               *call = zend_vm_stack_copy_call_frame(*call TSRMLS_CC);
        }
-       ZVAL_LONG(EG(argument_stack)->top, count);
-       return EG(argument_stack)->top++;
 }
 /* }}} */
 
index 1b74564dfdf79317905f5baff009c3bea1f159b0..49d9275bfa272bdfeff9f711aa0fa4e9f774c870 100644 (file)
@@ -221,6 +221,19 @@ static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
        return --EG(argument_stack)->top;
 }
 
+static zend_always_inline zend_call_frame *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_call_frame *prev TSRMLS_DC)
+{
+       zend_call_frame * call = (zend_call_frame*)EG(argument_stack)->top;
+       call->func = func;
+       call->num_args = num_args;
+       call->flags = flags;
+       call->called_scope = called_scope;
+       call->object = object;
+       call->prev = prev;
+       EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT;
+       return call;
+}
+
 static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
 {
        zval *ret;
@@ -234,8 +247,7 @@ static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
 
 static zend_always_inline zval* zend_vm_stack_frame_base(zend_execute_data *ex)
 {
-       return (zval*)((char*)ex->call_slots +
-               ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
+       return EX_VAR_NUM_2(ex, ex->op_array->last_var + ex->op_array->T);
 }
 
 static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
@@ -250,12 +262,13 @@ static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
        }
 }
 
-static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_call_frame(zend_call_frame *call, int nested TSRMLS_DC)
 {
-       zval *p = EG(argument_stack)->top - 1;
+       zend_uint num_args = call->num_args;    
 
-       if (EXPECTED(Z_LVAL_P(p) > 0)) {
-               zval *end = p - Z_LVAL_P(p);
+       if (num_args > 0) {
+               zval *p = ZEND_CALL_ARG(call, num_args + 1);
+               zval *end = p - num_args;
 
                do {
                        p--;
@@ -263,27 +276,25 @@ static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC
                } while (p != end);
        }
        if (nested) {
-               EG(argument_stack)->top = p;
+               EG(argument_stack)->top = (zval*)call;
        } else {
-               zend_vm_stack_free(p TSRMLS_CC);
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
        }
 }
 
 static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
 {
-       zval *p = ex->function_state.arguments;
-       return Z_LVAL_P(p);
+       return ex->call->num_args;
 }
 
 static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
 {
-       zval *p = ex->function_state.arguments;
-       int arg_count = Z_LVAL_P(p);
+       int arg_count = ex->call->num_args;
 
        if (UNEXPECTED(requested_arg > arg_count)) {
                return NULL;
        }
-       return p - arg_count + requested_arg - 1;
+       return ZEND_CALL_ARG(ex->call, requested_arg);
 }
 
 static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
index ebb995a262f105727cf541b4e5fbc56a4dc8339a..d326037b152dfea8a6bf3d9953c97eeb245f67fc 100644 (file)
@@ -393,17 +393,24 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
 /* return class name and "::" or "". */
 ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
 {
+       zend_function *func;
+
        if (!zend_is_executing(TSRMLS_C)) {
                if (space) {
                        *space = "";
                }
                return "";
        }
-       switch (EG(current_execute_data)->function_state.function->type) {
+       if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
+               func = EG(current_execute_data)->call->func;
+       } else {
+               func = (zend_function*)EG(current_execute_data)->op_array;
+       }
+       switch (func->type) {
                case ZEND_USER_FUNCTION:
                case ZEND_INTERNAL_FUNCTION:
                {
-                       zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
+                       zend_class_entry *ce = func->common.scope;
 
                        if (space) {
                                *space = ce ? "::" : "";
@@ -421,12 +428,19 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
 
 ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
 {
+       zend_function *func;
+
        if (!zend_is_executing(TSRMLS_C)) {
                return NULL;
        }
-       switch (EG(current_execute_data)->function_state.function->type) {
+       if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
+               func = EG(current_execute_data)->call->func;
+       } else {
+               func = (zend_function*)EG(current_execute_data)->op_array;
+       }
+       switch (func->type) {
                case ZEND_USER_FUNCTION: {
-                               zend_string *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
+                               zend_string *function_name = func->common.function_name;
 
                                if (function_name) {
                                        return function_name->val;
@@ -436,7 +450,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
                        }
                        break;
                case ZEND_INTERNAL_FUNCTION:
-                       return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name->val;
+                       return func->common.function_name->val;
                        break;
                default:
                        return NULL;
@@ -655,6 +669,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        zend_class_entry *called_scope = NULL;
        zend_execute_data execute_data;
        zend_fcall_info_cache fci_cache_local;
+       zend_function *func;
        zval tmp;
 
        ZVAL_UNDEF(fci->retval);
@@ -719,7 +734,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                STR_RELEASE(callable_name);
        }
 
-       EX(function_state).function = fci_cache->function_handler;
+       ZEND_VM_STACK_GROW_IF_NEEDED(ZEND_CALL_FRAME_SLOT + fci->param_count);
+
+       func = fci_cache->function_handler;
+       EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
        calling_scope = fci_cache->calling_scope;
        called_scope = fci_cache->called_scope;
        fci->object = fci_cache->object;
@@ -729,24 +747,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                return FAILURE;
        }
 
-       if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
-               if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
-                       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name->val, EX(function_state).function->common.function_name->val);
+       if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
+               if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", func->common.scope->name->val, func->common.function_name->val);
                }
-               if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
+               if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
                        zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
-                               EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
-                               EX(function_state).function->common.scope ? "::" : "",
-                               EX(function_state).function->common.function_name->val);
+                               func->common.scope ? func->common.scope->name->val : "",
+                               func->common.scope ? "::" : "",
+                               func->common.function_name->val);
                }
        }
 
-       ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
-
        for (i=0; i<fci->param_count; i++) {
                zval *param;
 
-               if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
+               if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
                        // TODO: Scalar values don't have reference counters anymore.
                        // They are assumed to be 1, and they may be easily passed by
                        // reference now. However, previously scalars with refcount==1
@@ -766,19 +782,19 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                            (!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) {
 
                                if (fci->no_separation &&
-                                       !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
+                                       !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
                                        if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
                                                /* hack to clean up the stack */
                                                ZVAL_LONG(&tmp, i);
                                                zend_vm_stack_push(&tmp TSRMLS_CC);
-                                               zend_vm_stack_clear_multiple(0 TSRMLS_CC);
+                                               zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
                                        }
 
                                        zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
                                                i+1,
-                                               EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
-                                               EX(function_state).function->common.scope ? "::" : "",
-                                               EX(function_state).function->common.function_name->val);
+                                               func->common.scope ? func->common.scope->name->val : "",
+                                               func->common.scope ? "::" : "",
+                                               func->common.function_name->val);
                                        return FAILURE;
                                }
 
@@ -797,7 +813,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        param = &fci->params[i];
                } else if (Z_ISREF(fci->params[i]) &&
                           /* don't separate references for __call */
-                          (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
+                          (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
                        param = &tmp;
                        ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
                } else {
@@ -807,13 +823,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                zend_vm_stack_push(param TSRMLS_CC);
        }
 
-       EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
-       ZVAL_LONG(EX(function_state).arguments, fci->param_count);
-
        EG(scope) = calling_scope;
        EG(called_scope) = called_scope;
        if (!fci->object ||
-           (EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
+           (func->common.fn_flags & ZEND_ACC_STATIC)) {
                Z_OBJ(EG(This)) = NULL;
        } else {
                Z_OBJ(EG(This)) = fci->object;
@@ -823,9 +836,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        EX(prev_execute_data) = EG(current_execute_data);
        EG(current_execute_data) = &execute_data;
 
-       if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+       if (func->type == ZEND_USER_FUNCTION) {
                calling_symbol_table = EG(active_symbol_table);
-               EG(scope) = EX(function_state).function->common.scope;
+               EG(scope) = func->common.scope;
                if (fci->symbol_table) {
                        EG(active_symbol_table) = fci->symbol_table;
                } else {
@@ -833,7 +846,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                }
 
                original_op_array = EG(active_op_array);
-               EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+               EG(active_op_array) = (zend_op_array *) func;
                original_opline_ptr = EG(opline_ptr);
 
                if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) {
@@ -848,15 +861,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
                }
                EG(active_symbol_table) = calling_symbol_table;
-       } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
-               int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+       } else if (func->type == ZEND_INTERNAL_FUNCTION) {
+               int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
                ZVAL_NULL(fci->retval);
-               if (EX(function_state).function->common.scope) {
-                       EG(scope) = EX(function_state).function->common.scope;
+               if (func->common.scope) {
+                       EG(scope) = func->common.scope;
                }
                if (EXPECTED(zend_execute_internal == NULL)) {
                        /* saves one function call if zend_execute_internal is not used */
-                       EX(function_state).function->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
+                       func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
                } else {
                        zend_execute_internal(&execute_data, fci TSRMLS_CC);
                }
@@ -880,22 +893,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
 
                /* Not sure what should be done here if it's a static method */
                if (fci->object) {
-                       fci->object->handlers->call_method(EX(function_state).function->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
+                       fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
                } else {
                        zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
                }
 
-               if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
-                       STR_RELEASE(EX(function_state).function->common.function_name);
+               if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+                       STR_RELEASE(func->common.function_name);
                }
-               efree(EX(function_state).function);
+               efree(func);
 
                if (EG(exception)) {
                        zval_ptr_dtor(fci->retval);
                        ZVAL_UNDEF(fci->retval);
                }
        }
-       zend_vm_stack_clear_multiple(0 TSRMLS_CC);
+       zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
 
        if (Z_OBJ(EG(This))) {
                zval_ptr_dtor(&EG(This));
index c80e909565de4f2ffa7b258426e63c9a99b6a0e5..2f82922b7aa50cdc59f5516043ba470364d466e2 100644 (file)
@@ -87,11 +87,11 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
 
        /* If yield was used as a function argument there may be active
         * method calls those objects need to be freed */
-       while (execute_data->call >= execute_data->call_slots) {
+       while (execute_data->call) {
                if (execute_data->call->object) {
                        OBJ_RELEASE(execute_data->call->object);
                }
-               execute_data->call--;
+               execute_data->call = execute_data->call->prev;
        }
 }
 /* }}} */
@@ -133,11 +133,10 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
                 * generator (for func_get_args) so those have to be freed too. */
                {
                        zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
-                       zval *arguments = prev_execute_data->function_state.arguments;
 
-                       if (arguments) {
-                               int arguments_count = Z_LVAL_P(arguments);
-                               zval *arguments_start = arguments - arguments_count;
+                       if (prev_execute_data->call) {
+                               int arguments_count = prev_execute_data->call->num_args;
+                               zval *arguments_start = ZEND_CALL_ARG(prev_execute_data->call, 1);
                                int i;
 
                                for (i = 0; i < arguments_count; ++i) {
index ac4599282e934acc0efd7775a25fea0c145ce5b2..e38fbfc6408597287e87423e4950acae354658e3 100644 (file)
@@ -905,7 +905,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{
 
 ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
 {
-       zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
+       zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
        zval method_name, method_args;
        zval method_result;
        zend_class_entry *ce = Z_OBJCE_P(getThis());
@@ -1123,7 +1123,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str
 
 ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
 {
-       zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
+       zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
        zval method_name, method_args;
        zval method_result;
        zend_class_entry *ce = EG(scope);
index 7ecccdaf32744a6bb46cb6476f1006257b329140..7fb1d9d87818c944e81d7b8cebd9b319c86bb8a6 100644 (file)
@@ -70,7 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
 
        op_array->T = 0;
 
-       op_array->nested_calls = 0;
        op_array->used_stack = 0;
 
        op_array->function_name = NULL;
index 38377d3cceb6852c7f27cae4d99b8d6a5aef49ab..f6153d80ec56e872287b2f019396d384beb41ce2 100644 (file)
@@ -1772,6 +1772,7 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
 ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
+       zend_call_frame *call;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -1790,12 +1791,9 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                EG(active_op_array) = EX(op_array);
                EG(active_symbol_table) = EX(symbol_table);
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-               EX(function_state).arguments = NULL;
-
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                               if (EX(call)->is_ctor_result_used) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
+                               if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -1812,9 +1810,9 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                EG(scope) = EX(scope);
                EG(called_scope) = EX(called_scope);
 
-               EX(call)--;
-
-               zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
 
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
@@ -1836,10 +1834,11 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 
                execute_data = EG(current_execute_data);
                zend_attach_symbol_table(execute_data);
-               EX(function_state).function = (zend_function *) EX(op_array);
-               EX(function_state).arguments = NULL;
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -1876,215 +1875,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
        }               
 }
 
-ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
-{
-       USE_OPLINE
-       zend_function *fbc = EX(function_state).function;
-       zend_object *object;
-       zend_uint num_args;
-
-       SAVE_OPLINE();
-       object = EX(call)->object;
-       if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
-               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
-                       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
-               }
-               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
-                       zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
-                               fbc->common.scope ? fbc->common.scope->name->val : "",
-                               fbc->common.scope ? "::" : "",
-                               fbc->common.function_name->val);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-               }
-       }
-       if (fbc->common.scope &&
-               !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
-               !object) {
-
-               if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                       /* FIXME: output identifiers properly */
-                       zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
-                       }
-               } else {
-                       /* FIXME: output identifiers properly */
-                       /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                       zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
-               }
-       }
-
-       if (EXPECTED(EX(call)->num_additional_args == 0)) {
-               num_args = opline->extended_value;
-               EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
-               ZVAL_LONG(EX(function_state).arguments, num_args);
-       } else {
-               num_args = opline->extended_value + EX(call)->num_additional_args;
-               EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
-       }
-       LOAD_OPLINE();
-
-       if (fbc->type == ZEND_INTERNAL_FUNCTION) {
-               int should_change_scope = 0;
-               zval *ret;
-
-               if (fbc->common.scope) {
-                       should_change_scope = 1;
-                       Z_OBJ(EG(This)) = object;
-                       /* TODO: we don't set scope if we call an object method ??? */
-                       /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
-#if 1
-                       EG(scope) = (object) ? NULL : fbc->common.scope;
-#else 
-                       EG(scope) = fbc->common.scope;
-#endif
-                       EG(called_scope) = EX(call)->called_scope;
-               }
-
-               if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
-                       zend_uint i;
-                       zval *p = EX(function_state).arguments - num_args;
-
-                       for (i = 0; i < num_args; ++i, ++p) {
-                               zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
-                       }
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               if (RETURN_VALUE_USED(opline)) {
-                                       ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               }
-                               if (UNEXPECTED(should_change_scope)) {
-                                       ZEND_VM_C_GOTO(fcall_end_change_scope);
-                               } else {
-                                       ZEND_VM_C_GOTO(fcall_end);
-                               }
-                       }
-               }
-
-               ret = EX_VAR(opline->result.var);
-               ZVAL_NULL(ret);
-               Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
-
-               if (!zend_execute_internal) {
-                       /* saves one function call if zend_execute_internal is not used */
-                       fbc->internal_function.handler(num_args, ret TSRMLS_CC);
-               } else {
-                       zend_execute_internal(execute_data, NULL TSRMLS_CC);
-               }
-
-               if (!RETURN_VALUE_USED(opline)) {
-                       zval_ptr_dtor(ret);
-               }
-
-               if (UNEXPECTED(should_change_scope)) {
-                       ZEND_VM_C_GOTO(fcall_end_change_scope);
-               } else {
-                       ZEND_VM_C_GOTO(fcall_end);
-               }
-       } else if (fbc->type == ZEND_USER_FUNCTION) {
-               zval *return_value = NULL;
-
-               Z_OBJ(EG(This)) = object;
-               EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
-               EG(active_symbol_table) = NULL;
-               EG(active_op_array) = &fbc->op_array;
-               if (RETURN_VALUE_USED(opline)) {
-                       return_value = EX_VAR(opline->result.var);
-
-                       ZVAL_NULL(return_value);
-                       Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
-               }
-
-               if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
-                       if (RETURN_VALUE_USED(opline)) {
-                               zend_generator_create_zval(EG(active_op_array), EX_VAR(opline->result.var) TSRMLS_CC);
-                       }
-               } else if (EXPECTED(zend_execute_ex == execute_ex)) {
-                       if (EXPECTED(EG(exception) == NULL)) {
-                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
-                               ZEND_VM_ENTER();
-                       }
-               } else {
-                       zend_execute(EG(active_op_array), return_value TSRMLS_CC);
-               }
-
-               EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
-                       zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
-               }
-               EG(active_symbol_table) = EX(symbol_table);
-       } else { /* ZEND_OVERLOADED_FUNCTION */
-               Z_OBJ(EG(This)) = object;
-//???          EG(scope) = NULL;
-               EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
-
-               ZVAL_NULL(EX_VAR(opline->result.var));
-
-               /* Not sure what should be done here if it's a static method */
-               if (EXPECTED(object != NULL)) {
-                       object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
-               } else {
-                       zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
-               }
-
-               if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
-                       STR_RELEASE(fbc->common.function_name);
-               }
-               efree(fbc);
-
-               if (!RETURN_VALUE_USED(opline)) {
-                       zval_ptr_dtor(EX_VAR(opline->result.var));
-               } else {
-//???                  Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
-//???                  Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
-                       Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
-               }
-       }
-
-ZEND_VM_C_LABEL(fcall_end_change_scope):
-       if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                       if (EX(call)->is_ctor_result_used) {
-                               Z_DELREF(EG(This));
-                       }
-                       if (Z_REFCOUNT(EG(This)) == 1) {
-                               zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
-                       }
-               }
-               if (!Z_DELREF(EG(This))) {
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
-                       _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
-               } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
-                       gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
-               }
-       }
-       Z_OBJ(EG(This)) = EX(object);
-       EG(scope) = EX(scope);
-       EG(called_scope) = EX(called_scope);
-
-ZEND_VM_C_LABEL(fcall_end):
-       EX(function_state).function = (zend_function *) EX(op_array);
-       EX(function_state).arguments = NULL;
-       EX(call)--;
-
-       zend_vm_stack_clear_multiple(1 TSRMLS_CC);
-
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               zend_throw_exception_internal(NULL TSRMLS_CC);
-               if (RETURN_VALUE_USED(opline)) {
-                       zval_ptr_dtor(EX_VAR(opline->result.var));
-               }
-               HANDLE_EXCEPTION();
-       }
-
-       ZEND_VM_NEXT_OPCODE();
-}
-
 ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
 {
        USE_OPLINE
@@ -2407,8 +2197,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1, free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -2423,29 +2215,29 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
        }
 
        object = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (OP2_TYPE != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (OP2_TYPE == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -2456,15 +2248,14 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        FREE_OP2();
        FREE_OP1_IF_VAR();
@@ -2478,7 +2269,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -2496,24 +2288,17 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (OP1_TYPE == IS_CONST &&
            OP2_TYPE == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (OP1_TYPE != IS_CONST &&
                   OP2_TYPE == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (OP2_TYPE != IS_UNUSED) {
                zend_free_op free_op2;
@@ -2529,20 +2314,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (OP2_TYPE == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (OP1_TYPE == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (OP2_TYPE != IS_CONST) {
@@ -2555,33 +2340,38 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (OP1_TYPE != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -2590,26 +2380,25 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
 ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
 {
        USE_OPLINE
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *object;
        zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
 
        if (OP2_TYPE == IS_CONST) {
                function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-                       call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+                       fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
                } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
 
-               call->object = NULL;
-               call->called_scope = NULL;
-               call->num_additional_args = 0;
-               call->is_ctor_call = 0;
-               EX(call) = call;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2635,33 +2424,28 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                        STR_FREE(lcname);
                        FREE_OP2();
 
-                       call->fbc = Z_FUNC_P(func);
-                       call->object = NULL;
-                       call->called_scope = NULL;
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
                } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
                    EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                        Z_OBJ_HANDLER_P(function_name, get_closure) &&
-                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
-                       if (call->object) {
-                               GC_REFCOUNT(call->object)++;
+                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+                       if (object) {
+                               GC_REFCOUNT(object)++;
                        }
                        if (OP2_TYPE == IS_VAR && OP2_FREE && Z_REFCOUNT_P(function_name) == 1 &&
-                           call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+                           fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                                /* Delay closure destruction until its invocation */
-                               call->fbc->common.prototype = (zend_function*)function_name_ptr;
+                               fbc->common.prototype = (zend_function*)function_name_ptr;
                        } else {
                                FREE_OP2();
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2687,40 +2471,39 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
-                               call->object = NULL;
-                               call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
-                               if (UNEXPECTED(call->called_scope == NULL)) {
+                               object = NULL;
+                               called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+                               if (UNEXPECTED(called_scope == NULL)) {
                                        CHECK_EXCEPTION();
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               if (call->called_scope->get_static_method) {
-                                       call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+                               if (called_scope->get_static_method) {
+                                       fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
                                } else {
-                                       call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+                                       fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
                                }
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
                                }
                        } else {
-                               call->called_scope = Z_OBJCE_P(obj);
-                               call->object = Z_OBJ_P(obj);
+                               called_scope = Z_OBJCE_P(obj);
+                               object = Z_OBJ_P(obj);
 
-                               call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+                               fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
                                }
 
-                               if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                                       call->object = NULL;
+                               if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+                                       object = NULL;
                                } else {
-                                       GC_REFCOUNT(call->object)++; /* For $this pointer */
+                                       GC_REFCOUNT(object)++; /* For $this pointer */
                                }
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        FREE_OP2();
                        CHECK_EXCEPTION();
@@ -2741,68 +2524,263 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
        USE_OPLINE
        zval *func_name;
        zval *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
 
        func_name = opline->op2.zv + 1;
        if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
                func_name++;
                if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
        } else {
-               call->fbc = Z_FUNC_P(func);
-               CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+               fbc = Z_FUNC_P(func);
+               CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
        }
 
-       call->object = NULL;
-       call->called_scope = NULL;
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
-{
-       EX(function_state).function = EX(call)->fbc;
-       ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);
-}
-
-ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
+ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
 {
        USE_OPLINE
-       zend_free_op free_op1;
-       zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R);
+       zend_free_op free_op2;
+       zval *fname = GET_OP2_ZVAL_PTR(BP_VAR_R);
        zval *func;
-       call_slot *call = EX(call_slots) + opline->op2.num;
+       zend_function *fbc;
 
        if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
-               EX(function_state).function = CACHED_PTR(Z_CACHE_SLOT_P(fname));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
        } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
            SAVE_OPLINE();
                zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
        } else {
-               EX(function_state).function = Z_FUNC_P(func);
-               CACHE_PTR(Z_CACHE_SLOT_P(fname), EX(function_state).function);
+               fbc = Z_FUNC_P(func);
+               CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
        }
 
-       call->fbc = EX(function_state).function;
-       call->object = NULL;
-       call->called_scope = NULL;
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
-       FREE_OP1();
+       FREE_OP2();
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
+{
+       USE_OPLINE
+       zend_function *fbc = EX(call)->func;
+       zend_object *object;
+       zend_uint num_args;
+       zend_call_frame *call;
+
+       SAVE_OPLINE();
+       EX(call)->flags |= ZEND_CALL_DONE;
+       object = EX(call)->object;
+       if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
+                       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
+               }
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+                       zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
+                               fbc->common.scope ? fbc->common.scope->name->val : "",
+                               fbc->common.scope ? "::" : "",
+                               fbc->common.function_name->val);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               HANDLE_EXCEPTION();
+                       }
+               }
+       }
+       if (fbc->common.scope &&
+               !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
+               !object) {
+
+               if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                       /* FIXME: output identifiers properly */
+                       zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               HANDLE_EXCEPTION();
+                       }
+               } else {
+                       /* FIXME: output identifiers properly */
+                       /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+                       zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
+               }
+       }
+
+       if (EXPECTED(EX(call)->num_args == 0)) {
+               EX(call)->num_args = num_args = opline->extended_value;
+       } else {
+               EX(call)->num_args += opline->extended_value;
+               num_args = EX(call)->num_args;
+               zend_vm_stack_adjust_call_frame(&EX(call) TSRMLS_CC);
+       }
+       LOAD_OPLINE();
+
+       if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+               int should_change_scope = 0;
+               zval *ret;
+
+               if (fbc->common.scope) {
+                       should_change_scope = 1;
+                       Z_OBJ(EG(This)) = object;
+                       /* TODO: we don't set scope if we call an object method ??? */
+                       /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
+#if 1
+                       EG(scope) = (object) ? NULL : fbc->common.scope;
+#else 
+                       EG(scope) = fbc->common.scope;
+#endif
+                       EG(called_scope) = EX(call)->called_scope;
+               }
+
+               if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+                       zend_uint i;
+                       zval *p = ZEND_CALL_ARG(EX(call), 1);
+
+                       for (i = 0; i < num_args; ++i) {
+                               zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
+                               p++;
+                       }
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               if (RETURN_VALUE_USED(opline)) {
+                                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                               }
+                               if (UNEXPECTED(should_change_scope)) {
+                                       ZEND_VM_C_GOTO(fcall_end_change_scope);
+                               } else {
+                                       ZEND_VM_C_GOTO(fcall_end);
+                               }
+                       }
+               }
+
+               ret = EX_VAR(opline->result.var);
+               ZVAL_NULL(ret);
+               Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+
+               if (!zend_execute_internal) {
+                       /* saves one function call if zend_execute_internal is not used */
+                       fbc->internal_function.handler(num_args, ret TSRMLS_CC);
+               } else {
+                       zend_execute_internal(execute_data, NULL TSRMLS_CC);
+               }
+
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(ret);
+               }
+
+               if (UNEXPECTED(should_change_scope)) {
+                       ZEND_VM_C_GOTO(fcall_end_change_scope);
+               } else {
+                       ZEND_VM_C_GOTO(fcall_end);
+               }
+       } else if (fbc->type == ZEND_USER_FUNCTION) {
+               zval *return_value = NULL;
+
+               Z_OBJ(EG(This)) = object;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
+               EG(active_symbol_table) = NULL;
+               EG(active_op_array) = &fbc->op_array;
+               if (RETURN_VALUE_USED(opline)) {
+                       return_value = EX_VAR(opline->result.var);
+
+                       ZVAL_NULL(return_value);
+                       Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+               }
+
+               if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       if (RETURN_VALUE_USED(opline)) {
+                               zend_generator_create_zval(EG(active_op_array), EX_VAR(opline->result.var) TSRMLS_CC);
+                       }
+               } else if (EXPECTED(zend_execute_ex == execute_ex)) {
+                       if (EXPECTED(EG(exception) == NULL)) {
+                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+                               ZEND_VM_ENTER();
+                       }
+               } else {
+                       zend_execute(EG(active_op_array), return_value TSRMLS_CC);
+               }
+
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
+                       zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
+               }
+               EG(active_symbol_table) = EX(symbol_table);
+       } else { /* ZEND_OVERLOADED_FUNCTION */
+               Z_OBJ(EG(This)) = object;
+//???          EG(scope) = NULL;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
 
-       ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);
+               ZVAL_NULL(EX_VAR(opline->result.var));
+
+               /* Not sure what should be done here if it's a static method */
+               if (EXPECTED(object != NULL)) {
+                       object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+               } else {
+                       zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
+               }
+
+               if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+                       STR_RELEASE(fbc->common.function_name);
+               }
+               efree(fbc);
+
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(EX_VAR(opline->result.var));
+               } else {
+//???                  Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+//???                  Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+                       Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
+               }
+       }
+
+ZEND_VM_C_LABEL(fcall_end_change_scope):
+       if (Z_OBJ(EG(This))) {
+               if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
+                       if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
+                               Z_DELREF(EG(This));
+                       }
+                       if (Z_REFCOUNT(EG(This)) == 1) {
+                               zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
+                       }
+               }
+               if (!Z_DELREF(EG(This))) {
+                       EX(call)->flags &= ~ZEND_CALL_DONE;
+                       _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+               } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+                       gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+               }
+       }
+       Z_OBJ(EG(This)) = EX(object);
+       EG(scope) = EX(scope);
+       EG(called_scope) = EX(called_scope);
+
+ZEND_VM_C_LABEL(fcall_end):
+       call = EX(call);
+       EX(call) = EX(call)->prev;
+       zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
+
+       if (UNEXPECTED(EG(exception) != NULL)) {
+               zend_throw_exception_internal(NULL TSRMLS_CC);
+               if (RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(EX_VAR(opline->result.var));
+               }
+               HANDLE_EXCEPTION();
+       }
+
+       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
@@ -2995,8 +2973,8 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
        zend_free_op free_op1;
 
        SAVE_OPLINE();
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
                }
        }
@@ -3044,7 +3022,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
                        ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
                }
        } else {
-               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
                }
        }
@@ -3065,7 +3043,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
        } else {
                if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
                        !(opline->extended_value & ZEND_ARG_SEND_SILENT) :
-                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error(E_STRICT, "Only variables should be passed by reference");
                }
                top = zend_vm_stack_top_inc(TSRMLS_C);
@@ -3118,8 +3096,8 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
        zval *varptr, *top;
        zend_free_op free_op1;
 
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
                }
        }
@@ -3147,7 +3125,7 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
        SAVE_OPLINE();
 
        args = GET_OP1_ZVAL_PTR(BP_VAR_R);
-       arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
+       arg_num = opline->op2.num + EX(call)->num_args + 1;
 
 ZEND_VM_C_LABEL(send_again):
        switch (Z_TYPE_P(args)) {
@@ -3164,7 +3142,7 @@ ZEND_VM_C_LABEL(send_again):
 
                                /* check if any of arguments are going to be passed by reference */
                                for (i = 0; i < zend_hash_num_elements(ht); i++) {
-                                       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num + i)) {
+                                       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
                                                separate = 1;
                                                break;
                                        }
@@ -3184,7 +3162,7 @@ ZEND_VM_C_LABEL(send_again):
                                }
 
                                top = zend_vm_stack_top_inc(TSRMLS_C);
-                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
                                        if (!Z_IMMUTABLE_P(args)) {
                                                ZVAL_MAKE_REF(arg);
                                                Z_ADDREF_P(arg);
@@ -3198,7 +3176,7 @@ ZEND_VM_C_LABEL(send_again):
                                        ZVAL_COPY(top, arg);
                                }
 
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
                                arg_num++;
                        } ZEND_HASH_FOREACH_END();
 
@@ -3260,13 +3238,13 @@ ZEND_VM_C_LABEL(send_again):
                                        zval_dtor(&key);
                                }
 
-                               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
                                        zend_error(
                                                E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
                                                " by unpacking a Traversable, passing by-value instead", arg_num,
-                                               EX(call)->fbc->common.scope ? EX(call)->fbc->common.scope->name->val : "",
-                                               EX(call)->fbc->common.scope ? "::" : "",
-                                               EX(call)->fbc->common.function_name->val
+                                               EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
+                                               EX(call)->func->common.scope ? "::" : "",
+                                               EX(call)->func->common.function_name->val
                                        );
                                }
                                
@@ -3278,7 +3256,7 @@ ZEND_VM_C_LABEL(send_again):
 
                                ZEND_VM_STACK_GROW_IF_NEEDED(1);
                                zend_vm_stack_push(arg TSRMLS_CC);
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
 
                                iter->funcs->move_forward(iter TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3307,15 +3285,14 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
 
        SAVE_OPLINE();
        if (UNEXPECTED(arg_num > arg_count)) {
                zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
        } else {
                zval *var_ptr;
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
 
                if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
                        zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
@@ -3333,8 +3310,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
        zval *var_ptr;
 
        SAVE_OPLINE();
@@ -3351,7 +3327,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
                        }
                }
        } else {
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
                ZVAL_COPY(var_ptr, param);
        }
 
@@ -3367,8 +3343,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
        zval *params;
 
        SAVE_OPLINE();
@@ -3377,7 +3352,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
        if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
 
        if (arg_num <= arg_count) {
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
                array_init_size(params, arg_count - arg_num + 1);
                if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
                        do {
@@ -3515,21 +3490,19 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
                }
                ZEND_VM_JMP(opline->op2.jmp_addr);
        } else {
-               call_slot *call = EX(call_slots) + opline->extended_value;
+               /* We are not handling overloaded classes right now */
+               EX(call) = zend_vm_stack_push_call_frame(
+                       constructor, 0,
+                       RETURN_VALUE_USED(opline) ?
+                               (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
+                       Z_CE_P(EX_VAR(opline->op1.var)),
+                       Z_OBJ(object_zval),
+                       EX(call) TSRMLS_CC);
 
                if (RETURN_VALUE_USED(opline)) {
                        ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
                }
 
-               /* We are not handling overloaded classes right now */
-               call->fbc = constructor;
-               call->object = Z_OBJ(object_zval);
-               call->called_scope = Z_CE_P(EX_VAR(opline->op1.var));
-               call->num_additional_args = 0;
-               call->is_ctor_call = 1;
-               call->is_ctor_result_used = RETURN_VALUE_USED(opline);
-               EX(call) = call;
-
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -4008,13 +3981,15 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
+               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
                        return_value = EX_VAR(opline->result.var);
                }
 
-               EX(function_state).function = (zend_function *) new_op_array;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -4027,10 +4002,11 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                        zend_execute(new_op_array, return_value TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -5176,18 +5152,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
        zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
        int i;
        zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
-       zval *stack_frame;
-
-       /* Figure out where the next stack frame (which maybe contains pushed
-        * arguments that have to be dtor'ed) starts */
-       stack_frame = zend_vm_stack_frame_base(execute_data);
-
-       /* If the exception was thrown during a function call there might be
-        * arguments pushed to the stack that have to be dtor'ed. */
-       while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
-               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
-               zval_ptr_dtor(stack_zval_p);
-       }
 
        for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
                if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
@@ -5206,12 +5170,20 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                }
        }
 
-       if (EX(call) >= EX(call_slots)) {
-               call_slot *call = EX(call);
+       if (EX(call)) {
+               zend_call_frame *call = EX(call);
                do {
+                       zval *args = ZEND_CALL_ARG(call, 1);
+
+                       /* If the exception was thrown during a function call there might be
+                        * arguments pushed to the stack that have to be dtor'ed. */
+                       while (zend_vm_stack_top(TSRMLS_C) != args) {
+                               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
+                               zval_ptr_dtor(stack_zval_p);
+                       }
                        if (call->object) {
-                               if (call->is_ctor_call) {
-                                       if (call->is_ctor_result_used) {
+                               if (call->flags & ZEND_CALL_CTOR) {
+                                       if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {
@@ -5220,8 +5192,9 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       call--;
-               } while (call >= EX(call_slots));
+                       EG(argument_stack)->top = (zval*)call;
+                       call = call->prev;
+               } while (call);
                EX(call) = NULL;
        }
 
@@ -5382,7 +5355,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
        }
 
        closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC;
-       closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
+       closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC;
        if (closure_is_static || closure_is_being_defined_inside_static_context) {
                zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC);
        } else {
@@ -5646,4 +5619,4 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
+ZEND_VM_EXPORT_HANDLER(zend_do_fcall, ZEND_DO_FCALL)
index b69dcbf711da94333a40a8ea8806d03d4560886b..f341e19fdb12c5fab8d396abb0a4863c8bda77a6 100644 (file)
@@ -384,6 +384,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC
 static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
+       zend_call_frame *call;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -402,12 +403,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                EG(active_op_array) = EX(op_array);
                EG(active_symbol_table) = EX(symbol_table);
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-               EX(function_state).arguments = NULL;
-
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                               if (EX(call)->is_ctor_result_used) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
+                               if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -424,9 +422,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                EG(scope) = EX(scope);
                EG(called_scope) = EX(called_scope);
 
-               EX(call)--;
-
-               zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
 
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
@@ -448,10 +446,11 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 
                execute_data = EG(current_execute_data);
                zend_attach_symbol_table(execute_data);
-               EX(function_state).function = (zend_function *) EX(op_array);
-               EX(function_state).arguments = NULL;
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -488,14 +487,35 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
        }
 }
 
-static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL  ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_function *fbc = EX(function_state).function;
+
+       ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
+       ZEND_VM_CONTINUE();
+}
+
+static int ZEND_FASTCALL  ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zval *tmp = EX_VAR(opline->result.var);
+
+       SAVE_OPLINE();
+       ZVAL_EMPTY_STRING(tmp);
+       /*CHECK_EXCEPTION();*/
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_function *fbc = EX(call)->func;
        zend_object *object;
        zend_uint num_args;
+       zend_call_frame *call;
 
        SAVE_OPLINE();
+       EX(call)->flags |= ZEND_CALL_DONE;
        object = EX(call)->object;
        if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
@@ -528,13 +548,12 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                }
        }
 
-       if (EXPECTED(EX(call)->num_additional_args == 0)) {
-               num_args = opline->extended_value;
-               EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
-               ZVAL_LONG(EX(function_state).arguments, num_args);
+       if (EXPECTED(EX(call)->num_args == 0)) {
+               EX(call)->num_args = num_args = opline->extended_value;
        } else {
-               num_args = opline->extended_value + EX(call)->num_additional_args;
-               EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
+               EX(call)->num_args += opline->extended_value;
+               num_args = EX(call)->num_args;
+               zend_vm_stack_adjust_call_frame(&EX(call) TSRMLS_CC);
        }
        LOAD_OPLINE();
 
@@ -557,10 +576,11 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
 
                if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
                        zend_uint i;
-                       zval *p = EX(function_state).arguments - num_args;
+                       zval *p = ZEND_CALL_ARG(EX(call), 1);
 
-                       for (i = 0; i < num_args; ++i, ++p) {
+                       for (i = 0; i < num_args; ++i) {
                                zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
+                               p++;
                        }
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                if (RETURN_VALUE_USED(opline)) {
@@ -659,8 +679,8 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
 
 fcall_end_change_scope:
        if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                       if (EX(call)->is_ctor_result_used) {
+               if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
+                       if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -668,8 +688,7 @@ fcall_end_change_scope:
                        }
                }
                if (!Z_DELREF(EG(This))) {
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
+                       EX(call)->flags &= ~ZEND_CALL_DONE;
                        _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
                } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
                        gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
@@ -680,11 +699,9 @@ fcall_end_change_scope:
        EG(called_scope) = EX(called_scope);
 
 fcall_end:
-       EX(function_state).function = (zend_function *) EX(op_array);
-       EX(function_state).arguments = NULL;
-       EX(call)--;
-
-       zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+       call = EX(call);
+       EX(call) = EX(call)->prev;
+       zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
 
        if (UNEXPECTED(EG(exception) != NULL)) {
                zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -697,31 +714,6 @@ fcall_end:
        ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_FASTCALL  ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       USE_OPLINE
-
-       ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
-       ZEND_VM_CONTINUE();
-}
-
-static int ZEND_FASTCALL  ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       USE_OPLINE
-       zval *tmp = EX_VAR(opline->result.var);
-
-       SAVE_OPLINE();
-       ZVAL_EMPTY_STRING(tmp);
-       /*CHECK_EXCEPTION();*/
-       ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL  ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       EX(function_state).function = EX(call)->fbc;
-       return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
 static int ZEND_FASTCALL  ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        /* The generator object is stored in EX(return_value) */
@@ -743,7 +735,7 @@ static int ZEND_FASTCALL  ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        SAVE_OPLINE();
 
        args = get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R);
-       arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
+       arg_num = opline->op2.num + EX(call)->num_args + 1;
 
 send_again:
        switch (Z_TYPE_P(args)) {
@@ -760,7 +752,7 @@ send_again:
 
                                /* check if any of arguments are going to be passed by reference */
                                for (i = 0; i < zend_hash_num_elements(ht); i++) {
-                                       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num + i)) {
+                                       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
                                                separate = 1;
                                                break;
                                        }
@@ -780,7 +772,7 @@ send_again:
                                }
 
                                top = zend_vm_stack_top_inc(TSRMLS_C);
-                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
                                        if (!Z_IMMUTABLE_P(args)) {
                                                ZVAL_MAKE_REF(arg);
                                                Z_ADDREF_P(arg);
@@ -794,7 +786,7 @@ send_again:
                                        ZVAL_COPY(top, arg);
                                }
 
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
                                arg_num++;
                        } ZEND_HASH_FOREACH_END();
 
@@ -856,13 +848,13 @@ send_again:
                                        zval_dtor(&key);
                                }
 
-                               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
                                        zend_error(
                                                E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
                                                " by unpacking a Traversable, passing by-value instead", arg_num,
-                                               EX(call)->fbc->common.scope ? EX(call)->fbc->common.scope->name->val : "",
-                                               EX(call)->fbc->common.scope ? "::" : "",
-                                               EX(call)->fbc->common.function_name->val
+                                               EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
+                                               EX(call)->func->common.scope ? "::" : "",
+                                               EX(call)->func->common.function_name->val
                                        );
                                }
 
@@ -874,7 +866,7 @@ send_again:
 
                                ZEND_VM_STACK_GROW_IF_NEEDED(1);
                                zend_vm_stack_push(arg TSRMLS_CC);
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
 
                                iter->funcs->move_forward(iter TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -903,15 +895,14 @@ static int ZEND_FASTCALL  ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
 
        SAVE_OPLINE();
        if (UNEXPECTED(arg_num > arg_count)) {
                zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
        } else {
                zval *var_ptr;
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
 
                if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
                        zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
@@ -929,8 +920,7 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
        zval *params;
 
        SAVE_OPLINE();
@@ -939,7 +929,7 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
        if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
 
        if (arg_num <= arg_count) {
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
                array_init_size(params, arg_count - arg_num + 1);
                if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
                        do {
@@ -990,21 +980,19 @@ static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
                ZEND_VM_JMP(opline->op2.jmp_addr);
        } else {
-               call_slot *call = EX(call_slots) + opline->extended_value;
+               /* We are not handling overloaded classes right now */
+               EX(call) = zend_vm_stack_push_call_frame(
+                       constructor, 0,
+                       RETURN_VALUE_USED(opline) ?
+                               (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
+                       Z_CE_P(EX_VAR(opline->op1.var)),
+                       Z_OBJ(object_zval),
+                       EX(call) TSRMLS_CC);
 
                if (RETURN_VALUE_USED(opline)) {
                        ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
                }
 
-               /* We are not handling overloaded classes right now */
-               call->fbc = constructor;
-               call->object = Z_OBJ(object_zval);
-               call->called_scope = Z_CE_P(EX_VAR(opline->op1.var));
-               call->num_additional_args = 0;
-               call->is_ctor_call = 1;
-               call->is_ctor_result_used = RETURN_VALUE_USED(opline);
-               EX(call) = call;
-
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -1205,18 +1193,6 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
        zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
        int i;
        zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
-       zval *stack_frame;
-
-       /* Figure out where the next stack frame (which maybe contains pushed
-        * arguments that have to be dtor'ed) starts */
-       stack_frame = zend_vm_stack_frame_base(execute_data);
-
-       /* If the exception was thrown during a function call there might be
-        * arguments pushed to the stack that have to be dtor'ed. */
-       while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
-               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
-               zval_ptr_dtor(stack_zval_p);
-       }
 
        for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
                if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
@@ -1235,12 +1211,20 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                }
        }
 
-       if (EX(call) >= EX(call_slots)) {
-               call_slot *call = EX(call);
+       if (EX(call)) {
+               zend_call_frame *call = EX(call);
                do {
+                       zval *args = ZEND_CALL_ARG(call, 1);
+
+                       /* If the exception was thrown during a function call there might be
+                        * arguments pushed to the stack that have to be dtor'ed. */
+                       while (zend_vm_stack_top(TSRMLS_C) != args) {
+                               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
+                               zval_ptr_dtor(stack_zval_p);
+                       }
                        if (call->object) {
-                               if (call->is_ctor_call) {
-                                       if (call->is_ctor_result_used) {
+                               if (call->flags & ZEND_CALL_CTOR) {
+                                       if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {
@@ -1249,8 +1233,9 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       call--;
-               } while (call >= EX(call_slots));
+                       EG(argument_stack)->top = (zval*)call;
+                       call = call->prev;
+               } while (call);
                EX(call) = NULL;
        }
 
@@ -1459,26 +1444,25 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
 static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *object;
        zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
 
        if (IS_CONST == IS_CONST) {
                function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-                       call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+                       fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
                } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
 
-               call->object = NULL;
-               call->called_scope = NULL;
-               call->num_additional_args = 0;
-               call->is_ctor_call = 0;
-               EX(call) = call;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -1503,33 +1487,28 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                        }
                        STR_FREE(lcname);
 
-                       call->fbc = Z_FUNC_P(func);
-                       call->object = NULL;
-                       call->called_scope = NULL;
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
                } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
                    EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                        Z_OBJ_HANDLER_P(function_name, get_closure) &&
-                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
-                       if (call->object) {
-                               GC_REFCOUNT(call->object)++;
+                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+                       if (object) {
+                               GC_REFCOUNT(object)++;
                        }
                        if (IS_CONST == IS_VAR && 0 && Z_REFCOUNT_P(function_name) == 1 &&
-                           call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+                           fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                                /* Delay closure destruction until its invocation */
-                               call->fbc->common.prototype = (zend_function*)function_name_ptr;
+                               fbc->common.prototype = (zend_function*)function_name_ptr;
                        } else {
 
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1555,40 +1534,39 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
-                               call->object = NULL;
-                               call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
-                               if (UNEXPECTED(call->called_scope == NULL)) {
+                               object = NULL;
+                               called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+                               if (UNEXPECTED(called_scope == NULL)) {
                                        CHECK_EXCEPTION();
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               if (call->called_scope->get_static_method) {
-                                       call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+                               if (called_scope->get_static_method) {
+                                       fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
                                } else {
-                                       call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+                                       fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
                                }
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
                                }
                        } else {
-                               call->called_scope = Z_OBJCE_P(obj);
-                               call->object = Z_OBJ_P(obj);
+                               called_scope = Z_OBJCE_P(obj);
+                               object = Z_OBJ_P(obj);
 
-                               call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+                               fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
                                }
 
-                               if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                                       call->object = NULL;
+                               if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+                                       object = NULL;
                                } else {
-                                       GC_REFCOUNT(call->object)++; /* For $this pointer */
+                                       GC_REFCOUNT(object)++; /* For $this pointer */
                                }
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1608,30 +1586,51 @@ static int ZEND_FASTCALL  ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC
        USE_OPLINE
        zval *func_name;
        zval *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
 
        func_name = opline->op2.zv + 1;
        if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
                func_name++;
                if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
        } else {
-               call->fbc = Z_FUNC_P(func);
-               CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+               fbc = Z_FUNC_P(func);
+               CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
        }
 
-       call->object = NULL;
-       call->called_scope = NULL;
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *fname = opline->op2.zv;
+       zval *func;
+       zend_function *fbc;
+
+       if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
+       } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
+           SAVE_OPLINE();
+               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
+       } else {
+               fbc = Z_FUNC_P(func);
+               CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1640,8 +1639,7 @@ static int ZEND_FASTCALL  ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zval *arguments = EX(prev_execute_data)->function_state.arguments;
-       zend_uint arg_count = Z_LVAL_P(arguments);
+       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
        zval *var_ptr;
 
        SAVE_OPLINE();
@@ -1658,7 +1656,7 @@ static int ZEND_FASTCALL  ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
                        }
                }
        } else {
-               zval *param = arguments - arg_count + arg_num - 1;
+               zval *param = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
                ZVAL_COPY(var_ptr, param);
        }
 
@@ -1786,26 +1784,25 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
 static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *object;
        zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
 
        if (IS_TMP_VAR == IS_CONST) {
                function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-                       call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+                       fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
                } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
 
-               call->object = NULL;
-               call->called_scope = NULL;
-               call->num_additional_args = 0;
-               call->is_ctor_call = 0;
-               EX(call) = call;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -1831,33 +1828,28 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                        STR_FREE(lcname);
                        zval_dtor(free_op2.var);
 
-                       call->fbc = Z_FUNC_P(func);
-                       call->object = NULL;
-                       call->called_scope = NULL;
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
                } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
                    EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                        Z_OBJ_HANDLER_P(function_name, get_closure) &&
-                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
-                       if (call->object) {
-                               GC_REFCOUNT(call->object)++;
+                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+                       if (object) {
+                               GC_REFCOUNT(object)++;
                        }
                        if (IS_TMP_VAR == IS_VAR && 1 && Z_REFCOUNT_P(function_name) == 1 &&
-                           call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+                           fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                                /* Delay closure destruction until its invocation */
-                               call->fbc->common.prototype = (zend_function*)function_name_ptr;
+                               fbc->common.prototype = (zend_function*)function_name_ptr;
                        } else {
                                zval_dtor(free_op2.var);
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1883,40 +1875,39 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
-                               call->object = NULL;
-                               call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
-                               if (UNEXPECTED(call->called_scope == NULL)) {
+                               object = NULL;
+                               called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+                               if (UNEXPECTED(called_scope == NULL)) {
                                        CHECK_EXCEPTION();
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               if (call->called_scope->get_static_method) {
-                                       call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+                               if (called_scope->get_static_method) {
+                                       fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
                                } else {
-                                       call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+                                       fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
                                }
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
                                }
                        } else {
-                               call->called_scope = Z_OBJCE_P(obj);
-                               call->object = Z_OBJ_P(obj);
+                               called_scope = Z_OBJCE_P(obj);
+                               object = Z_OBJ_P(obj);
 
-                               call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+                               fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
                                }
 
-                               if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                                       call->object = NULL;
+                               if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+                                       object = NULL;
                                } else {
-                                       GC_REFCOUNT(call->object)++; /* For $this pointer */
+                                       GC_REFCOUNT(object)++; /* For $this pointer */
                                }
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        zval_dtor(free_op2.var);
                        CHECK_EXCEPTION();
@@ -1975,26 +1966,25 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
 static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *object;
        zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
 
        if (IS_VAR == IS_CONST) {
                function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-                       call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+                       fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
                } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
 
-               call->object = NULL;
-               call->called_scope = NULL;
-               call->num_additional_args = 0;
-               call->is_ctor_call = 0;
-               EX(call) = call;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2020,33 +2010,28 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                        STR_FREE(lcname);
                        zval_ptr_dtor_nogc(free_op2.var);
 
-                       call->fbc = Z_FUNC_P(func);
-                       call->object = NULL;
-                       call->called_scope = NULL;
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
                } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
                    EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                        Z_OBJ_HANDLER_P(function_name, get_closure) &&
-                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
-                       if (call->object) {
-                               GC_REFCOUNT(call->object)++;
+                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+                       if (object) {
+                               GC_REFCOUNT(object)++;
                        }
                        if (IS_VAR == IS_VAR && (free_op2.var != NULL) && Z_REFCOUNT_P(function_name) == 1 &&
-                           call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+                           fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                                /* Delay closure destruction until its invocation */
-                               call->fbc->common.prototype = (zend_function*)function_name_ptr;
+                               fbc->common.prototype = (zend_function*)function_name_ptr;
                        } else {
                                zval_ptr_dtor_nogc(free_op2.var);
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2072,40 +2057,39 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
-                               call->object = NULL;
-                               call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
-                               if (UNEXPECTED(call->called_scope == NULL)) {
+                               object = NULL;
+                               called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+                               if (UNEXPECTED(called_scope == NULL)) {
                                        CHECK_EXCEPTION();
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               if (call->called_scope->get_static_method) {
-                                       call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+                               if (called_scope->get_static_method) {
+                                       fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
                                } else {
-                                       call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+                                       fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
                                }
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
                                }
                        } else {
-                               call->called_scope = Z_OBJCE_P(obj);
-                               call->object = Z_OBJ_P(obj);
+                               called_scope = Z_OBJCE_P(obj);
+                               object = Z_OBJ_P(obj);
 
-                               call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+                               fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
                                }
 
-                               if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                                       call->object = NULL;
+                               if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+                                       object = NULL;
                                } else {
-                                       GC_REFCOUNT(call->object)++; /* For $this pointer */
+                                       GC_REFCOUNT(object)++; /* For $this pointer */
                                }
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        zval_ptr_dtor_nogc(free_op2.var);
                        CHECK_EXCEPTION();
@@ -2202,26 +2186,25 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
 static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *object;
        zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
 
        if (IS_CV == IS_CONST) {
                function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-                       call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+                       fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
                } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
                } else {
-                       call->fbc = Z_FUNC_P(func);
-                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+                       fbc = Z_FUNC_P(func);
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
                }
 
-               call->object = NULL;
-               call->called_scope = NULL;
-               call->num_additional_args = 0;
-               call->is_ctor_call = 0;
-               EX(call) = call;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2246,33 +2229,28 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                        }
                        STR_FREE(lcname);
 
-                       call->fbc = Z_FUNC_P(func);
-                       call->object = NULL;
-                       call->called_scope = NULL;
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
                } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
                    EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                        Z_OBJ_HANDLER_P(function_name, get_closure) &&
-                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
-                       if (call->object) {
-                               GC_REFCOUNT(call->object)++;
+                       Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+                       if (object) {
+                               GC_REFCOUNT(object)++;
                        }
                        if (IS_CV == IS_VAR && 0 && Z_REFCOUNT_P(function_name) == 1 &&
-                           call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+                           fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
                                /* Delay closure destruction until its invocation */
-                               call->fbc->common.prototype = (zend_function*)function_name_ptr;
+                               fbc->common.prototype = (zend_function*)function_name_ptr;
                        } else {
 
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2298,40 +2276,39 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
-                               call->object = NULL;
-                               call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
-                               if (UNEXPECTED(call->called_scope == NULL)) {
+                               object = NULL;
+                               called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+                               if (UNEXPECTED(called_scope == NULL)) {
                                        CHECK_EXCEPTION();
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               if (call->called_scope->get_static_method) {
-                                       call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+                               if (called_scope->get_static_method) {
+                                       fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
                                } else {
-                                       call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+                                       fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
                                }
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
                                }
                        } else {
-                               call->called_scope = Z_OBJCE_P(obj);
-                               call->object = Z_OBJ_P(obj);
+                               called_scope = Z_OBJCE_P(obj);
+                               object = Z_OBJ_P(obj);
 
-                               call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
-                               if (UNEXPECTED(call->fbc == NULL)) {
-                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+                               fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+                               if (UNEXPECTED(fbc == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
                                }
 
-                               if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-                                       call->object = NULL;
+                               if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+                                       object = NULL;
                                } else {
-                                       GC_REFCOUNT(call->object)++; /* For $this pointer */
+                                       GC_REFCOUNT(object)++; /* For $this pointer */
                                }
                        }
 
-                       call->num_additional_args = 0;
-                       call->is_ctor_call = 0;
-                       EX(call) = call;
+                       EX(call) = zend_vm_stack_push_call_frame(
+                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2557,34 +2534,6 @@ static int ZEND_FASTCALL  ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
        ZEND_VM_JMP(opline);
 }
 
-static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       USE_OPLINE
-
-       zval *fname = opline->op1.zv;
-       zval *func;
-       call_slot *call = EX(call_slots) + opline->op2.num;
-
-       if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
-               EX(function_state).function = CACHED_PTR(Z_CACHE_SLOT_P(fname));
-       } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
-           SAVE_OPLINE();
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
-       } else {
-               EX(function_state).function = Z_FUNC_P(func);
-               CACHE_PTR(Z_CACHE_SLOT_P(fname), EX(function_state).function);
-       }
-
-       call->fbc = EX(function_state).function;
-       call->object = NULL;
-       call->called_scope = NULL;
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
-
-       return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
 static int ZEND_FASTCALL  ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -2709,8 +2658,8 @@ static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
 
 
        SAVE_OPLINE();
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
                }
        }
@@ -2993,13 +2942,15 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
+               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
                        return_value = EX_VAR(opline->result.var);
                }
 
-               EX(function_state).function = (zend_function *) new_op_array;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -3012,10 +2963,11 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                        zend_execute(new_op_array, return_value TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3789,7 +3741,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -3807,24 +3760,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_CONST == IS_CONST &&
            IS_CONST == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_CONST != IS_CONST &&
                   IS_CONST == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_CONST != IS_UNUSED) {
 
@@ -3840,20 +3786,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_CONST == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_CONST == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_CONST != IS_CONST) {
@@ -3866,33 +3812,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       if (IS_CONST != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
+               }
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4757,7 +4708,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -4775,24 +4727,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_CONST == IS_CONST &&
            IS_TMP_VAR == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_CONST != IS_CONST &&
                   IS_TMP_VAR == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op2;
@@ -4808,20 +4753,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_TMP_VAR == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_CONST == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_TMP_VAR != IS_CONST) {
@@ -4834,33 +4779,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       if (IS_CONST != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
+               }
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5593,7 +5543,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -5611,24 +5562,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_CONST == IS_CONST &&
            IS_VAR == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_CONST != IS_CONST &&
                   IS_VAR == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op2;
@@ -5644,20 +5588,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_VAR == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_CONST == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_VAR != IS_CONST) {
@@ -5670,33 +5614,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       if (IS_CONST != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
+               }
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -6288,7 +6237,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -6306,24 +6256,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_CONST == IS_CONST &&
            IS_UNUSED == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_CONST != IS_CONST &&
                   IS_UNUSED == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_UNUSED != IS_UNUSED) {
 
@@ -6339,20 +6282,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_UNUSED == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_CONST == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_UNUSED != IS_CONST) {
@@ -6365,33 +6308,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (IS_CONST != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -6681,7 +6629,7 @@ static int ZEND_FASTCALL  ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
        }
 
        closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC;
-       closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
+       closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC;
        if (closure_is_static || closure_is_being_defined_inside_static_context) {
                zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC);
        } else {
@@ -7119,7 +7067,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -7137,24 +7086,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_CONST == IS_CONST &&
            IS_CV == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_CONST != IS_CONST &&
                   IS_CV == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_CV != IS_UNUSED) {
 
@@ -7170,20 +7112,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_CV == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_CONST == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_CV != IS_CONST) {
@@ -7196,33 +7138,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (IS_CONST != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -7910,8 +7857,8 @@ static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
        zend_free_op free_op1;
 
        SAVE_OPLINE();
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
                }
        }
@@ -8196,13 +8143,15 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
+               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
                        return_value = EX_VAR(opline->result.var);
                }
 
-               EX(function_state).function = (zend_function *) new_op_array;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -8215,10 +8164,11 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                        zend_execute(new_op_array, return_value TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -9079,8 +9029,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -9095,29 +9047,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
        }
 
        object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CONST != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CONST == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -9128,15 +9080,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -9914,8 +9865,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1, free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -9930,29 +9883,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
        }
 
        object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_TMP_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_TMP_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -9963,15 +9916,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -10750,8 +10702,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1, free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -10766,29 +10720,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
        }
 
        object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -10799,15 +10753,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -12136,8 +12089,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -12152,29 +12107,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
        }
 
        object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CV != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CV == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -12185,15 +12140,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -13073,7 +13027,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                        return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        } else {
-               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        }
@@ -13094,7 +13048,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
        } else {
                if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
                        !(opline->extended_value & ZEND_ARG_SEND_SILENT) :
-                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error(E_STRICT, "Only variables should be passed by reference");
                }
                top = zend_vm_stack_top_inc(TSRMLS_C);
@@ -13147,8 +13101,8 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
        zval *varptr, *top;
        zend_free_op free_op1;
 
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        }
@@ -13447,13 +13401,15 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
+               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
                        return_value = EX_VAR(opline->result.var);
                }
 
-               EX(function_state).function = (zend_function *) new_op_array;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -13466,10 +13422,11 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                        zend_execute(new_op_array, return_value TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -15334,8 +15291,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -15350,29 +15309,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
        }
 
        object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CONST != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CONST == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -15383,15 +15342,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -15404,7 +15362,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -15422,24 +15381,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_VAR == IS_CONST &&
            IS_CONST == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_VAR != IS_CONST &&
                   IS_CONST == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_CONST != IS_UNUSED) {
 
@@ -15455,20 +15407,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_CONST == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_VAR == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_CONST != IS_CONST) {
@@ -15481,33 +15433,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (IS_VAR != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -17562,8 +17519,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1, free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -17578,29 +17537,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
        }
 
        object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_TMP_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_TMP_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -17611,15 +17570,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
        zval_ptr_dtor_nogc(free_op1.var);
@@ -17633,7 +17591,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -17651,24 +17610,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_VAR == IS_CONST &&
            IS_TMP_VAR == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_VAR != IS_CONST &&
                   IS_TMP_VAR == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op2;
@@ -17684,20 +17636,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_TMP_VAR == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_VAR == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_TMP_VAR != IS_CONST) {
@@ -17710,33 +17662,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       if (IS_VAR != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
+               }
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -19758,8 +19715,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1, free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -19774,29 +19733,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
        }
 
        object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -19807,15 +19766,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
        zval_ptr_dtor_nogc(free_op1.var);
@@ -19829,7 +19787,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -19847,24 +19806,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_VAR == IS_CONST &&
            IS_VAR == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_VAR != IS_CONST &&
                   IS_VAR == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op2;
@@ -19880,20 +19832,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_VAR == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_VAR == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_VAR != IS_CONST) {
@@ -19906,33 +19858,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (IS_VAR != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -21295,7 +21252,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -21313,24 +21271,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_VAR == IS_CONST &&
            IS_UNUSED == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_VAR != IS_CONST &&
                   IS_UNUSED == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_UNUSED != IS_UNUSED) {
 
@@ -21346,20 +21297,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_UNUSED == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_VAR == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_UNUSED != IS_CONST) {
@@ -21372,33 +21323,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
+               }
+       }
+
+       if (IS_VAR != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -23129,8 +23085,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op1;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -23145,29 +23103,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
        }
 
        object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CV != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CV == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -23178,15 +23136,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -23199,7 +23156,8 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
        USE_OPLINE
        zval *function_name;
        zend_class_entry *ce;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_object *object;
+       zend_function *fbc;
 
        SAVE_OPLINE();
 
@@ -23217,24 +23175,17 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                        }
                        CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
                }
-               call->called_scope = ce;
        } else {
                ce = Z_CE_P(EX_VAR(opline->op1.var));
-
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
-                       call->called_scope = EG(called_scope);
-               } else {
-                       call->called_scope = ce;
-               }
        }
 
        if (IS_VAR == IS_CONST &&
            IS_CV == IS_CONST &&
            CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
-               call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+               fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
        } else if (IS_VAR != IS_CONST &&
                   IS_CV == IS_CONST &&
-                  (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+                  (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
                /* do nothing */
        } else if (IS_CV != IS_UNUSED) {
 
@@ -23250,20 +23201,20 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                }
 
                if (ce->get_static_method) {
-                       call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+                       fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
                } else {
-                       call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
                }
-               if (UNEXPECTED(call->fbc == NULL)) {
+               if (UNEXPECTED(fbc == NULL)) {
                        zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
                }
                if (IS_CV == IS_CONST &&
-                   EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                   EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+                   EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                   EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
                        if (IS_VAR == IS_CONST) {
-                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+                               CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
                        } else {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
                        }
                }
                if (IS_CV != IS_CONST) {
@@ -23276,33 +23227,38 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
                }
-               call->fbc = ce->constructor;
+               fbc = ce->constructor;
        }
 
-       if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
-               call->object = NULL;
+       if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
+               object = NULL;
        } else {
                if (Z_OBJ(EG(This)) &&
                    Z_OBJ_HT(EG(This))->get_class_entry &&
                    !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
                    /* We are calling method of the other (incompatible) class,
                       but passing $this. This is done for compatibility with php-4. */
-                       if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
-                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                       if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                               zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        } else {
                                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
-                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+                               zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
                        }
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+               object = Z_OBJ(EG(This));
+               if (object) {
+                       GC_REFCOUNT(object)++;
                }
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       if (IS_VAR != IS_CONST) {
+               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+                       ce = EG(called_scope);
+               }
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -24706,8 +24662,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
        USE_OPLINE
        zval *function_name;
 
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -24722,29 +24680,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
        }
 
        object = _get_obj_zval_ptr_unused(TSRMLS_C);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CONST != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CONST == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -24755,15 +24713,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -26079,8 +26036,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -26095,29 +26054,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
        }
 
        object = _get_obj_zval_ptr_unused(TSRMLS_C);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_TMP_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_TMP_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -26128,15 +26087,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -27356,8 +27314,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -27372,29 +27332,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
        }
 
        object = _get_obj_zval_ptr_unused(TSRMLS_C);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -27405,15 +27365,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -29143,8 +29102,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
        USE_OPLINE
        zval *function_name;
 
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -29159,29 +29120,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
        }
 
        object = _get_obj_zval_ptr_unused(TSRMLS_C);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CV != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CV == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -29192,15 +29153,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -30216,7 +30176,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                        return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        } else {
-               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+               if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        }
@@ -30237,7 +30197,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
        } else {
                if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
                        !(opline->extended_value & ZEND_ARG_SEND_SILENT) :
-                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+                       !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        zend_error(E_STRICT, "Only variables should be passed by reference");
                }
                top = zend_vm_stack_top_inc(TSRMLS_C);
@@ -30289,8 +30249,8 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        zval *varptr, *top;
 
 
-       if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
-               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+       if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
                        return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                }
        }
@@ -30576,13 +30536,15 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
+               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
                        return_value = EX_VAR(opline->result.var);
                }
 
-               EX(function_state).function = (zend_function *) new_op_array;
+               EX(call) = zend_vm_stack_push_call_frame(
+                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -30595,10 +30557,11 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                        zend_execute(new_op_array, return_value TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
+               call = EX(call);
+               EX(call) = EX(call)->prev;
+               zend_vm_stack_free((zval*)call TSRMLS_CC);
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -32312,8 +32275,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
        USE_OPLINE
        zval *function_name;
 
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -32328,29 +32293,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
        }
 
        object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CONST != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CONST == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -32361,15 +32326,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -34354,8 +34318,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -34370,29 +34336,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
        }
 
        object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_TMP_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_TMP_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -34403,15 +34369,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -36432,8 +36397,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
        USE_OPLINE
        zval *function_name;
        zend_free_op free_op2;
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -36448,29 +36415,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
        }
 
        object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_VAR != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_VAR == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -36481,15 +36448,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -39551,8 +39517,10 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
        USE_OPLINE
        zval *function_name;
 
-       call_slot *call = EX(call_slots) + opline->result.num;
        zval *object;
+       zend_function *fbc;
+       zend_class_entry *called_scope;
+       zend_object *obj;
 
        SAVE_OPLINE();
 
@@ -39567,29 +39535,29 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
        }
 
        object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
+       obj = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (EXPECTED(obj != NULL)) {
+               called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
                if (IS_CV != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+                   (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+                   zend_object *orig_obj = obj;
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
+                       if (UNEXPECTED(obj->handlers->get_method == NULL)) {
                                zend_error_noreturn(E_ERROR, "Object does not support method calls");
                        }
 
                        /* First, locate the function. */
-                       call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
-                       if (UNEXPECTED(call->fbc == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
+                       fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(fbc == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
                        }
                        if (IS_CV == IS_CONST &&
-                           EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
-                           EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
-                           EXPECTED(call->object == object)) {
-                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
+                           EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+                           EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+                           EXPECTED(obj == orig_obj)) {
+                               CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
                        }
                }
        } else {
@@ -39600,15 +39568,14 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
        }
 
-       if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
-               call->object = NULL;
+       if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+               obj = NULL;
        } else {
-               GC_REFCOUNT(call->object)++; /* For $this pointer */
+               GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
-       call->num_additional_args = 0;
-       call->is_ctor_call = 0;
-       EX(call) = call;
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -41678,56 +41645,56 @@ void zend_init_opcodes_handlers(void)
        ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
-       ZEND_DO_FCALL_SPEC_CONST_HANDLER,
-       ZEND_DO_FCALL_SPEC_CONST_HANDLER,
-       ZEND_DO_FCALL_SPEC_CONST_HANDLER,
-       ZEND_DO_FCALL_SPEC_CONST_HANDLER,
-       ZEND_DO_FCALL_SPEC_CONST_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_DO_FCALL_SPEC_HANDLER,
+       ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
-       ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
        ZEND_RETURN_SPEC_CONST_HANDLER,
        ZEND_RETURN_SPEC_CONST_HANDLER,
        ZEND_RETURN_SPEC_CONST_HANDLER,
@@ -44438,6 +44405,6 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* op)
 
 ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS)
 {
-       return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       return ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
 }
 
index df127039c6b0556a5ede6b067a040e50368730dd..8859228aad049b5a2b595e5d2fb94e93ae037c46 100644 (file)
@@ -83,7 +83,7 @@ const char *zend_vm_opcodes_map[169] = {
        "ZEND_END_SILENCE",
        "ZEND_INIT_FCALL_BY_NAME",
        "ZEND_DO_FCALL",
-       "ZEND_DO_FCALL_BY_NAME",
+       "ZEND_INIT_FCALL",
        "ZEND_RETURN",
        "ZEND_RECV",
        "ZEND_RECV_INIT",
index df499f946b74db25bb1b69849d426a08285a7e36..7d74a807b5f9038741873ba1804c0cf663460520 100644 (file)
@@ -84,7 +84,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
 #define ZEND_END_SILENCE                      58
 #define ZEND_INIT_FCALL_BY_NAME               59
 #define ZEND_DO_FCALL                         60
-#define ZEND_DO_FCALL_BY_NAME                 61
+#define ZEND_INIT_FCALL                       61
 #define ZEND_RETURN                           62
 #define ZEND_RECV                             63
 #define ZEND_RECV_INIT                        64
index 7baebd36d88127ac1a6c5fd97b9e0670c78957a5..a3b6d085785aba8e7f59ced45b6ff013fa504bd2 100644 (file)
@@ -1958,7 +1958,6 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
                                        case ZEND_ASSIGN:
                                        case ZEND_ASSIGN_REF:
                                        case ZEND_DO_FCALL:
-                                       case ZEND_DO_FCALL_BY_NAME:
                                                if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
                                                        ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
index 26af07a189262b6653565ec4289c73609b2c2694..480e4f92fe4f3147d718c06d21320e7b1dd57a60 100644 (file)
@@ -108,8 +108,8 @@ static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_c
                end = opline + op_array->last;
                while (opline < end) {
                        switch (opline->opcode) {
-                               case ZEND_DO_FCALL:
-                                       LITERAL_INFO(opline->op1.constant, LITERAL_FUNC, 1, 1, 1);
+                               case ZEND_INIT_FCALL:
+                                       LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
                                        break;
                                case ZEND_INIT_FCALL_BY_NAME:
                                        if (ZEND_OP2_TYPE(opline) == IS_CONST) {
index cd27704de5211e6e26987e5ee5b7b9560b48454d..3f755bed1867c97e7a5e88955dffd9d240fbaf81 100644 (file)
@@ -12,9 +12,15 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
        zend_op *opline = op_array->opcodes;
        zend_op *end = opline + op_array->last;
        int call = 0;
-       void *checkpoint = zend_arena_checkpoint(ctx->arena)
-       optimizer_call_info *call_stack = zend_arena_calloc(&ctx->arena, op_array->nested_calls + 1, sizeof(optimizer_call_info));
+       void *checkpoint; 
+       optimizer_call_info *call_stack;
 
+       if (op_array->last < 2) {
+               return;
+       }
+
+       checkpoint = zend_arena_checkpoint(ctx->arena); 
+       call_stack = zend_arena_calloc(&ctx->arena, op_array->last / 2, sizeof(optimizer_call_info));
        while (opline < end) {
                switch (opline->opcode) {
                        case ZEND_INIT_FCALL_BY_NAME:
@@ -31,23 +37,27 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
                        case ZEND_NEW:
                        case ZEND_INIT_METHOD_CALL:
                        case ZEND_INIT_STATIC_METHOD_CALL:
+                       case ZEND_INIT_FCALL:
                                call_stack[call].opline = opline;
                                call++;
                                break;
-                       case ZEND_DO_FCALL_BY_NAME:
+                       case ZEND_DO_FCALL:
                                call--;
                                if (call_stack[call].func && call_stack[call].opline) {
                                        zend_op *fcall = call_stack[call].opline;
 
-                                       opline->opcode = ZEND_DO_FCALL;
-                                       ZEND_OP1_TYPE(opline) = IS_CONST;
-                                       opline->op1.constant = fcall->op2.constant + 1;
-                                       Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
-                                       literal_dtor(&ZEND_OP2_LITERAL(fcall));
-                                       if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
+                                       if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
+                                               fcall->opcode = ZEND_INIT_FCALL;
+                                               literal_dtor(&ZEND_OP2_LITERAL(fcall));
+                                               fcall->op2.constant = fcall->op2.constant + 1;
+                                       } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
+                                               fcall->opcode = ZEND_INIT_FCALL;
+                                               literal_dtor(&op_array->literals[fcall->op2.constant]);
                                                literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
+                                               fcall->op2.constant = fcall->op2.constant + 1;
+                                       } else {
+                                               ZEND_ASSERT(0);
                                        }
-                                       MAKE_NOP(fcall);
                                } else if (opline->extended_value == 0 &&
                                           call_stack[call].opline &&
                                           call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME &&
@@ -55,12 +65,9 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
 
                                        zend_op *fcall = call_stack[call].opline;
 
-                                       opline->opcode = ZEND_DO_FCALL;
-                                       ZEND_OP1_TYPE(opline) = IS_CONST;
-                                       opline->op1.constant = fcall->op2.constant + 1;
-                                       Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
+                                       fcall->opcode = ZEND_INIT_FCALL;
                                        literal_dtor(&ZEND_OP2_LITERAL(fcall));
-                                       MAKE_NOP(fcall);
+                                       fcall->op2.constant = fcall->op2.constant + 1;
                                }
                                call_stack[call].func = NULL;
                                call_stack[call].opline = NULL;
@@ -79,21 +86,21 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
                                }
                                break;
                        case ZEND_SEND_VAL:
-                               if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+                               if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
                                        if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
                                                /* We won't convert it into_DO_FCALL to emit error at run-time */
                                                call_stack[call - 1].opline = NULL;
                                        } else {
-                                               opline->extended_value = ZEND_DO_FCALL;
+                                               opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
                                        }
                                }
                                break;
                        case ZEND_SEND_VAR:
-                               if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+                               if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
                                        if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
                                                opline->opcode = ZEND_SEND_REF;
                                        }
-                                       opline->extended_value = ZEND_DO_FCALL;
+                                       opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
                                }
                                break;
                        case ZEND_SEND_VAR_NO_REF:
@@ -104,12 +111,12 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
                                                opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND;
                                        } else {
                                                opline->opcode = ZEND_SEND_VAR;
-                                               opline->extended_value = ZEND_DO_FCALL;
+                                               opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
                                        }
                                }
                                break;
                        case ZEND_SEND_REF:
-                               if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+                               if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND && call_stack[call - 1].func) {
                                        /* We won't handle run-time pass by reference */
                                        call_stack[call - 1].opline = NULL;
                                }
index 73fa0d02f9fc25146a29559effe9130077213826..de97f64db85be78364cdcd5120114f447bdaff71 100644 (file)
@@ -320,22 +320,25 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
 #endif
                        break;
 
-               case ZEND_DO_FCALL:
+               case ZEND_INIT_FCALL:
                        /* define("name", scalar); */
                        if (collect_constants &&
-                           opline->extended_value == 2 &&
-                           ZEND_OP1_TYPE(opline) == IS_CONST &&
-                           Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
-                           Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 &&
-                           zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
-                           (opline-1)->opcode == ZEND_SEND_VAL &&
-                           ZEND_OP1_TYPE(opline-1) == IS_CONST &&
-                           Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_STRING &&
-                           (opline-2)->opcode == ZEND_SEND_VAL &&
-                           ZEND_OP1_TYPE(opline-2) == IS_CONST &&
-                           Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
-                               zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
-                               break;
+                           ZEND_OP2_TYPE(opline) == IS_CONST &&
+                           Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
+                           Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("define")-1 &&
+                           zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), "define", sizeof("define")-1) == 0) {
+                               
+                               if ((opline+1)->opcode == ZEND_SEND_VAL &&
+                                   ZEND_OP1_TYPE(opline+1) == IS_CONST &&
+                                   Z_TYPE(ZEND_OP1_LITERAL(opline+1)) == IS_STRING &&
+                                   (opline+2)->opcode == ZEND_SEND_VAL &&
+                                   ZEND_OP1_TYPE(opline+2) == IS_CONST &&
+                                   Z_TYPE(ZEND_OP1_LITERAL(opline+2)) <= IS_STRING &&
+                                   (opline+3)->opcode == ZEND_DO_FCALL) {
+
+                                       zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline+1), &ZEND_OP1_LITERAL(opline+2));
+                                       break;
+                               }
                        } else {
                                /* don't colllect constants after any other function call */
                                collect_constants = 0;
@@ -348,40 +351,42 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                           is_callable(x)
                           extension_loaded(x)
                        */
-                       if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL &&
-                               ZEND_OP1_TYPE(opline - 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline - 1)) == IS_STRING &&
-                               ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
-                               if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                       if ((opline + 1)->opcode == ZEND_SEND_VAL &&
+                           (opline + 2)->opcode == ZEND_DO_FCALL &&
+                               ZEND_OP1_TYPE(opline + 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline + 1)) == IS_STRING &&
+                               ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
+                               if ((Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("function_exists")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "function_exists", sizeof("function_exists")-1)) ||
-                                       (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                                       (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("is_callable")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "is_callable", sizeof("is_callable")))) {
                                        zend_internal_function *func;
                                        char *lc_name = zend_str_tolower_dup(
-                                                       Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+                                                       Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
                                        
-                                       if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)))) != NULL &&
+                                       if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)))) != NULL &&
                                                        func->type == ZEND_INTERNAL_FUNCTION &&
                                                        func->module->type == MODULE_PERSISTENT) {
                                                zval t;
                                                ZVAL_BOOL(&t, 1);
-                                               if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
-                                                       MAKE_NOP((opline - 1));
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline));
+                                               if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+                                                       literal_dtor(&ZEND_OP2_LITERAL(opline));
                                                        MAKE_NOP(opline);
+                                                       literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+                                                       MAKE_NOP(opline + 1);
+                                                       MAKE_NOP(opline + 2);
                                                }
                                        }
                                        efree(lc_name);
-                               } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                               } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "extension_loaded", sizeof("extension_loaded")-1)) {
                                        zval t;
                                        char *lc_name = zend_str_tolower_dup(
-                                                       Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+                                                       Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
                                        zend_module_entry *m = zend_hash_str_find_ptr(&module_registry,
-                                                       lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+                                                       lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
 
                                        efree(lc_name);
                                        if (!m) {
@@ -398,51 +403,55 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                                                }
                                        } 
 
-                                       if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
-                                               literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
-                                               MAKE_NOP((opline - 1));
-                                               literal_dtor(&ZEND_OP1_LITERAL(opline));
+                                       if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+                                               literal_dtor(&ZEND_OP2_LITERAL(opline));
                                                MAKE_NOP(opline);
+                                               literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+                                               MAKE_NOP(opline + 1);
+                                               MAKE_NOP(opline + 2);
                                        }
-                               } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                               } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("defined")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "defined", sizeof("defined")-1)) {
                                        zval t;
 
-                                       if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) {
+                                       if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) {
 
                                                ZVAL_BOOL(&t, 1);
-                                               if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
-                                                       MAKE_NOP((opline - 1));
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline));
+                                               if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+                                                       literal_dtor(&ZEND_OP2_LITERAL(opline));
                                                        MAKE_NOP(opline);
+                                                       literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+                                                       MAKE_NOP(opline + 1);
+                                                       MAKE_NOP(opline + 2);
                                                }
                                        }
-                               } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                               } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("constant")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "constant", sizeof("constant")-1)) {
                                        zval t;
                                        
-                                       if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 1 TSRMLS_CC)) {
-                                               if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
-                                                       MAKE_NOP((opline - 1));
-                                                       literal_dtor(&ZEND_OP1_LITERAL(opline));
+                                       if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) {
+                                               if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+                                                       literal_dtor(&ZEND_OP2_LITERAL(opline));
                                                        MAKE_NOP(opline);
+                                                       literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+                                                       MAKE_NOP(opline + 1);
+                                                       MAKE_NOP(opline + 2);
                                                }
                                        }
-                               } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen")-1 &&
-                                       !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+                               } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("strlen")-1 &&
+                                       !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
                                                "strlen", sizeof("strlen")-1)) {
                                        zval t;
 
-                                       ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
-                                       if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
-                                               literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
-                                               MAKE_NOP((opline - 1));
-                                               literal_dtor(&ZEND_OP1_LITERAL(opline));
+                                       ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
+                                       if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+                                               literal_dtor(&ZEND_OP2_LITERAL(opline));
                                                MAKE_NOP(opline);
+                                               literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+                                               MAKE_NOP(opline + 1);
+                                               MAKE_NOP(opline + 2);
                                        }
                                }
                        }                       
@@ -485,7 +494,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                case ZEND_FE_RESET:
                case ZEND_FE_FETCH:
                case ZEND_NEW:
-               case ZEND_DO_FCALL_BY_NAME:
+               case ZEND_DO_FCALL:
 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
                case ZEND_JMP_SET:
 #endif
index 2ea6544e23ab1b839a670a7382711709bbd1ea8f..681a54a74eefd7618e65bf700bae44c121a21a7d 100644 (file)
@@ -178,12 +178,6 @@ static void update_op1_const(zend_op_array *op_array,
                                        zend_optimizer_add_literal(op_array, val TSRMLS_CC);
                                        STR_HASH_VAL(Z_STR(op_array->literals[opline->op1.constant+1]));
                                        break;
-                               case ZEND_DO_FCALL:
-                                       zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
-                                       opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
-                                       STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
-                                       Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
-                                       break;
                                default:
                                        opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
                                        STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
@@ -204,6 +198,13 @@ static void update_op2_const(zend_op_array *op_array,
 {
        ZEND_OP2_TYPE(opline) = IS_CONST;
 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+       if (opline->opcode == ZEND_INIT_FCALL) {
+               zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+               opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+               STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
+               Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
+               return;
+       }
        opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
        if (Z_TYPE_P(val) == IS_STRING) {
                STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
@@ -340,9 +341,9 @@ static int replace_var_by_const(zend_op_array *op_array,
                                                if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
                                                        return 0;
                                                }
-                                               opline->extended_value = ZEND_DO_FCALL;
+                                               opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
                                        } else {
-                                               opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+                                               opline->extended_value = 0;
                                        }
                                        opline->opcode = ZEND_SEND_VAL;
                                        break;
index 0ae3feb2eefee2bb9a5568cb5503fc01c8509cce..361d1207f8d4a5477b89b3d8b02a0e7461f1fd9f 100644 (file)
@@ -44,7 +44,7 @@
 #define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX)
 
 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-# define MAKE_NOP(opline)      { opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; }
+# define MAKE_NOP(opline)      { (opline)->opcode = ZEND_NOP; memset(&(opline)->result, 0, sizeof((opline)->result)); memset(&(opline)->op1, 0, sizeof((opline)->op1)); memset(&(opline)->op2, 0, sizeof((opline)->op2));(opline)->result_type=(opline)->op1_type=(opline)->op2_type=IS_UNUSED; (opline)->handler = zend_opcode_handlers[ZEND_NOP]; }
 # define RESULT_USED(op)       (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
 # define RESULT_UNUSED(op)     ((op->result_type & EXT_TYPE_UNUSED) != 0)
 # define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
index d353b00a06eaf0b16e5792901ee05fa2114ab656..ec76f37715a93777ef455ddeab3d9d514ef0be7a 100644 (file)
@@ -1102,7 +1102,6 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */
 
                                        memset(&execute_data, 0, sizeof(zend_execute_data));
                                        EG(current_execute_data) = &execute_data;
-                                       EX(function_state).function = pce->constructor;
                                        zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, &arg);
 
                                        if (EG(exception)) {
index 925f2de64e93f2e1555c9321acd465d6db67ec6b..22ccb8f2bb9e7828b651b48c025a4a7612abd9b8 100644 (file)
@@ -74,9 +74,10 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
 
                fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
 
-               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
-                       return -1;
-               }
+               // TODO: fpm_php_trace_dump() has be reimplemented ???
+//???          if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
+//???                  return -1;
+//???          }
 
                function = l;