]> granicus.if.org Git - php/commitdiff
Refactored parameter passing mechanism.
authorDmitry Stogov <dmitry@zend.com>
Mon, 30 Jun 2014 11:43:45 +0000 (15:43 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 30 Jun 2014 11:43:45 +0000 (15:43 +0400)
In PHP-5.6 and below each argument passed to user function was copies on VM stack twice.
Now we always have ZEND_INIT_FCALL (or simular) opcode that pushes "call frame" on top of VM stack.
"Call frame" is actually the same zend_execute_data structure.
All the following ZEND_SEND instructions push arguments on top of the stack in a way that they directly comes into corresponding CV variables of the called frame. Extra arguments are copied at the end of stack frame (after all CV and TMP variables) on function enterance.

There are two minor incompatibilities:
1) It's not allowed to decalre functions redefining arguments e.g. "function foo($a,$a) {}".
2) func_get_arg() and func_get args() return the current value of argument and not the original value that was sent.

26 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_execute.skl
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
ext/phar/phar_object.c
ext/spl/php_spl.c
sapi/cli/php_cli.c
sapi/fpm/fpm/fpm_php_trace.c

index 1568374f4eeaf9a373749014e4929e66d7e6fa32..6b469c2b0a034fe404e11e79626d720984526c75 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);
 
@@ -82,14 +80,13 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
 /* 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;
@@ -98,7 +95,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);
 
@@ -108,22 +106,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;
@@ -132,22 +128,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);
+               zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
+               param_ptr++;
        }
 
        return SUCCESS;
@@ -807,7 +803,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,
@@ -827,7 +823,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,
@@ -850,7 +846,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,
@@ -864,7 +860,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",
@@ -888,7 +884,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;
@@ -899,7 +895,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 */
@@ -970,7 +966,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..df81c5d666995de01c6ac6f72cfbc3b322d0bea6 100644 (file)
@@ -394,10 +394,10 @@ ZEND_FUNCTION(gc_disable)
    Get the number of arguments that were passed to the function */
 ZEND_FUNCTION(func_num_args)
 {
-       zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+       zend_execute_data *ex = EG(current_execute_data);
 
-       if (ex && ex->function_state.arguments) {
-               RETURN_LONG(Z_LVAL_P(ex->function_state.arguments));
+       if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) {
+               RETURN_LONG(ex->num_args);
        } else {
                zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
                RETURN_LONG(-1);
@@ -409,11 +409,10 @@ 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;
+       int arg_count, first_extra_arg;
        zval *arg;
        long requested_offset;
-       zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+       zend_execute_data *ex;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
                return;
@@ -424,20 +423,28 @@ ZEND_FUNCTION(func_get_arg)
                RETURN_FALSE;
        }
 
-       if (!ex || !ex->function_state.arguments) {
+       ex = EG(current_execute_data);
+       if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
                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->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);
+       first_extra_arg = ex->func->op_array.num_args;
+       if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+               first_extra_arg--;
+       }
+       if (requested_offset >= first_extra_arg && (ex->num_args > first_extra_arg)) {
+               arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
+       } else {
+               arg = ZEND_CALL_ARG(ex, requested_offset + 1);
+       }
        RETURN_ZVAL_FAST(arg);
 }
 /* }}} */
@@ -447,26 +454,45 @@ ZEND_FUNCTION(func_get_arg)
 ZEND_FUNCTION(func_get_args)
 {
        zval *p;
-       int arg_count;
+       int arg_count, first_extra_arg;
        int i;
-       zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+       zend_execute_data *ex = EG(current_execute_data);
 
-       if (!ex || !ex->function_state.arguments) {
+       if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
                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->num_args;
 
        array_init_size(return_value, arg_count);
        if (arg_count) {
                Bucket *q;              
 
-               p -= arg_count;
+               first_extra_arg = ex->func->op_array.num_args;
+               if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+                       first_extra_arg--;
+               }
                zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
+               i = 0;
                q = Z_ARRVAL_P(return_value)->arData;
-               for (i=0; i<arg_count; i++) {
+               p = ZEND_CALL_ARG(ex, 1);
+               if (ex->num_args > first_extra_arg) {
+                       while (i < first_extra_arg) {
+                               q->h = i;
+                               q->key = NULL;
+                               if (!Z_ISREF_P(p)) {
+                                       ZVAL_COPY(&q->val, p);
+                               } else {
+                                       ZVAL_DUP(&q->val, Z_REFVAL_P(p));
+                           }
+                               p++;
+                               q++;
+                               i++;
+                       }
+                       p = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T);
+               }
+               while (i < arg_count) {
                        q->h = i;
                        q->key = NULL;
                        if (!Z_ISREF_P(p)) {
@@ -476,6 +502,7 @@ ZEND_FUNCTION(func_get_args)
                    }
                        p++;
                        q++;
+                       i++;
                }
                Z_ARRVAL_P(return_value)->nNumUsed = i;
                Z_ARRVAL_P(return_value)->nNumOfElements = i;
@@ -1957,22 +1984,37 @@ 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_execute_data *call, zval *arg_array TSRMLS_DC)
 {
-       zval *p = curpos;
-       zval *arg;
-       int arg_count = Z_LVAL_P(p);
+       int num_args = call->num_args;
 
-       array_init_size(arg_array, arg_count);
-       p -= arg_count;
+       array_init_size(arg_array, num_args);
+       if (num_args) {
+               int i = 0;
+               zval *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);
+               if (call->func->type == ZEND_USER_FUNCTION) {
+                       int first_extra_arg = call->func->op_array.num_args;
+                       
+                       if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+                               first_extra_arg--;
+                       }
+                       if (call->num_args > first_extra_arg) {
+                               while (i < first_extra_arg) {
+                                       if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
+                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
+                                       p++;
+                                       i++;
+                               }
+                               p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
+                       }
+               }
+
+               while (i < num_args) {
+                       if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
+                       zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
+                       p++;
+                       i++;
                }
        }
 }
@@ -1996,6 +2038,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;
@@ -2025,17 +2068,16 @@ ZEND_FUNCTION(debug_print_backtrace)
 
                skip = ptr;
                /* skip internal handler */
-               if (!skip->op_array &&
+               if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
                    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;
                }
 
-               if (skip->op_array) {
-                       filename = skip->op_array->filename->val;
+               if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
+                       filename = skip->func->op_array.filename->val;
                        lineno = skip->opline->lineno;
                } else {
                        filename = NULL;
@@ -2044,41 +2086,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 = ptr->func;
+                       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 (func->type != ZEND_EVAL_CODE) {
+                               if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
+                                       debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
                                }
                        }
                } else {
@@ -2137,13 +2185,14 @@ 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 &&
+                                       !ZEND_USER_CODE(prev->call->func->common.type)) {
                                        prev = NULL;
                                        break;
                                }                                   
-                               if (prev->op_array) {
-                                       zend_printf(") called at [%s:%d]\n", prev->op_array->filename->val, prev->opline->lineno);
+                               if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
+                                       zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
                                        break;
                                }
                                prev = prev->prev_execute_data;
@@ -2166,6 +2215,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;
@@ -2194,17 +2244,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                skip = ptr;
                /* skip internal handler */
-               if (!skip->op_array &&
+               if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
                    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;
                }
 
-               if (skip->op_array) {
-                       filename = skip->op_array->filename->val;
+               if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
+                       filename = skip->func->op_array.filename->val;
                        lineno = skip->opline->lineno;
                        add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename);
                        add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
@@ -2216,15 +2265,16 @@ 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 &&
+                                       !ZEND_USER_CODE(prev->call->func->common.type) &&
+                                       !(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
+                                               (prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
                                        break;
                                }                                   
-                               if (prev->op_array) {
+                               if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
 // TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
-                                       add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_DUP(prev->op_array->filename, 0));
+                                       add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_DUP(prev->func->op_array.filename, 0));
                                        add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
                                        break;
                                }
@@ -2235,28 +2285,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 = ptr->func;
+                       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 +2326,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) {
+                               func->type != ZEND_EVAL_CODE) {
+                               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);
                                }
                        }
@@ -2333,7 +2389,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                        add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
                }
 
-               add_next_index_zval(return_value, &stack_frame);
+               zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
 
                include_filename = filename; 
 
index 3c2921f53cd630859dcad08752eb62bfa06ea874..053a5eb199a33f7eb266cabda01260f5102a4530 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());
@@ -213,7 +213,7 @@ static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
        if (closure->func.type == ZEND_USER_FUNCTION) {
                zend_execute_data *ex = EG(current_execute_data);
                while (ex) {
-                       if (ex->op_array == &closure->func.op_array) {
+                       if (ex->func == &closure->func) {
                                zend_error(E_ERROR, "Cannot destroy active lambda function");
                        }
                        ex = ex->prev_execute_data;
index c6116693b7679f1a0717b806c06c5deff55e99f8..647fab48be1478f6a3aba72e71f219029431a474 100644 (file)
@@ -97,9 +97,9 @@ ZEND_API zend_compiler_globals compiler_globals;
 ZEND_API zend_executor_globals executor_globals;
 #endif
 
-static void zend_push_function_call_entry(zend_function *fbc TSRMLS_DC) /* {{{ */
+static void zend_push_function_call_entry(zend_function *fbc, zend_uint opline_num TSRMLS_DC) /* {{{ */
 {
-       zend_function_call_entry fcall = { fbc };
+       zend_function_call_entry fcall = { fbc, opline_num };
        zend_stack_push(&CG(function_call_stack), &fcall);
 }
 /* }}} */
@@ -182,8 +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;
 }
@@ -1463,6 +1461,11 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
                                        && opline->result.var == op1->u.op.var) {
                                        if (opline->opcode == ZEND_NEW) {
                                                opline->result_type |= EXT_TYPE_UNUSED;
+                                               opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
+                                               while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
+                                                       opline--;
+                                               }
+                                               opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
                                        }
                                        break;
                                }
@@ -1841,7 +1844,9 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
                var.u.op.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC);
                Z_STR(varname->u.constant) = CG(active_op_array)->vars[EX_VAR_TO_NUM(var.u.op.var)];
                var.EA = 0;
-               if (Z_STRHASH(varname->u.constant) == THIS_HASHVAL &&
+               if (EX_VAR_TO_NUM(var.u.op.var) != CG(active_op_array)->num_args) {
+                       zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter %s", Z_STRVAL(varname->u.constant));
+               } else if (Z_STRHASH(varname->u.constant) == THIS_HASHVAL &&
                        Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
                    !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
                        if (CG(active_op_array)->scope &&
@@ -1949,6 +1954,8 @@ 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_uint op_number;
        zend_function *function;
        zend_string *lcname;
        char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
@@ -1977,10 +1984,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;
 
-       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;
-       }
+       op_number = get_next_op_number(CG(active_op_array));
+       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, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 0;
 }
@@ -2017,12 +2028,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;
@@ -2033,10 +2042,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;
-       }
+       zend_push_function_call_entry(NULL, last_op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2056,21 +2062,21 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC) /* {{{ */
 
 void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
 {
+       zend_uint op_number;
        zend_op *opline;
 
+       op_number = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        if (ns_call) {
                /* 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;
@@ -2081,10 +2087,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;
-       }
+       zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2481,6 +2484,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
 int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
 {
        znode class_node;
+       zend_uint op_number;
        zend_op *opline;
 
        if (method_name->op_type == IS_CONST) {
@@ -2501,14 +2505,14 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
            ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
                zend_resolve_class_name(class_name TSRMLS_CC);
                class_node = *class_name;
+               op_number = get_next_op_number(CG(active_op_array) TSRMLS_CC);
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        } else {
                zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+               op_number = get_next_op_number(CG(active_op_array) TSRMLS_CC);
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-               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 =
@@ -2529,10 +2533,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
                SET_NODE(opline->op2, method_name);
        }
 
-       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;
-       }
+       zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 1; /* Dynamic */
 }
@@ -2550,26 +2551,20 @@ 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;
+               zend_uint call_flags = 0;
 
-                       /* 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 = &CG(active_op_array)->opcodes[fcall->op_number];
+               opline->extended_value = fcall->arg_num;
+
+               if (opline->opcode == ZEND_NEW) {
+                       call_flags = ZEND_CALL_CTOR;
                }
+
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_DO_FCALL;
+               SET_UNUSED(opline->op1);
+               SET_UNUSED(opline->op2);
+               opline->op1.num = call_flags;
        }
 
        opline->result.var = get_temporary_variable(CG(active_op_array));
@@ -2577,10 +2572,6 @@ 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;
-       }
-       CG(context).used_stack -= fcall->arg_num;
        zend_stack_del_top(&CG(function_call_stack));
 }
 /* }}} */
@@ -2682,19 +2673,13 @@ 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;
        SET_NODE(opline->op1, param);
        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;
-       }
 }
 /* }}} */
 
@@ -2705,25 +2690,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 +5585,12 @@ 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;
-       }
+       zend_push_function_call_entry(NULL, new_token->u.op.opline_num TSRMLS_CC);
 }
 /* }}} */
 
@@ -5819,6 +5781,14 @@ 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;
+       opline->extended_value = 1;
+       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,28 +5800,18 @@ 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;
-       }
 }
 /* }}} */
 
index 5b5397844ffdc21e4d60dd8fe9acdf814f6f645e..b053ee9820b86c584b2cf190f712a0f42b240b35 100644 (file)
@@ -59,8 +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;
 } zend_compiler_context;
@@ -266,9 +264,6 @@ struct _zend_op_array {
 
        zend_uint T;
 
-       zend_uint nested_calls;
-       zend_uint used_stack;
-
        zend_brk_cont_element *brk_cont_array;
        int last_brk_cont;
 
@@ -336,14 +331,9 @@ 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 op_number;
        zend_uint arg_num;
        zend_bool uses_argument_unpacking;
 } zend_function_call_entry;
@@ -361,15 +351,6 @@ 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 enum _vm_frame_kind {
        VM_FRAME_NESTED_FUNCTION,       /* stackless VM call to function */
        VM_FRAME_NESTED_CODE,           /* stackless VM call to include/require/eval */
@@ -379,28 +360,38 @@ 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_object         *object;           /* current $this                  */
-       zend_class_entry    *scope;            /* function scope (self)          */
-       zend_class_entry    *called_scope;     /* function called scope (static) */
-       zend_array          *symbol_table;
+       zend_execute_data   *call;             /* current call                   */
        void               **run_time_cache;
+       zend_function       *func;             /* executed op_array              */
+       zend_uint            num_args;
+       zend_uchar           flags;
+       zend_uchar           frame_kind;
+       zend_class_entry    *called_scope;
+       zend_object         *object;
+       zend_execute_data   *prev_nested_call;
        zend_execute_data   *prev_execute_data;
        zval                *return_value;
-       vm_frame_kind        frame_kind;
-       // TODO: simplify call sequence and remove call_* ???
-       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;
+       zend_class_entry    *scope;            /* function scope (self)          */
+       zend_array          *symbol_table;
+       struct _zend_op     *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
+       zend_object         *delayed_exception;
+       zval                 old_error_reporting;
 };
 
+#define ZEND_CALL_CTOR               (1 << 0)
+#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1)
+#define ZEND_CALL_DONE               (1 << 2)
+
+#define ZEND_CALL_FRAME_SLOT \
+       ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + 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)))
+
 #define EX(element) execute_data.element
 
 #define EX_VAR_2(ex, n)                        ((zval*)(((char*)(ex)) + ((int)(n))))
-#define EX_VAR_NUM_2(ex, n)     (((zval*)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n))
+#define EX_VAR_NUM_2(ex, n)     (((zval*)(ex)) + (ZEND_CALL_FRAME_SLOT + ((int)(n))))
 
 #define EX_VAR(n)                              EX_VAR_2(execute_data, n)
 #define EX_VAR_NUM(n)                  EX_VAR_NUM_2(execute_data, n)
@@ -730,8 +721,8 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
 #define ZEND_FETCH_CLASS_DEFAULT       0
 #define ZEND_FETCH_CLASS_SELF          1
 #define ZEND_FETCH_CLASS_PARENT                2
-#define ZEND_FETCH_CLASS_MAIN          3       /* unused */
-#define ZEND_FETCH_CLASS_GLOBAL                4       /* unused */
+#define ZEND_FETCH_CLASS_MAIN          3       /* unused ??? */
+#define ZEND_FETCH_CLASS_GLOBAL                4       /* unused ??? */
 #define ZEND_FETCH_CLASS_AUTO          5
 #define ZEND_FETCH_CLASS_INTERFACE     6
 #define ZEND_FETCH_CLASS_STATIC                7
@@ -750,7 +741,6 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
 #define ZEND_PARSED_NEW                                        (1<<6)
 #define ZEND_PARSED_LIST_EXPR                  (1<<7)
 
-
 /* unset types */
 #define ZEND_UNSET_REG 0
 
@@ -770,6 +760,9 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
 #define        ZEND_EVAL_CODE                                          4
 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY     5
 
+/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
+#define ZEND_USER_CODE(type) ((type & 1) == 0)
+
 #define ZEND_INTERNAL_CLASS         1
 #define ZEND_USER_CLASS             2
 
@@ -877,7 +870,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..5318bbe2d3b584eb3f0e294a5be0a8bee1a5d27e 100644 (file)
@@ -525,12 +525,13 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ul
        }
 }
 
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
 {
        zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
        const char *fname = zf->common.function_name->val;
        const char *fsep;
        const char *fclass;
+       zval old_arg;
 
        if (zf->common.scope) {
                fsep =  "::";
@@ -540,11 +541,20 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen
                fclass = "";
        }
 
-       if (ptr && ptr->op_array) {
-               zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename->val, ptr->opline->lineno);
+       if (arg && zf->common.type == ZEND_USER_FUNCTION) {
+               ZVAL_COPY_VALUE(&old_arg, arg);
+               ZVAL_UNDEF(arg);
+       }
+
+       if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+               zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
        } else {
                zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
        }
+
+       if (arg && zf->common.type == ZEND_USER_FUNCTION) {
+               ZVAL_COPY_VALUE(arg, &old_arg);
+       }
 }
 
 static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
@@ -572,21 +582,21 @@ static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg
                if (Z_TYPE_P(arg) == IS_OBJECT) {
                        need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
                        if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
-                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val TSRMLS_CC);
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC);
                        }
                } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
                        need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
-                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
+                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC);
                }
        } else if (cur_arg_info->type_hint) {
                if (cur_arg_info->type_hint == IS_ARRAY) {
                        ZVAL_DEREF(arg);
                        if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
-                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
                        }
                } else if (cur_arg_info->type_hint == IS_CALLABLE) {
                        if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
-                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
                        }
 #if ZEND_DEBUG
                } else {
@@ -618,12 +628,12 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
                char *class_name;
 
                need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
-               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
+               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
        } else if (cur_arg_info->type_hint) {
                if (cur_arg_info->type_hint == IS_ARRAY) {
-                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
+                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
                } else if (cur_arg_info->type_hint == IS_CALLABLE) {
-                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
+                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL TSRMLS_CC);
 #if ZEND_DEBUG
                } else {
                        zend_error(E_ERROR, "Unknown typehint");
@@ -635,15 +645,15 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
 
 static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
 {
-       if (EXPECTED(!(EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
-           zend_verify_missing_arg_type((zend_function *) EX(op_array), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
-               const char *class_name = EX(op_array)->scope ? EX(op_array)->scope->name->val : "";
-               const char *space = EX(op_array)->scope ? "::" : "";
-               const char *func_name = EX(op_array)->function_name ? EX(op_array)->function_name->val : "main";
+       if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
+           zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
+               const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : "";
+               const char *space = EX(func)->common.scope ? "::" : "";
+               const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main";
                zend_execute_data *ptr = EX(prev_execute_data);
 
-               if(ptr && ptr->op_array) {
-                       zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->op_array->filename->val, ptr->opline->lineno);
+               if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+                       zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->func->op_array.filename->val, ptr->opline->lineno);
                } else {
                        zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
                }
@@ -1468,13 +1478,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
                );
        }
 }
@@ -1495,9 +1505,9 @@ void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{
 
 static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
 {
-       if (EXPECTED(EX(op_array)->last_var > 0)) {
+       if (EXPECTED(EX(func)->op_array.last_var > 0)) {
                zval *cv = EX_VAR_NUM(0);
-               zval *end = cv + EX(op_array)->last_var;
+               zval *end = cv + EX(func)->op_array.last_var;
                do {
                        zval_ptr_dtor(cv);
                        cv++;
@@ -1517,132 +1527,65 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
  * ==================
  *
  *                             +========================================+
- *                             | zend_execute_data                      |<---+
- *                             |     EX(function_state).arguments       |--+ |
- *                             |  ...                                   |  | |
- *                             | ARGUMENT [1]                           |  | |
- *                             | ...                                    |  | |
- *                             | ARGUMENT [ARGS_NUMBER]                 |  | |
- *                             | ARGS_NUMBER                            |<-+ |
- *                             +========================================+    |
- *                                                                           |
- *                             +========================================+    |
- * EG(current_execute_data) -> | zend_execute_data                      |    |
- *                             |     EX(prev_execute_data)              |----+
+ * EG(current_execute_data) -> | zend_execute_data                      |
  *                             +----------------------------------------+
- *     EX_CV_NUM(0) ---------> | VAR[0]                                 |
+ *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
+ *                             | ...                                    |
+ *                             | VAR[op_array->num_args-1] = ARG[N]     |
  *                             | ...                                    |
  *                             | VAR[op_array->last_var-1]              |
- *                             | VAR[op_array->last_var]                |
+ *                             | VAR[op_array->last_var] = TMP[0]       |
  *                             | ...                                    |
  *                             | VAR[op_array->last_var+op_array->T-1]  |
- *                             +----------------------------------------+
- *           EX(call_slots) -> | CALL_SLOT[0]                           |
+ *                             | ARG[N+1] (extra_args)                  |
  *                             | ...                                    |
- *                             | CALL_SLOT[op_array->nested_calls-1]    |
- *                             +----------------------------------------+
- * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0]                    |
- *                             | ...                                    |
- * zend_vm_stack_top --------> | ...                                    |
- *                             | ...                                    |
- *                             | ARGUMENTS STACK [op_array->used_stack] |
  *                             +----------------------------------------+
  */
 
-static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
 {
-       zend_execute_data *execute_data;
-
-       /*
-        * When allocating the execute_data, memory for compiled variables and
-        * temporary variables is also allocated before and after the actual
-        * zend_execute_data struct. In addition we also allocate space to store
-        * information about syntactically nested called functions and actual
-        * parameters. op_array->last_var specifies the number of compiled
-        * variables and op_array->T is the number of temporary variables. If there
-        * is no symbol table, then twice as much memory is allocated for compiled
-        * variables. In that case the first half contains zval**s and the second
-        * half the actual zval*s (which would otherwise be in the symbol table).
-        */
-       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;
-
-       /*
-        * Normally the execute_data is allocated on the VM stack (because it does
-        * not actually do any allocation and thus is faster). For generators
-        * though this behavior would be suboptimal, because the (rather large)
-        * structure would have to be copied back and forth every time execution is
-        * suspended or resumed. That's why for generators the execution context
-        * is allocated using a separate VM stack, thus allowing to save and
-        * restore it simply by replacing a pointer. The same segment also keeps
-        * a copy of previous execute_data and passed parameters.
-        */
-       if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
-               /* Prepend the regular stack frame with a copy of prev_execute_data
-                * 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);
-
-               total_size += args_size + execute_data_size;
-
-               EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(zval) - 1)) / sizeof(zval));
-               EG(argument_stack)->prev = NULL;
-               execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size);
-
-               /* 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)));
-
-               /* 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);
-                       int i;
-
-                       for (i = 0; i < args_count; i++) {
-                               ZVAL_COPY(arg_dst + i, arg_src + i);
-                       }
-               }
-       } else {
-               execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
-               EX(prev_execute_data) = EG(current_execute_data);
-       }
+       ZEND_ASSERT(EX(func) == (zend_function*)op_array);
+       ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
+       ZEND_ASSERT(EX(called_scope) == EG(called_scope));
 
        EX(return_value) = return_value;
        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);
-       EX(called_scope) = EG(called_scope);
        EX(symbol_table) = EG(active_symbol_table);
 
-       if (EX(symbol_table)) {
+       if (UNEXPECTED(EX(symbol_table) != NULL)) {
                zend_attach_symbol_table(execute_data);
        } else {
+               zend_uint first_extra_arg = op_array->num_args;
+               
+               if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
+                       first_extra_arg--;
+               }
+               if (UNEXPECTED(EX(num_args) > first_extra_arg)) {
+                       /* move extra args into separate array after all CV and TMP vars */
+                       zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T);
+
+                       memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
+               }
+
                do {
-                       /* Initialize CV variables */
-                       zval *var = EX_VAR_NUM(0);
-                       zval *end = var + op_array->last_var;
+                       /* Initialize CV variables (skip arguments) */
+                       int num_args = MIN(op_array->num_args, EX(num_args));
 
-                       while (var != end) {
-                               ZVAL_UNDEF(var);
-                               var++;
+                       if (EXPECTED(num_args < op_array->last_var)) {
+                               zval *var = EX_VAR_NUM(num_args);
+                               zval *end = EX_VAR_NUM(op_array->last_var);
+
+                               do {
+                                       ZVAL_UNDEF(var);
+                                       var++;
+                               } while (var != end);
                        }
                } while (0);
 
@@ -1661,62 +1604,120 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
        }
        EX(run_time_cache) = op_array->run_time_cache;
 
-       EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
        EG(current_execute_data) = execute_data;
+}
+/* }}} */
+
+ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
+{
+       /*
+        * Normally the execute_data is allocated on the VM stack (because it does
+        * not actually do any allocation and thus is faster). For generators
+        * though this behavior would be suboptimal, because the (rather large)
+        * structure would have to be copied back and forth every time execution is
+        * suspended or resumed. That's why for generators the execution context
+        * is allocated using a separate VM stack, thus allowing to save and
+        * restore it simply by replacing a pointer.
+        */
+       zend_execute_data *execute_data;
+       zend_uint num_args = EG(current_execute_data)->call->num_args;
+
+       EG(argument_stack) = zend_vm_stack_new_page(
+               MAX(ZEND_VM_STACK_PAGE_SIZE, 
+                       ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)));
+       EG(argument_stack)->prev = NULL;
+
+       execute_data = zend_vm_stack_push_call_frame(
+               (zend_function*)op_array,
+               num_args,
+               EG(current_execute_data)->call->flags,
+               EG(current_execute_data)->call->called_scope,
+               EG(current_execute_data)->call->object,
+               NULL TSRMLS_CC);
+       execute_data->num_args = num_args;
+
+       /* copy arguments */
+       if (num_args > 0) {
+               zval *arg_src = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+               zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
+               int i;
+
+               for (i = 0; i < num_args; i++) {
+                       ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
+               }
+       }
+
+       i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
 
        return execute_data;
 }
 /* }}} */
 
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
 {
-       return i_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
+       zend_execute_data *execute_data;
+       
+       execute_data = EG(current_execute_data)->call;
+       EX(prev_execute_data) = EG(current_execute_data);
+       i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC);
+
+       return execute_data;
 }
 /* }}} */
 
-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_execute_data *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) /* {{{ */
-{
-       zend_vm_stack p = EG(argument_stack);
-
-       zend_vm_stack_extend(count + 1 TSRMLS_CC);
+static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+{
+       zend_execute_data *new_call;
+       int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
+               
+       /* copy call frame into new stack segment */
+       zend_vm_stack_extend(used_stack TSRMLS_CC);
+       new_call = (zend_execute_data*)EG(argument_stack)->top;
+       EG(argument_stack)->top += used_stack;          
+       *new_call = *call;
+       if (passed_args) {
+               zval *src = ZEND_CALL_ARG(call, 1);
+               zval *dst = ZEND_CALL_ARG(new_call, 1);
+               do {
+                       ZVAL_COPY_VALUE(dst, src);
+                       passed_args--;
+                       src++;
+                       dst++;
+               } while (passed_args);
+       }
 
-       EG(argument_stack)->top += count;
-       ZVAL_LONG(EG(argument_stack)->top, count);
-       while (count-- > 0) {
-               zval *data = --p->top;
-               ZVAL_COPY_VALUE(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count, data);
+       /* delete old call_frame from previous stack segment */
+       EG(argument_stack)->prev->top = (zval*)call;
 
-               if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
-                       zend_vm_stack r = p;
+       /* delete previous stack segment if it becames empty */
+       if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) {
+               zend_vm_stack r = EG(argument_stack)->prev;
 
-                       EG(argument_stack)->prev = p->prev;
-                       p = p->prev;
-                       efree(r);
-               }
+               EG(argument_stack)->prev = r->prev;
+               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_extend_call_frame(zend_execute_data **call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
 {
-       if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
-               || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
-               return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
+       if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
+               EG(argument_stack)->top += additional_args;
+       } else {
+               *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
        }
-       ZVAL_LONG(EG(argument_stack)->top, count);
-       return EG(argument_stack)->top++;
 }
 /* }}} */
 
-
 #define ZEND_VM_NEXT_OPCODE() \
        CHECK_SYMBOL_TABLES() \
        ZEND_VM_INC_OPCODE(); \
index b80d2adff844ab3935e95b8403876e6ac3c26c4a..40f42ae2dda5ef70f702473ec9ac69a15135aec6 100644 (file)
@@ -35,7 +35,8 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
 void init_executor(TSRMLS_D);
 void shutdown_executor(TSRMLS_D);
 void shutdown_destructors(TSRMLS_D);
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC);
 ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
 ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
@@ -48,7 +49,7 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
 ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
 
 ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
 
 static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
 {
@@ -149,7 +150,7 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s
 ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
 
 /* dedicated Zend executor functions - do not use! */
-#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
+#define ZEND_VM_STACK_PAGE_SIZE (16 * 1024) /* should be a power of 2 */
 
 struct _zend_vm_stack {
        zval *top;
@@ -157,22 +158,26 @@ struct _zend_vm_stack {
        zend_vm_stack prev;
 };
 
+#define ZEND_VM_STACK_HEADER_SLOT \
+       ((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
+
 #define ZEND_VM_STACK_ELEMETS(stack) \
-       ((zval*)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
-
-#define ZEND_VM_STACK_GROW_IF_NEEDED(count)                                                    \
-       do {                                                                                                                    \
-               if (UNEXPECTED((count) >                                                                        \
-                   EG(argument_stack)->end - EG(argument_stack)->top)) {       \
-                       zend_vm_stack_extend((count) TSRMLS_CC);                                \
-               }                                                                                                                       \
+       (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT)
+
+#define ZEND_VM_STACK_GROW_IF_NEEDED(count)                                                            \
+       do {                                                                                                                            \
+               if (UNEXPECTED(((count) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) > \
+                       ((char*)EG(argument_stack)->end) -                                                      \
+                   ((char*)EG(argument_stack)->top))) {                                                \
+                       zend_vm_stack_extend((count) TSRMLS_CC);                                        \
+               }                                                                                                                               \
        } while (0)
 
 static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
-       zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(zval) * count);
+       zend_vm_stack page = (zend_vm_stack)emalloc(count * ZEND_MM_ALIGNED_SIZE(sizeof(zval)));
 
        page->top = ZEND_VM_STACK_ELEMETS(page);
-       page->end = page->top + count;
+       page->end = (zval*)page + count;
        page->prev = NULL;
        return page;
 }
@@ -180,6 +185,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
 static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
 {
        EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
+       EG(argument_stack)->top++;
 }
 
 static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
@@ -195,95 +201,90 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
 
 static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
 {
-       zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
+       int size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
+       zend_vm_stack p = zend_vm_stack_new_page(
+               (size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ? 
+               (size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) & 
+                       ~((ZEND_VM_STACK_PAGE_SIZE * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) : 
+               ZEND_VM_STACK_PAGE_SIZE);
        p->prev = EG(argument_stack);
        EG(argument_stack) = p;
 }
 
-static zend_always_inline zval *zend_vm_stack_top(TSRMLS_D)
-{
-       return EG(argument_stack)->top;
-}
-
-static zend_always_inline zval *zend_vm_stack_top_inc(TSRMLS_D)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
 {
-       return EG(argument_stack)->top++;
+       int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
+       zend_execute_data *call;
+       
+       if (ZEND_USER_CODE(func->type)) {
+               used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
+       }
+       ZEND_VM_STACK_GROW_IF_NEEDED(used_stack);
+       call = (zend_execute_data*)EG(argument_stack)->top;
+       EG(argument_stack)->top += used_stack;
+       call->func = func;
+       call->num_args = 0;
+       call->flags = flags;
+       call->called_scope = called_scope;
+       call->object = object;
+       call->prev_nested_call = prev;
+       return call;
 }
 
-static zend_always_inline void zend_vm_stack_push(zval *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
 {
-       ZVAL_COPY_VALUE(EG(argument_stack)->top, ptr);
-       EG(argument_stack)->top++;
-}
+       zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
 
-static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
-{
-       return --EG(argument_stack)->top;
+       if (UNEXPECTED(call->num_args > first_extra_arg)) {
+               zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
+               zval *p = end + (call->num_args - first_extra_arg);
+               do {
+                       p--;
+                       i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+               } while (p != end);
+       }
 }
 
-static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
 {
-       zval *ret;
-       int count = (size + (sizeof(zval) - 1)) / sizeof(zval);
+       zend_uint num_args = call->num_args;    
 
-       ZEND_VM_STACK_GROW_IF_NEEDED(count);
-       ret = EG(argument_stack)->top;
-       EG(argument_stack)->top += count;
-       return ret;
-}
+       if (num_args > 0) {
+               zval *p = ZEND_CALL_ARG(call, num_args + 1);
+               zval *end = p - num_args;;
 
-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);
+               do {
+                       p--;
+                       i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+               } while (p != end);
+       }
 }
 
-static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
 {
-       if (UNEXPECTED((void*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == ptr)) {
+       if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (zval*)call)) {
                zend_vm_stack p = EG(argument_stack);
 
                EG(argument_stack) = p->prev;
                efree(p);
        } else {
-               EG(argument_stack)->top = (zval*)ptr;
-       }
-}
-
-static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
-{
-       zval *p = EG(argument_stack)->top - 1;
-
-       if (EXPECTED(Z_LVAL_P(p) > 0)) {
-               zval *end = p - Z_LVAL_P(p);
-
-               do {
-                       p--;
-                       i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
-               } while (p != end);
-       }
-       if (nested) {
-               EG(argument_stack)->top = p;
-       } else {
-               zend_vm_stack_free(p TSRMLS_CC);
+               EG(argument_stack)->top = (zval*)call;
        }
 }
 
 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..2ba582942ab7e58f7087db8e0bde00649983edf4 100644 (file)
@@ -156,7 +156,6 @@ void init_executor(TSRMLS_D) /* {{{ */
        EG(error_handling) = EH_NORMAL;
 
        zend_vm_stack_init(TSRMLS_C);
-       ZVAL_LONG(zend_vm_stack_top_inc(TSRMLS_C), 0);
 
        zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0);
        GC_REFCOUNT(&EG(symbol_table)) = 1;
@@ -393,17 +392,25 @@ 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 = EG(current_execute_data)->func;
+       }
+       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 = EG(current_execute_data)->func;
+       }
+       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);
@@ -681,7 +696,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                EX(object) = Z_OBJ(EG(This));
                EX(scope) = EG(scope);
                EX(called_scope) = EG(called_scope);
-               EX(op_array) = NULL;
+               EX(func) = NULL;
                EX(opline) = NULL;
        } else {
                /* This only happens when we're called outside any execute()'s
@@ -719,7 +734,8 @@ 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;
+       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 +745,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 +780,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)) {
-                                       if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
+                                       !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
+                                       if (i) {
                                                /* 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);
+                                               EX(call)->num_args = i;
+                                               zend_vm_stack_free_args(EX(call) TSRMLS_CC);
                                        }
+                                       zend_vm_stack_free_call_frame(EX(call) 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;
                                }
 
@@ -794,27 +808,26 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        } else if (Z_REFCOUNTED(fci->params[i])) {
                                Z_ADDREF(fci->params[i]);
                        }
-                       param = &fci->params[i];
+                       param = ZEND_CALL_ARG(EX(call), i+1);
+                       ZVAL_COPY_VALUE(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;
+                       param = ZEND_CALL_ARG(EX(call), i+1);
                        ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
                } else {
-                       param = &tmp;
+                       param = ZEND_CALL_ARG(EX(call), i+1);
                        ZVAL_COPY(param, &fci->params[i]);
                }
-               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);
+       EX(call)->num_args = 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)) {
-               Z_OBJ(EG(This)) = NULL;
+           (func->common.fn_flags & ZEND_ACC_STATIC)) {
+               Z_OBJ(EG(This)) = EX(call)->object = NULL;
        } else {
                Z_OBJ(EG(This)) = fci->object;
                Z_ADDREF(EG(This));
@@ -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,18 +861,21 @@ 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);
                }
+               zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+               zend_vm_stack_free_call_frame(EX(call) TSRMLS_CC);
+
                /*  We shouldn't fix bad extensions here,
                        because it can break proper ones (Bug #34045)
                if (!EX(function_state).function->common.return_reference)
@@ -880,22 +896,21 @@ 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);
 
        if (Z_OBJ(EG(This))) {
                zval_ptr_dtor(&EG(This));
@@ -1080,6 +1095,10 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
 
                zend_try {
                        ZVAL_UNDEF(&local_retval);
+                       if (EG(current_execute_data)) {
+                               EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+                                       (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+                       }
                        zend_execute(new_op_array, &local_retval TSRMLS_CC);
                } zend_catch {
                        destroy_op_array(new_op_array TSRMLS_CC);
@@ -1583,33 +1602,34 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
 
                /* Search for last called user function */
                ex = EG(current_execute_data);
-               while (ex && !ex->op_array) {
+               while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
                        ex = ex->prev_execute_data;
                }
-               if (ex && ex->symbol_table) {
+               if (!ex) {
+                       return;
+               }
+               if (ex->symbol_table) {
                        EG(active_symbol_table) = ex->symbol_table;
                        return;
                }
 
-               if (ex && ex->op_array) {
-                       if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
-                               /*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
-                               EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
-                       } else {
-                               EG(active_symbol_table) = emalloc(sizeof(zend_array));
-                               GC_REFCOUNT(EG(active_symbol_table)) = 0;
-                               GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
-                               zend_hash_init(&EG(active_symbol_table)->ht, ex->op_array->last_var, NULL, ZVAL_PTR_DTOR, 0);
-                               /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
-                       }
-                       ex->symbol_table = EG(active_symbol_table);
-                       for (i = 0; i < ex->op_array->last_var; i++) {
-                               zval zv;
-                                       
-                               ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
-                               zend_hash_add_new(&EG(active_symbol_table)->ht,
-                                       ex->op_array->vars[i], &zv);
-                       }
+               if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
+                       /*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
+                       EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
+               } else {
+                       EG(active_symbol_table) = emalloc(sizeof(zend_array));
+                       GC_REFCOUNT(EG(active_symbol_table)) = 0;
+                       GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
+                       zend_hash_init(&EG(active_symbol_table)->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
+                       /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
+               }
+               ex->symbol_table = EG(active_symbol_table);
+               for (i = 0; i < ex->func->op_array.last_var; i++) {
+                       zval zv;
+
+                       ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
+                       zend_hash_add_new(&EG(active_symbol_table)->ht,
+                               ex->func->op_array.vars[i], &zv);
                }
        }
 }
@@ -1618,7 +1638,7 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
 {
        int i;
-       zend_op_array *op_array = execute_data->op_array;
+       zend_op_array *op_array = &execute_data->func->op_array;
        HashTable *ht = &execute_data->symbol_table->ht;
        
        /* copy real values from symbol table into CV slots and create
@@ -1649,7 +1669,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
 {
        int i;
-       zend_op_array *op_array = execute_data->op_array;
+       zend_op_array *op_array = &execute_data->func->op_array;
        HashTable *ht = &execute_data->symbol_table->ht;
        
        /* copy real values from CV slots into symbol table */
@@ -1669,7 +1689,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS
        if (!EG(active_symbol_table)) {
                int i;
                zend_execute_data *execute_data = EG(current_execute_data);
-               zend_op_array *op_array = execute_data->op_array;
+               zend_op_array *op_array = &execute_data->func->op_array;
                zend_ulong h = STR_HASH_VAL(name);
 
                if (op_array) {
@@ -1702,7 +1722,7 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int
        if (!EG(active_symbol_table)) {
                int i;
                zend_execute_data *execute_data = EG(current_execute_data);
-               zend_op_array *op_array = execute_data->op_array;
+               zend_op_array *op_array = &execute_data->func->op_array;
                zend_ulong h = zend_hash_func(name, len);
 
                if (op_array) {
index c80e909565de4f2ffa7b258426e63c9a99b6a0e5..f4847b0839df2b1c55fb1ae17d9be47aff2b86ca 100644 (file)
@@ -32,7 +32,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC
 static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
 {
        zend_execute_data *execute_data = generator->execute_data;
-       zend_op_array *op_array = execute_data->op_array;
+       zend_op_array *op_array = &execute_data->func->op_array;
 
        if (generator->send_target) {
                if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
@@ -75,23 +75,13 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
                }
        }
 
-       /* Clear any backed up stack arguments */
-       {
-               zval *ptr = generator->stack->top - 1;
-               zval *end = zend_vm_stack_frame_base(execute_data);
-
-               for (; ptr >= end; --ptr) {
-                       zval_ptr_dtor((zval*) ptr);
-               }
-       }
-
        /* 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_nested_call;
        }
 }
 /* }}} */
@@ -110,7 +100,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
 
        if (generator->execute_data) {
                zend_execute_data *execute_data = generator->execute_data;
-               zend_op_array *op_array = execute_data->op_array;
+               zend_op_array *op_array = &execute_data->func->op_array;
 
                if (!execute_data->symbol_table) {
                        zend_free_compiled_variables(execute_data TSRMLS_CC);
@@ -128,23 +118,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
                        return;
                }
 
-               /* We have added an additional stack frame in prev_execute_data, so we
-                * have to free it. It also contains the arguments passed to the
-                * 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;
-                               int i;
-
-                               for (i = 0; i < arguments_count; ++i) {
-                                       zval_ptr_dtor(arguments_start + i);
-                               }
-                       }
-               }
+               zend_vm_stack_free_extra_args(generator->execute_data TSRMLS_CC);
 
                /* Some cleanups are only necessary if the generator was closued
                 * before it could finish execution (reach a return statement). */
@@ -158,6 +132,10 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
                        efree(op_array);
                }
 
+               if (generator->execute_data->prev_execute_data) {
+                       generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call;
+               }
+
                efree(generator->stack);
                generator->execute_data = NULL;
        }
@@ -171,18 +149,18 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
        zend_uint op_num, finally_op_num;
        int i;
 
-       if (!ex || !ex->op_array->has_finally_block) {
+       if (!ex || !ex->func->op_array.has_finally_block) {
                return;
        }
 
        /* -1 required because we want the last run opcode, not the
         * next to-be-run one. */
-       op_num = ex->opline - ex->op_array->opcodes - 1;
+       op_num = ex->opline - ex->func->op_array.opcodes - 1;
 
        /* Find next finally block */
        finally_op_num = 0;
-       for (i = 0; i < ex->op_array->last_try_catch; i++) {
-               zend_try_catch_element *try_catch = &ex->op_array->try_catch_array[i];
+       for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
+               zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
 
                if (op_num < try_catch->try_op) {
                        break;
@@ -196,7 +174,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
        /* If a finally block was found we jump directly to it and
         * resume the generator. */
        if (finally_op_num) {
-               ex->opline = &ex->op_array->opcodes[finally_op_num];
+               ex->opline = &ex->func->op_array.opcodes[finally_op_num];
                ex->fast_ret = NULL;
                generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
                zend_generator_resume(generator TSRMLS_CC);
@@ -288,7 +266,7 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
        opline_ptr = EG(opline_ptr);
        current_symbol_table = EG(active_symbol_table);
        EG(active_symbol_table) = NULL;
-       execute_data = zend_create_execute_data_from_op_array(op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+       execute_data = zend_create_generator_execute_data(op_array, return_value TSRMLS_CC);
        EG(active_symbol_table) = current_symbol_table;
        EG(current_execute_data) = current_execute_data;
        EG(opline_ptr) = opline_ptr;
@@ -300,8 +278,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
        }
 
        /* Save execution context in generator object. */
-       execute_data->prev_execute_data->object = Z_OBJ_P(return_value);
        generator = (zend_generator *) Z_OBJ_P(return_value);
+       execute_data->prev_execute_data = NULL;
        generator->execute_data = execute_data;
        generator->stack = EG(argument_stack);
        EG(argument_stack) = current_stack;
@@ -343,13 +321,14 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
                zend_class_entry *original_scope = EG(scope);
                zend_class_entry *original_called_scope = EG(called_scope);
                zend_vm_stack original_stack = EG(argument_stack);
+               zend_execute_data *prev_execute_data;
 
                original_This = Z_OBJ(EG(This));
 
                /* Set executor globals */
                EG(current_execute_data) = generator->execute_data;
                EG(opline_ptr) = &generator->execute_data->opline;
-               EG(active_op_array) = generator->execute_data->op_array;
+               EG(active_op_array) = &generator->execute_data->func->op_array;
                EG(active_symbol_table) = generator->execute_data->symbol_table;
                Z_OBJ(EG(This)) = generator->execute_data->object;
                EG(scope) = generator->execute_data->scope;
@@ -358,17 +337,32 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
 
                /* We want the backtrace to look as if the generator function was
                 * called from whatever method we are current running (e.g. next()).
-                * The first prev_execute_data contains an additional stack frame,
-                * which makes the generator function show up in the backtrace and
-                * makes the arguments available to func_get_args(). So we have to
-                * set the prev_execute_data of that prev_execute_data :) */
-               generator->execute_data->prev_execute_data->prev_execute_data = original_execute_data;
+                * So we have to link generator call frame with caller call frames */
+
+               prev_execute_data = original_execute_data;
+        if (prev_execute_data &&
+            prev_execute_data->call &&
+            (prev_execute_data->call->flags & ZEND_CALL_DONE)) {
+                       prev_execute_data->call->prev_execute_data = prev_execute_data;
+                       prev_execute_data = prev_execute_data->call;
+               }
+               generator->execute_data->prev_execute_data = prev_execute_data;
+               if (prev_execute_data) {
+                       generator->execute_data->prev_nested_call = prev_execute_data->call;
+                       prev_execute_data->call = generator->execute_data;
+               }
 
                /* Resume execution */
                generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
                zend_execute_ex(generator->execute_data TSRMLS_CC);
                generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;
 
+               /* Unlink generator call_frame from the caller */
+               if (generator->execute_data && generator->execute_data->prev_execute_data) {
+                       generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call;
+                       generator->execute_data->prev_execute_data = NULL;
+               }
+
                /* Restore executor globals */
                EG(current_execute_data) = original_execute_data;
                EG(opline_ptr) = original_opline_ptr;
@@ -670,7 +664,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
                return NULL;
        }
 
-       if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
+       if (by_ref && !(generator->execute_data->func->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
                zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC);
                return NULL;
        }
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..cad1dd2e9c09e425bb019caa7c56d97d3b7fc91a 100644 (file)
@@ -70,9 +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;
        op_array->filename = zend_get_compiled_filename(TSRMLS_C);
        op_array->doc_comment = NULL;
@@ -631,7 +628,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
 {
        zend_op *opline, *end;
 
-       if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
+       if (!ZEND_USER_CODE(op_array->type)) {
                return 0;
        }
        if (op_array->has_finally_block) {
index 38377d3cceb6852c7f27cae4d99b8d6a5aef49ab..f0da4eeded0f0c28689facb80ce96aff0cc464cd 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_execute_data *prev_nested_call;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -1780,22 +1781,22 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                if (UNEXPECTED(EX(symbol_table) != NULL)) {
                        zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
                }
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
-                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
+                       zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
                }
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
 
                execute_data = EG(current_execute_data);
+               EX(call) = prev_nested_call;
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->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(opline)->op1.num & ZEND_CALL_CTOR)) {
+                               if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -1812,10 +1813,6 @@ 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);
-
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
                        zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -1830,16 +1827,16 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                ZEND_VM_LEAVE();
        } else if (frame_kind == VM_FRAME_NESTED_CODE) {
                zend_detach_symbol_table(execute_data);
-               destroy_op_array(EX(op_array) TSRMLS_CC);
-               efree(EX(op_array));
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               destroy_op_array(&EX(func)->op_array TSRMLS_CC);
+               efree(EX(func));
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
 
                execute_data = EG(current_execute_data);
+               EX(call) = prev_nested_call;
                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);
+               EG(active_op_array) = &EX(func)->op_array;
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -1851,6 +1848,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
        } else {
                if (frame_kind == VM_FRAME_TOP_FUNCTION) {
                        i_free_compiled_variables(execute_data TSRMLS_CC);
+                       zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
                } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
                        zend_array *symbol_table = EX(symbol_table);
                        zend_execute_data *old_execute_data;
@@ -1858,7 +1856,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                        zend_detach_symbol_table(execute_data);
                        old_execute_data = EX(prev_execute_data);
                        while (old_execute_data) {
-                               if (old_execute_data->op_array) {
+                               if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
                                        if (old_execute_data->symbol_table == symbol_table) {
                                                zend_attach_symbol_table(old_execute_data);
                                        }
@@ -1867,224 +1865,20 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                                old_execute_data = old_execute_data->prev_execute_data;
                        }
                }
-               if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
-                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
+                       zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
+               }
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
+               
+               if (EG(current_execute_data)) {
+                       EG(current_execute_data)->call = prev_nested_call;
                }
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
                EG(opline_ptr) = NULL;
                ZEND_VM_RETURN();
        }               
 }
 
-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 +2201,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,32 +2219,8 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        FREE_OP2();
                        HANDLE_EXCEPTION();
@@ -2456,15 +2228,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (OP2_TYPE != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        FREE_OP2();
        FREE_OP1_IF_VAR();
@@ -2478,7 +2273,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();
 
@@ -2487,7 +2283,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -2496,24 +2292,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 +2318,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 +2344,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (OP1_TYPE != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -2590,32 +2383,32 @@ 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
-       zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
+       zval *function_name, *func;
 
        if (OP2_TYPE == IS_CONST) {
-               function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+               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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
        } else {
                zend_string *lcname;
                zend_free_op free_op2;
+               zend_class_entry *called_scope;
+               zend_object *object;
+               zval *function_name_ptr;
 
                SAVE_OPLINE();
                function_name_ptr = function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -2634,37 +2427,23 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
+                       fbc = Z_FUNC_P(func);
+                       called_scope = NULL;
+                       object = NULL;
                } 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else if (OP2_TYPE != IS_CONST &&
                                EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                                zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2687,51 +2466,49 @@ 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;
-
                        FREE_OP2();
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else {
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+                       ZEND_VM_CONTINUE(); /* Never reached */
                }
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -2741,68 +2518,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, opline->extended_value, 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, opline->extended_value, 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_execute_data *call = EX(call);
+       zend_function *fbc = call->func;
+
+       SAVE_OPLINE();
+       call->flags = ZEND_CALL_DONE;
+       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) &&
+               !call->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);
+               }
+       }
+
+       LOAD_OPLINE();
+
+       if (UNEXPECTED(fbc->type == ZEND_INTERNAL_FUNCTION)) {
+               int should_change_scope = 0;
+               zval *ret;
+
+               if (fbc->common.scope) {
+                       should_change_scope = 1;
+                       Z_OBJ(EG(This)) = call->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) = (call->object) ? NULL : fbc->common.scope;
+#else 
+                       EG(scope) = fbc->common.scope;
+#endif
+                       EG(called_scope) = call->called_scope;
+               }
+
+               if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+                       zend_uint i;
+                       zval *p = ZEND_CALL_ARG(call, 1);
+
+                       for (i = 0; i < call->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(call->num_args, ret TSRMLS_CC);
+               } else {
+                       zend_execute_internal(execute_data, NULL TSRMLS_CC);
+               }
+               
+               zend_vm_stack_free_args(call TSRMLS_CC);
+
+               EX(call) = call->prev_nested_call;
+               zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(ret);
+               }
 
-       ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);
+               if (UNEXPECTED(should_change_scope)) {
+                       ZEND_VM_C_GOTO(fcall_end_change_scope);
+               } else {
+                       ZEND_VM_C_GOTO(fcall_end);
+               }
+       } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
+               zval *return_value = NULL;
+
+               Z_OBJ(EG(This)) = call->object;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = 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((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       if (RETURN_VALUE_USED(opline)) {
+                               zend_generator_create_zval(&fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC);
+                       }
+       
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+               } else {
+                       call->prev_execute_data = EG(current_execute_data);
+                       i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+
+                       if (EXPECTED(zend_execute_ex == execute_ex)) {
+                               ZEND_VM_ENTER();
+                       } else {
+                               execute_ex(call TSRMLS_CC);
+                       }
+               }
+
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = &EX(func)->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)) = call->object;
+//???          EG(scope) = NULL;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = 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(call->object != NULL)) {
+                       call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+               } else {
+                       zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
+               }
+
+               zend_vm_stack_free_args(call TSRMLS_CC);
+
+               EX(call) = call->prev_nested_call;
+               zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
+               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) && (opline->op1.num & ZEND_CALL_CTOR)) {
+                       if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
+                               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))) {
+                       _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):
+       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)
@@ -2945,7 +2917,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
        /* Check whether an exception has been thrown, if not, jump over code */
        zend_exception_restore(TSRMLS_C);
        if (EG(exception) == NULL) {
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
                ZEND_VM_CONTINUE(); /* CHECK_ME */
        }
        if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
@@ -2969,7 +2941,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
                                zend_throw_exception_internal(NULL TSRMLS_CC);
                                HANDLE_EXCEPTION();
                        }
-                       ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+                       ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
                        ZEND_VM_CONTINUE(); /* CHECK_ME */
                }
        }
@@ -2991,22 +2963,23 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
 ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
 {
        USE_OPLINE
-       zval *value, *top;
+       zval *value, *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);
                }
        }
 
        value = GET_OP1_ZVAL_PTR(BP_VAR_R);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
-       ZVAL_COPY_VALUE(top, value);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
+       ZVAL_COPY_VALUE(arg, value);
        if (OP1_TYPE == IS_CONST) {
-               if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
-                       zval_copy_ctor_func(top);
+               if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+                       zval_copy_ctor_func(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -3015,18 +2988,19 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
 ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
        zend_free_op free_op1;
 
        varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
                FREE_OP1();
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (OP1_TYPE == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -3036,7 +3010,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
 {
        USE_OPLINE
        zend_free_op free_op1;
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -3044,7 +3018,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);
                }
        }
@@ -3061,15 +3035,18 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
                if (OP1_TYPE == IS_CV) {
                        Z_ADDREF_P(varptr);
                }
-               zend_vm_stack_push(varptr TSRMLS_CC);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY_VALUE(arg, varptr);
        } 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);
-               ZVAL_COPY(top, varptr);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY(arg, varptr);
                FREE_OP1_IF_VAR();
        }
        CHECK_EXCEPTION();
@@ -3080,7 +3057,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
 {
        USE_OPLINE
        zend_free_op free_op1;
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
@@ -3089,23 +3066,24 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
                zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
        }
 
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
-               ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+               ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
                ZEND_VM_NEXT_OPCODE();
        }
 
        if (Z_ISREF_P(varptr)) {
                Z_ADDREF_P(varptr);
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
        } else if (OP1_TYPE == IS_VAR &&
                UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
-               ZVAL_COPY_VALUE(top, varptr);
-               ZVAL_MAKE_REF(top);
+               ZVAL_COPY_VALUE(arg, varptr);
+               ZVAL_MAKE_REF(arg);
        } else {
                ZVAL_MAKE_REF(varptr);
                Z_ADDREF_P(varptr);
-               ZVAL_REF(top, Z_REF_P(varptr));
+               ZVAL_REF(arg, Z_REF_P(varptr));
        }
 
        FREE_OP1_VAR_PTR();
@@ -3115,24 +3093,25 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
 ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
        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);
                }
        }
 
        varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
                FREE_OP1();
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (OP1_TYPE == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -3147,7 +3126,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 = EX(call)->num_args + 1;
 
 ZEND_VM_C_LABEL(send_again):
        switch (Z_TYPE_P(args)) {
@@ -3156,7 +3135,7 @@ ZEND_VM_C_LABEL(send_again):
                        zval *arg, *top;
                        zend_string *name;
 
-                       ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht));
+                       zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_DC);
 
                        if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
                                int i;
@@ -3164,7 +3143,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;
                                        }
@@ -3183,8 +3162,8 @@ ZEND_VM_C_LABEL(send_again):
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               top = zend_vm_stack_top_inc(TSRMLS_C);
-                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               top = ZEND_CALL_ARG(EX(call), 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);
@@ -3193,12 +3172,13 @@ ZEND_VM_C_LABEL(send_again):
                                                ZVAL_DUP(top, arg);
                                        }
                                } else if (Z_ISREF_P(arg)) {
+//TODO: change into ZVAL_COPY()???
                                        ZVAL_DUP(top, Z_REFVAL_P(arg));
                                } else {
                                        ZVAL_COPY(top, arg);
                                }
 
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
                                arg_num++;
                        } ZEND_HASH_FOREACH_END();
 
@@ -3232,7 +3212,7 @@ ZEND_VM_C_LABEL(send_again):
                        }
 
                        for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
-                               zval *arg;
+                               zval *arg, *top;
 
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        ZEND_VM_C_GOTO(unpack_iter_dtor);
@@ -3260,13 +3240,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
                                        );
                                }
                                
@@ -3276,9 +3256,10 @@ ZEND_VM_C_LABEL(send_again):
                                        if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                                }
 
-                               ZEND_VM_STACK_GROW_IF_NEEDED(1);
-                               zend_vm_stack_push(arg TSRMLS_CC);
-                               EX(call)->num_additional_args++;
+                               zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1 TSRMLS_DC);
+                               top = ZEND_CALL_ARG(EX(call), arg_num);
+                               ZVAL_COPY_VALUE(top, arg);
+                               EX(call)->num_args++;
 
                                iter->funcs->move_forward(iter TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3307,25 +3288,18 @@ 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);
 
        SAVE_OPLINE();
-       if (UNEXPECTED(arg_num > arg_count)) {
+       if (UNEXPECTED(arg_num > EX(num_args))) {
                zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
-       } else {
-               zval *var_ptr;
-               zval *param = arguments - arg_count + arg_num - 1;
+               CHECK_EXCEPTION();
+       } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+               zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
 
-               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);
-               }
-               var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-               if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
-               ZVAL_COPY(var_ptr, param);
+               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+               CHECK_EXCEPTION();
        }
 
-       CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -3333,30 +3307,24 @@ 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);
-       zval *var_ptr;
+       zval *param;
 
        SAVE_OPLINE();
-       var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-       if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
-       if (arg_num > arg_count) {
-               ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
-               if (Z_OPT_CONSTANT_P(var_ptr)) {
-                       zval_update_constant(var_ptr, 0 TSRMLS_CC);
+       param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+       if (arg_num > EX(num_args)) {
+               ZVAL_COPY_VALUE(param, opline->op2.zv);
+               if (Z_OPT_CONSTANT_P(param)) {
+                       zval_update_constant(param, 0 TSRMLS_CC);
                } else {
                        /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
-                       if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
-                               zval_copy_ctor_func(var_ptr);
+                       if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
+                               zval_copy_ctor_func(param);
                        }
                }
-       } else {
-               zval *param = arguments - arg_count + arg_num - 1;
-               ZVAL_COPY(var_ptr, param);
        }
 
-       if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
-               zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+       if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
        }
 
        CHECK_EXCEPTION();
@@ -3367,21 +3335,21 @@ 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(num_args);
        zval *params;
 
        SAVE_OPLINE();
 
        params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-       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;
+
                array_init_size(params, arg_count - arg_num + 1);
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
-                       do {
-                               zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+               param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+                       do {                    
+                               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
                                zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
                                if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
                                param++;
@@ -3423,8 +3391,8 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
-                          EX(op_array), execute_data TSRMLS_CC);
-       ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
+       ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
 }
 
 ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
@@ -3434,8 +3402,8 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
-                          EX(op_array), execute_data TSRMLS_CC);
-       ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
+       ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
 }
 
 ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
@@ -3446,9 +3414,9 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
-                          EX(op_array), execute_data TSRMLS_CC);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
 
-       brk_opline = EX(op_array)->opcodes + el->brk;
+       brk_opline = EX(func)->op_array.opcodes + el->brk;
 
        if (brk_opline->opcode == ZEND_SWITCH_FREE) {
                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -3515,21 +3483,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, opline->extended_value,
+                       RETURN_VALUE_USED(opline) ?
+                               ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
+                       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();
        }
@@ -4014,23 +3980,23 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                        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, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
                }
 
+               EX(call)->prev_execute_data = EG(current_execute_data);
+           i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
-                       zend_execute(new_op_array, return_value TSRMLS_CC);
+                       execute_ex(EG(current_execute_data) TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->op_array;
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -4861,7 +4827,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
 ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
 {
        SAVE_OPLINE();
-       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(op_array)->function_name->val);
+       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val);
        ZEND_VM_NEXT_OPCODE(); /* Never reached */
 }
 
@@ -4987,7 +4953,7 @@ ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4997,7 +4963,7 @@ ZEND_VM_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5007,7 +4973,7 @@ ZEND_VM_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5018,7 +4984,7 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY)
        USE_OPLINE
 
        SAVE_OPLINE();
-       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0 TSRMLS_CC);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -5028,7 +4994,7 @@ ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
        USE_OPLINE
 
        SAVE_OPLINE();
-       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -5042,7 +5008,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
        if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
            ((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
             Z_CE_P(zce) != Z_CE_P(orig_zce))) {
-               do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+               do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5053,7 +5019,7 @@ ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
        USE_OPLINE
 
        SAVE_OPLINE();
-       do_bind_function(EX(op_array), opline, EG(function_table), 0);
+       do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -5173,45 +5139,37 @@ ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
 
 ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
 {
-       zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
+       zend_uint op_num = EG(opline_before_exception) - EX(func)->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) {
+       for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
+               if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
                        /* further blocks will not be relevant... */
                        break;
                }
-               if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
-                       catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
+               if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) {
+                       catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op;
                }
-               if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
-                       finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
+               if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
+                       finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
                }
-               if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op &&
-                               op_num < EG(active_op_array)->try_catch_array[i].finally_end) {
-                       finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end;
+               if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
+                               op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
+                       finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
                }
        }
 
-       if (EX(call) >= EX(call_slots)) {
-               call_slot *call = EX(call);
+       if (EX(call)) {
+               zend_execute_data *call = EX(call);
                do {
+                       /* If the exception was thrown during a function call there might be
+                        * arguments pushed to the stack that have to be dtor'ed. */
+                       zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
                        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_UNUSED)) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {
@@ -5220,21 +5178,22 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       call--;
-               } while (call >= EX(call_slots));
-               EX(call) = NULL;
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+                       call = EX(call);
+               } while (call);
        }
 
-       for (i=0; i<EX(op_array)->last_brk_cont; i++) {
-               if (EX(op_array)->brk_cont_array[i].start < 0) {
+       for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+               if (EX(func)->op_array.brk_cont_array[i].start < 0) {
                        continue;
-               } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+               } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
-               } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+               } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
                        if (!catch_op_num ||
-                           catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
-                               zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+                           catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+                               zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
 
                                if (brk_opline->opcode == ZEND_SWITCH_FREE) {
                                        if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -5270,7 +5229,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                EX(delayed_exception) = EG(exception);
                EG(exception) = NULL;
                EX(fast_ret) = NULL;
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
                ZEND_VM_CONTINUE();
        } else if (catch_op_num) {
                if (finally_op_end && catch_op_num > finally_op_end) {
@@ -5280,14 +5239,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                                EX(delayed_exception) = NULL;
                        }
                }
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
                ZEND_VM_CONTINUE();
        } else {
                if (EX(delayed_exception)) {
                        zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
                        EX(delayed_exception) = NULL;
                }
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
                } else {
                        ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5318,7 +5277,7 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
                case ZEND_USER_OPCODE_CONTINUE:
                        ZEND_VM_CONTINUE();
                case ZEND_USER_OPCODE_RETURN:
-                       if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                                ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
                        } else {
                                ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5382,7 +5341,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 {
@@ -5432,7 +5391,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
        if (OP1_TYPE != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
@@ -5560,7 +5519,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
        if (opline->extended_value &&
            UNEXPECTED(EG(prev_exception) != NULL)) {
            /* in case of unhandled exception jump to catch block instead of finally */
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                ZEND_VM_CONTINUE();
        }
        EX(fast_ret) = opline + 1;
@@ -5579,15 +5538,15 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
                USE_OPLINE
 
                if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
-                       ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+                       ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                        ZEND_VM_CONTINUE();
                } else {
                        EG(exception) = EX(delayed_exception);
                        EX(delayed_exception) = NULL;
                        if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
-                               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+                               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                                ZEND_VM_CONTINUE();
-                       } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                                ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
                        } else {
                                ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5646,4 +5605,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..3f373a1a9807d98d92943787a7d52dbccdb4616b 100644 (file)
@@ -375,15 +375,27 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
 
 ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC)
 {
+       zend_execute_data *execute_data;
+
        if (EG(exception) != NULL) {
                return;
-       } 
-       zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
+       }
+
+       if (EG(current_execute_data) && EG(current_execute_data)->call) {
+               execute_data = EG(current_execute_data)->call;
+       } else {
+               execute_data = zend_vm_stack_push_call_frame(
+                       (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC);
+       }
+       EX(prev_execute_data) = EG(current_execute_data);
+       i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+       zend_execute_ex(execute_data TSRMLS_CC);
 }
 
 static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
+       zend_execute_data *prev_nested_call;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -392,22 +404,22 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                if (UNEXPECTED(EX(symbol_table) != NULL)) {
                        zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
                }
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
-                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
+                       zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
                }
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
 
                execute_data = EG(current_execute_data);
+               EX(call) = prev_nested_call;
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->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(opline)->op1.num & ZEND_CALL_CTOR)) {
+                               if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -424,10 +436,6 @@ 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);
-
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
                        zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -442,16 +450,16 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                ZEND_VM_LEAVE();
        } else if (frame_kind == VM_FRAME_NESTED_CODE) {
                zend_detach_symbol_table(execute_data);
-               destroy_op_array(EX(op_array) TSRMLS_CC);
-               efree(EX(op_array));
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               destroy_op_array(&EX(func)->op_array TSRMLS_CC);
+               efree(EX(func));
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
 
                execute_data = EG(current_execute_data);
+               EX(call) = prev_nested_call;
                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);
+               EG(active_op_array) = &EX(func)->op_array;
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -463,6 +471,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                if (frame_kind == VM_FRAME_TOP_FUNCTION) {
                        i_free_compiled_variables(execute_data TSRMLS_CC);
+                       zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
                } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
                        zend_array *symbol_table = EX(symbol_table);
                        zend_execute_data *old_execute_data;
@@ -470,7 +479,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                        zend_detach_symbol_table(execute_data);
                        old_execute_data = EX(prev_execute_data);
                        while (old_execute_data) {
-                               if (old_execute_data->op_array) {
+                               if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
                                        if (old_execute_data->symbol_table == symbol_table) {
                                                zend_attach_symbol_table(old_execute_data);
                                        }
@@ -479,24 +488,47 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                                old_execute_data = old_execute_data->prev_execute_data;
                        }
                }
-               if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
-                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
+                       zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
+               }
+               prev_nested_call = EX(prev_nested_call);
+               zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
+
+               if (EG(current_execute_data)) {
+                       EG(current_execute_data)->call = prev_nested_call;
                }
-               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
                EG(opline_ptr) = NULL;
                ZEND_VM_RETURN();
        }
 }
 
-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_object *object;
-       zend_uint num_args;
+
+       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();
-       object = EX(call)->object;
+       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_execute_data *call = EX(call);
+       zend_function *fbc = call->func;
+
+       SAVE_OPLINE();
+       call->flags = ZEND_CALL_DONE;
        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);
@@ -513,7 +545,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
        }
        if (fbc->common.scope &&
                !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
-               !object) {
+               !call->object) {
 
                if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
                        /* FIXME: output identifiers properly */
@@ -528,39 +560,32 @@ 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);
-       } 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) {
+       if (UNEXPECTED(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;
+                       Z_OBJ(EG(This)) = call->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;
+                       EG(scope) = (call->object) ? NULL : fbc->common.scope;
 #else
                        EG(scope) = fbc->common.scope;
 #endif
-                       EG(called_scope) = EX(call)->called_scope;
+                       EG(called_scope) = call->called_scope;
                }
 
                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(call, 1);
 
-                       for (i = 0; i < num_args; ++i, ++p) {
+                       for (i = 0; i < call->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)) {
@@ -580,11 +605,16 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
 
                if (!zend_execute_internal) {
                        /* saves one function call if zend_execute_internal is not used */
-                       fbc->internal_function.handler(num_args, ret TSRMLS_CC);
+                       fbc->internal_function.handler(call->num_args, ret TSRMLS_CC);
                } else {
                        zend_execute_internal(execute_data, NULL TSRMLS_CC);
                }
 
+               zend_vm_stack_free_args(call TSRMLS_CC);
+
+               EX(call) = call->prev_nested_call;
+               zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
                if (!RETURN_VALUE_USED(opline)) {
                        zval_ptr_dtor(ret);
                }
@@ -594,12 +624,12 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                } else {
                        goto fcall_end;
                }
-       } else if (fbc->type == ZEND_USER_FUNCTION) {
+       } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
                zval *return_value = NULL;
 
-               Z_OBJ(EG(This)) = object;
+               Z_OBJ(EG(This)) = call->object;
                EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
+               EG(called_scope) = call->called_scope;
                EG(active_symbol_table) = NULL;
                EG(active_op_array) = &fbc->op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -609,40 +639,50 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                        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 (UNEXPECTED((fbc->common.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);
+                               zend_generator_create_zval(&fbc->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);
+
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+               } else {
+                       call->prev_execute_data = EG(current_execute_data);
+                       i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+
+                       if (EXPECTED(zend_execute_ex == execute_ex)) {
                                ZEND_VM_ENTER();
+                       } else {
+                               execute_ex(call TSRMLS_CC);
                        }
-               } else {
-                       zend_execute(EG(active_op_array), return_value TSRMLS_CC);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->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;
+               Z_OBJ(EG(This)) = call->object;
 //???          EG(scope) = NULL;
                EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
+               EG(called_scope) = 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);
+               if (EXPECTED(call->object != NULL)) {
+                       call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC);
                } else {
                        zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
                }
 
+               zend_vm_stack_free_args(call TSRMLS_CC);
+
+               EX(call) = call->prev_nested_call;
+               zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
                if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
                        STR_RELEASE(fbc->common.function_name);
                }
@@ -659,8 +699,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) && (opline->op1.num & ZEND_CALL_CTOR)) {
+                       if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -668,8 +708,6 @@ fcall_end_change_scope:
                        }
                }
                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);
@@ -680,12 +718,6 @@ 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);
-
        if (UNEXPECTED(EG(exception) != NULL)) {
                zend_throw_exception_internal(NULL TSRMLS_CC);
                if (RETURN_VALUE_USED(opline)) {
@@ -697,31 +729,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 +750,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 = EX(call)->num_args + 1;
 
 send_again:
        switch (Z_TYPE_P(args)) {
@@ -752,7 +759,7 @@ send_again:
                        zval *arg, *top;
                        zend_string *name;
 
-                       ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht));
+                       zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_DC);
 
                        if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
                                int i;
@@ -760,7 +767,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;
                                        }
@@ -779,8 +786,8 @@ send_again:
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               top = zend_vm_stack_top_inc(TSRMLS_C);
-                               if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+                               top = ZEND_CALL_ARG(EX(call), 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);
@@ -789,12 +796,13 @@ send_again:
                                                ZVAL_DUP(top, arg);
                                        }
                                } else if (Z_ISREF_P(arg)) {
+//TODO: change into ZVAL_COPY()???
                                        ZVAL_DUP(top, Z_REFVAL_P(arg));
                                } else {
                                        ZVAL_COPY(top, arg);
                                }
 
-                               EX(call)->num_additional_args++;
+                               EX(call)->num_args++;
                                arg_num++;
                        } ZEND_HASH_FOREACH_END();
 
@@ -828,7 +836,7 @@ send_again:
                        }
 
                        for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
-                               zval *arg;
+                               zval *arg, *top;
 
                                if (UNEXPECTED(EG(exception) != NULL)) {
                                        goto unpack_iter_dtor;
@@ -856,13 +864,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
                                        );
                                }
 
@@ -872,9 +880,10 @@ send_again:
                                        if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                                }
 
-                               ZEND_VM_STACK_GROW_IF_NEEDED(1);
-                               zend_vm_stack_push(arg TSRMLS_CC);
-                               EX(call)->num_additional_args++;
+                               zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1 TSRMLS_DC);
+                               top = ZEND_CALL_ARG(EX(call), arg_num);
+                               ZVAL_COPY_VALUE(top, arg);
+                               EX(call)->num_args++;
 
                                iter->funcs->move_forward(iter TSRMLS_CC);
                                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -903,25 +912,18 @@ 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);
 
        SAVE_OPLINE();
-       if (UNEXPECTED(arg_num > arg_count)) {
+       if (UNEXPECTED(arg_num > EX(num_args))) {
                zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
-       } else {
-               zval *var_ptr;
-               zval *param = arguments - arg_count + arg_num - 1;
+               CHECK_EXCEPTION();
+       } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+               zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
 
-               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);
-               }
-               var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-               if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
-               ZVAL_COPY(var_ptr, param);
+               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+               CHECK_EXCEPTION();
        }
 
-       CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -929,21 +931,21 @@ 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(num_args);
        zval *params;
 
        SAVE_OPLINE();
 
        params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-       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;
+
                array_init_size(params, arg_count - arg_num + 1);
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+               param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
                        do {
-                               zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+                               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
                                zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
                                if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
                                param++;
@@ -990,21 +992,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, opline->extended_value,
+                       RETURN_VALUE_USED(opline) ?
+                               ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
+                       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();
        }
@@ -1056,7 +1056,7 @@ static int ZEND_FASTCALL  ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
 static int ZEND_FASTCALL  ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        SAVE_OPLINE();
-       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(op_array)->function_name->val);
+       zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val);
        ZEND_VM_NEXT_OPCODE(); /* Never reached */
 }
 
@@ -1064,7 +1064,7 @@ static int ZEND_FASTCALL  ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -1074,7 +1074,7 @@ static int ZEND_FASTCALL  ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -1084,7 +1084,7 @@ static int ZEND_FASTCALL  ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
 {
        SAVE_OPLINE();
        if (!EG(no_extensions)) {
-               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
+               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(func) TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -1095,7 +1095,7 @@ static int ZEND_FASTCALL  ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
        USE_OPLINE
 
        SAVE_OPLINE();
-       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0 TSRMLS_CC);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1105,7 +1105,7 @@ static int ZEND_FASTCALL  ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER(ZEND_OPCODE_
        USE_OPLINE
 
        SAVE_OPLINE();
-       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+       Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1119,7 +1119,7 @@ static int ZEND_FASTCALL  ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER(ZEND
        if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
            ((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
             Z_CE_P(zce) != Z_CE_P(orig_zce))) {
-               do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+               do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -1130,7 +1130,7 @@ static int ZEND_FASTCALL  ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
        USE_OPLINE
 
        SAVE_OPLINE();
-       do_bind_function(EX(op_array), opline, EG(function_table), 0);
+       do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1202,45 +1202,37 @@ static int ZEND_FASTCALL  ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 
 static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
-       zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
+       zend_uint op_num = EG(opline_before_exception) - EX(func)->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) {
+       for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
+               if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
                        /* further blocks will not be relevant... */
                        break;
                }
-               if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
-                       catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
+               if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) {
+                       catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op;
                }
-               if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
-                       finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
+               if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
+                       finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
                }
-               if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op &&
-                               op_num < EG(active_op_array)->try_catch_array[i].finally_end) {
-                       finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end;
+               if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
+                               op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
+                       finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
                }
        }
 
-       if (EX(call) >= EX(call_slots)) {
-               call_slot *call = EX(call);
+       if (EX(call)) {
+               zend_execute_data *call = EX(call);
                do {
+                       /* If the exception was thrown during a function call there might be
+                        * arguments pushed to the stack that have to be dtor'ed. */
+                       zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
                        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_UNUSED)) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {
@@ -1249,21 +1241,22 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       call--;
-               } while (call >= EX(call_slots));
-               EX(call) = NULL;
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+                       call = EX(call);
+               } while (call);
        }
 
-       for (i=0; i<EX(op_array)->last_brk_cont; i++) {
-               if (EX(op_array)->brk_cont_array[i].start < 0) {
+       for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+               if (EX(func)->op_array.brk_cont_array[i].start < 0) {
                        continue;
-               } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+               } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
-               } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+               } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
                        if (!catch_op_num ||
-                           catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
-                               zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+                           catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+                               zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
 
                                if (brk_opline->opcode == ZEND_SWITCH_FREE) {
                                        if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -1299,7 +1292,7 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                EX(delayed_exception) = EG(exception);
                EG(exception) = NULL;
                EX(fast_ret) = NULL;
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
                ZEND_VM_CONTINUE();
        } else if (catch_op_num) {
                if (finally_op_end && catch_op_num > finally_op_end) {
@@ -1309,14 +1302,14 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                                EX(delayed_exception) = NULL;
                        }
                }
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
                ZEND_VM_CONTINUE();
        } else {
                if (EX(delayed_exception)) {
                        zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
                        EX(delayed_exception) = NULL;
                }
-               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                        return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                } else {
                        return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1347,7 +1340,7 @@ static int ZEND_FASTCALL  ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
                case ZEND_USER_OPCODE_CONTINUE:
                        ZEND_VM_CONTINUE();
                case ZEND_USER_OPCODE_RETURN:
-                       if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                                return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                        } else {
                                return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1381,7 +1374,7 @@ static int ZEND_FASTCALL  ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        if (opline->extended_value &&
            UNEXPECTED(EG(prev_exception) != NULL)) {
            /* in case of unhandled exception jump to catch block instead of finally */
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                ZEND_VM_CONTINUE();
        }
        EX(fast_ret) = opline + 1;
@@ -1400,15 +1393,15 @@ static int ZEND_FASTCALL  ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                USE_OPLINE
 
                if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
-                       ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+                       ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                        ZEND_VM_CONTINUE();
                } else {
                        EG(exception) = EX(delayed_exception);
                        EX(delayed_exception) = NULL;
                        if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
-                               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+                               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
                                ZEND_VM_CONTINUE();
-                       } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+                       } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                                return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                        } else {
                                return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1459,32 +1452,32 @@ 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
-       zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
+       zval *function_name, *func;
 
        if (IS_CONST == IS_CONST) {
-               function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+               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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
        } else {
                zend_string *lcname;
 
+               zend_class_entry *called_scope;
+               zend_object *object;
+               zval *function_name_ptr;
 
                SAVE_OPLINE();
                function_name_ptr = function_name = opline->op2.zv;
@@ -1503,36 +1496,23 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
+                       fbc = Z_FUNC_P(func);
+                       called_scope = NULL;
+                       object = NULL;
                } 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else if (IS_CONST != IS_CONST &&
                                EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                                zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -1555,50 +1535,49 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else {
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+                       ZEND_VM_CONTINUE(); /* Never reached */
                }
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -1608,30 +1587,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);
+       }
+
+       EX(call) = zend_vm_stack_push_call_frame(
+               fbc, opline->extended_value, 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);
        }
 
-       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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1640,30 +1640,24 @@ 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);
-       zval *var_ptr;
+       zval *param;
 
        SAVE_OPLINE();
-       var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
-       if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
-       if (arg_num > arg_count) {
-               ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
-               if (Z_OPT_CONSTANT_P(var_ptr)) {
-                       zval_update_constant(var_ptr, 0 TSRMLS_CC);
+       param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+       if (arg_num > EX(num_args)) {
+               ZVAL_COPY_VALUE(param, opline->op2.zv);
+               if (Z_OPT_CONSTANT_P(param)) {
+                       zval_update_constant(param, 0 TSRMLS_CC);
                } else {
                        /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
-                       if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
-                               zval_copy_ctor_func(var_ptr);
+                       if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
+                               zval_copy_ctor_func(param);
                        }
                }
-       } else {
-               zval *param = arguments - arg_count + arg_num - 1;
-               ZVAL_COPY(var_ptr, param);
        }
 
-       if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
-               zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+       if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
        }
 
        CHECK_EXCEPTION();
@@ -1677,8 +1671,8 @@ static int ZEND_FASTCALL  ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
-                          EX(op_array), execute_data TSRMLS_CC);
-       ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
+       ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
 }
 
 static int ZEND_FASTCALL  ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -1688,8 +1682,8 @@ static int ZEND_FASTCALL  ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
-                          EX(op_array), execute_data TSRMLS_CC);
-       ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
+       ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
 }
 
 static int ZEND_FASTCALL  ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -1700,9 +1694,9 @@ static int ZEND_FASTCALL  ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
        SAVE_OPLINE();
        el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
-                          EX(op_array), execute_data TSRMLS_CC);
+                          &EX(func)->op_array, execute_data TSRMLS_CC);
 
-       brk_opline = EX(op_array)->opcodes + el->brk;
+       brk_opline = EX(func)->op_array.opcodes + el->brk;
 
        if (brk_opline->opcode == ZEND_SWITCH_FREE) {
                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -1786,32 +1780,32 @@ 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
-       zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
+       zval *function_name, *func;
 
        if (IS_TMP_VAR == IS_CONST) {
-               function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+               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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
        } else {
                zend_string *lcname;
                zend_free_op free_op2;
+               zend_class_entry *called_scope;
+               zend_object *object;
+               zval *function_name_ptr;
 
                SAVE_OPLINE();
                function_name_ptr = function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -1830,37 +1824,23 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
+                       fbc = Z_FUNC_P(func);
+                       called_scope = NULL;
+                       object = NULL;
                } 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else if (IS_TMP_VAR != IS_CONST &&
                                EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                                zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -1883,51 +1863,49 @@ 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;
-
                        zval_dtor(free_op2.var);
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else {
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+                       ZEND_VM_CONTINUE(); /* Never reached */
                }
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -1975,32 +1953,32 @@ 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
-       zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
+       zval *function_name, *func;
 
        if (IS_VAR == IS_CONST) {
-               function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+               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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
        } else {
                zend_string *lcname;
                zend_free_op free_op2;
+               zend_class_entry *called_scope;
+               zend_object *object;
+               zval *function_name_ptr;
 
                SAVE_OPLINE();
                function_name_ptr = function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -2019,37 +1997,23 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
+                       fbc = Z_FUNC_P(func);
+                       called_scope = NULL;
+                       object = NULL;
                } 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else if (IS_VAR != IS_CONST &&
                                EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                                zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2072,51 +2036,49 @@ 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;
-
                        zval_ptr_dtor_nogc(free_op2.var);
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else {
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+                       ZEND_VM_CONTINUE(); /* Never reached */
                }
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -2202,32 +2164,32 @@ 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
-       zval *function_name_ptr, *function_name, *func;
-       call_slot *call = EX(call_slots) + opline->result.num;
+       zend_function *fbc;
+       zval *function_name, *func;
 
        if (IS_CV == IS_CONST) {
-               function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+               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, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
        } else {
                zend_string *lcname;
 
+               zend_class_entry *called_scope;
+               zend_object *object;
+               zval *function_name_ptr;
 
                SAVE_OPLINE();
                function_name_ptr = function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
@@ -2246,36 +2208,23 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
+                       fbc = Z_FUNC_P(func);
+                       called_scope = NULL;
+                       object = NULL;
                } 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else if (IS_CV != IS_CONST &&
                                EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                                zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2298,50 +2247,49 @@ 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;
-
-                       CHECK_EXCEPTION();
-                       ZEND_VM_NEXT_OPCODE();
                } else {
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+                       ZEND_VM_CONTINUE(); /* Never reached */
                }
+               EX(call) = zend_vm_stack_push_call_frame(
+                       fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -2557,34 +2505,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
@@ -2705,22 +2625,23 @@ static int ZEND_FASTCALL  ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *value, *top;
+       zval *value, *arg;
 
 
        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);
                }
        }
 
        value = opline->op1.zv;
-       top = zend_vm_stack_top_inc(TSRMLS_C);
-       ZVAL_COPY_VALUE(top, value);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
+       ZVAL_COPY_VALUE(arg, value);
        if (IS_CONST == IS_CONST) {
-               if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
-                       zval_copy_ctor_func(top);
+               if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+                       zval_copy_ctor_func(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -2999,23 +2920,23 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                        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, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
                }
 
+               EX(call)->prev_execute_data = EG(current_execute_data);
+           i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
-                       zend_execute(new_op_array, return_value TSRMLS_CC);
+                       execute_ex(EG(current_execute_data) TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->op_array;
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3789,7 +3710,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();
 
@@ -3798,7 +3720,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -3807,24 +3729,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 +3755,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 +3781,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4336,7 +4255,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_CONST != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -4757,7 +4676,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();
 
@@ -4766,7 +4686,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -4775,24 +4695,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 +4721,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 +4747,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5022,7 +4939,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_CONST != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -5593,7 +5510,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();
 
@@ -5602,7 +5520,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -5611,24 +5529,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 +5555,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 +5581,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -6009,7 +5924,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_CONST != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -6288,7 +6203,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();
 
@@ -6297,7 +6213,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -6306,24 +6222,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 +6248,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 +6274,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -6681,7 +6594,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 {
@@ -6713,7 +6626,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
        if (IS_CONST != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -7119,7 +7032,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();
 
@@ -7128,7 +7042,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -7137,24 +7051,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 +7077,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 +7103,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_CONST != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -7238,7 +7149,7 @@ static int ZEND_FASTCALL  ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
        /* Check whether an exception has been thrown, if not, jump over code */
        zend_exception_restore(TSRMLS_C);
        if (EG(exception) == NULL) {
-               ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+               ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
                ZEND_VM_CONTINUE(); /* CHECK_ME */
        }
        if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
@@ -7262,7 +7173,7 @@ static int ZEND_FASTCALL  ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
                                zend_throw_exception_internal(NULL TSRMLS_CC);
                                HANDLE_EXCEPTION();
                        }
-                       ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+                       ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
                        ZEND_VM_CONTINUE(); /* CHECK_ME */
                }
        }
@@ -7436,7 +7347,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
        if (IS_CONST != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -7906,22 +7817,23 @@ static int ZEND_FASTCALL  ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *value, *top;
+       zval *value, *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);
                }
        }
 
        value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
-       ZVAL_COPY_VALUE(top, value);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
+       ZVAL_COPY_VALUE(arg, value);
        if (IS_TMP_VAR == IS_CONST) {
-               if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
-                       zval_copy_ctor_func(top);
+               if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+                       zval_copy_ctor_func(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -8202,23 +8114,23 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                        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, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
                }
 
+               EX(call)->prev_execute_data = EG(current_execute_data);
+           i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
-                       zend_execute(new_op_array, return_value TSRMLS_CC);
+                       execute_ex(EG(current_execute_data) TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->op_array;
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -9079,8 +8991,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,48 +9009,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CONST != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -9449,7 +9362,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -9914,8 +9827,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,32 +9845,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
 
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_dtor(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -9963,15 +9854,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_TMP_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -10135,7 +10049,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -10750,8 +10664,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,32 +10682,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_ptr_dtor_nogc(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -10799,15 +10691,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -11122,7 +11037,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -11687,7 +11602,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -12136,8 +12051,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,48 +12069,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CV != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -12355,7 +12271,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        if (IS_TMP_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -13044,18 +12960,19 @@ static int ZEND_FASTCALL  ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
        zend_free_op free_op1;
 
        varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
                zval_ptr_dtor_nogc(free_op1.var);
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (IS_VAR == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -13065,7 +12982,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
 {
        USE_OPLINE
        zend_free_op free_op1;
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -13073,7 +12990,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);
                }
        }
@@ -13090,15 +13007,18 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                if (IS_VAR == IS_CV) {
                        Z_ADDREF_P(varptr);
                }
-               zend_vm_stack_push(varptr TSRMLS_CC);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY_VALUE(arg, varptr);
        } 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);
-               ZVAL_COPY(top, varptr);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY(arg, varptr);
                zval_ptr_dtor_nogc(free_op1.var);
        }
        CHECK_EXCEPTION();
@@ -13109,7 +13029,7 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
 {
        USE_OPLINE
        zend_free_op free_op1;
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
@@ -13118,23 +13038,24 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
                zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
        }
 
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
-               ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+               ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
                ZEND_VM_NEXT_OPCODE();
        }
 
        if (Z_ISREF_P(varptr)) {
                Z_ADDREF_P(varptr);
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
        } else if (IS_VAR == IS_VAR &&
                UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
-               ZVAL_COPY_VALUE(top, varptr);
-               ZVAL_MAKE_REF(top);
+               ZVAL_COPY_VALUE(arg, varptr);
+               ZVAL_MAKE_REF(arg);
        } else {
                ZVAL_MAKE_REF(varptr);
                Z_ADDREF_P(varptr);
-               ZVAL_REF(top, Z_REF_P(varptr));
+               ZVAL_REF(arg, Z_REF_P(varptr));
        }
 
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -13144,24 +13065,25 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
 static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
        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);
                }
        }
 
        varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
                zval_ptr_dtor_nogc(free_op1.var);
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (IS_VAR == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -13453,23 +13375,23 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                        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, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
                }
 
+               EX(call)->prev_execute_data = EG(current_execute_data);
+           i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
-                       zend_execute(new_op_array, return_value TSRMLS_CC);
+                       execute_ex(EG(current_execute_data) TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->op_array;
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -15334,8 +15256,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,48 +15274,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CONST != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -15404,7 +15327,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();
 
@@ -15413,7 +15337,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -15422,24 +15346,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 +15372,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 +15398,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -16187,7 +16108,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -17562,8 +17483,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,32 +17501,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
 
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_dtor(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -17611,15 +17510,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_TMP_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
        zval_ptr_dtor_nogc(free_op1.var);
@@ -17633,7 +17555,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();
 
@@ -17642,7 +17565,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -17651,24 +17574,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 +17600,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 +17626,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -18169,7 +18089,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -19758,8 +19678,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,32 +19696,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_ptr_dtor_nogc(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -19807,15 +19705,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
        zval_ptr_dtor_nogc(free_op1.var);
@@ -19829,7 +19750,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();
 
@@ -19838,7 +19760,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -19847,24 +19769,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 +19795,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 +19821,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -20516,7 +20435,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -21295,7 +21214,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();
 
@@ -21304,7 +21224,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -21313,24 +21233,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 +21259,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 +21285,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -21713,7 +21630,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -23129,8 +23046,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,48 +23064,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CV != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -23199,7 +23117,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();
 
@@ -23208,7 +23127,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
                        ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
                } else {
-                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
                        if (UNEXPECTED(EG(exception) != NULL)) {
                                HANDLE_EXCEPTION();
                        }
@@ -23217,24 +23136,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 +23162,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 +23188,37 @@ 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;
-       } 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);
-                       } 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);
+       object = NULL;
+       if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+               if (Z_OBJ(EG(This))) {
+                       if (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 (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", fbc->common.scope->name->val, fbc->common.function_name->val);
+                               }
                        }
+                       object = Z_OBJ(EG(This));
+                       GC_REFCOUNT(object)++;
                }
-               call->object = Z_OBJ(EG(This));
-               if (call->object) {
-                       GC_REFCOUNT(call->object)++;
+       }
+
+       if (IS_VAR != IS_CONST) {
+               /* previous opcode is ZEND_FETCH_CLASS */
+               if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->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, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -23732,7 +23648,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        if (IS_VAR != IS_UNUSED) {
                zend_free_op free_op1;
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -24706,8 +24622,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,48 +24640,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CONST != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -25190,7 +25107,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
        if (IS_UNUSED != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -26079,8 +25996,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,32 +26014,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
 
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_dtor(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -26128,15 +26023,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_TMP_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -26467,7 +26385,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_UNUSED != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -27356,8 +27274,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,32 +27292,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_ptr_dtor_nogc(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -27405,15 +27301,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -27744,7 +27663,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_UNUSED != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -28260,7 +28179,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
        if (IS_UNUSED != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -29143,8 +29062,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,48 +29080,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CV != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -29528,7 +29448,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_UNUSED != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -30187,18 +30107,19 @@ static int ZEND_FASTCALL  ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
 
        varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
 
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (IS_CV == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -30208,7 +30129,7 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
 {
        USE_OPLINE
 
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -30216,7 +30137,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);
                }
        }
@@ -30233,15 +30154,18 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                if (IS_CV == IS_CV) {
                        Z_ADDREF_P(varptr);
                }
-               zend_vm_stack_push(varptr TSRMLS_CC);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY_VALUE(arg, varptr);
        } 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);
-               ZVAL_COPY(top, varptr);
+               arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+               EX(call)->num_args = opline->op2.num;
+               ZVAL_COPY(arg, varptr);
 
        }
        CHECK_EXCEPTION();
@@ -30252,7 +30176,7 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 {
        USE_OPLINE
 
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
        SAVE_OPLINE();
        varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
@@ -30261,23 +30185,24 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
                zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
        }
 
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
-               ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+               ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
                ZEND_VM_NEXT_OPCODE();
        }
 
        if (Z_ISREF_P(varptr)) {
                Z_ADDREF_P(varptr);
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
        } else if (IS_CV == IS_VAR &&
                UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
-               ZVAL_COPY_VALUE(top, varptr);
-               ZVAL_MAKE_REF(top);
+               ZVAL_COPY_VALUE(arg, varptr);
+               ZVAL_MAKE_REF(arg);
        } else {
                ZVAL_MAKE_REF(varptr);
                Z_ADDREF_P(varptr);
-               ZVAL_REF(top, Z_REF_P(varptr));
+               ZVAL_REF(arg, Z_REF_P(varptr));
        }
 
        ZEND_VM_NEXT_OPCODE();
@@ -30286,24 +30211,25 @@ static int ZEND_FASTCALL  ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zval *varptr, *top;
+       zval *varptr, *arg;
 
 
-       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);
                }
        }
 
        varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-       top = zend_vm_stack_top_inc(TSRMLS_C);
+       arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+       EX(call)->num_args = opline->op2.num;
        if (Z_ISREF_P(varptr)) {
-               ZVAL_COPY(top, Z_REFVAL_P(varptr));
+               ZVAL_COPY(arg, Z_REFVAL_P(varptr));
 
        } else {
-               ZVAL_COPY_VALUE(top, varptr);
+               ZVAL_COPY_VALUE(arg, varptr);
                if (IS_CV == IS_CV) {
-                       if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+                       if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
                }
        }
        ZEND_VM_NEXT_OPCODE();
@@ -30582,23 +30508,23 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                        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, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
                }
 
+               EX(call)->prev_execute_data = EG(current_execute_data);
+           i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
-                       zend_execute(new_op_array, return_value TSRMLS_CC);
+                       execute_ex(EG(current_execute_data) TSRMLS_CC);
                }
 
-               EX(function_state).function = (zend_function *) EX(op_array);
-
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
+               EG(active_op_array) = &EX(func)->op_array;
                destroy_op_array(new_op_array TSRMLS_CC);
                efree(new_op_array);
                if (UNEXPECTED(EG(exception) != NULL)) {
@@ -32312,8 +32238,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,48 +32256,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
+
+                       HANDLE_EXCEPTION();
+               }
+               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 (IS_CONST != IS_CONST ||
-                   (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
-                   zend_object *object = call->object;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       if (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       if (IS_CONST != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
 
-                       /* 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));
-                       }
-                       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);
-                       }
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -32951,7 +32878,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
        if (IS_CV != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -34354,8 +34281,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,32 +34299,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_dtor(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -34403,15 +34308,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_TMP_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -34846,7 +34774,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
        if (IS_CV != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -36432,8 +36360,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,32 +36378,8 @@ 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;
-
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object 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;
-
-                       if (UNEXPECTED(object->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));
-                       }
-                       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);
-                       }
-               }
-       } else {
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zval_ptr_dtor_nogc(free_op2.var);
                        HANDLE_EXCEPTION();
@@ -36481,15 +36387,38 @@ 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;
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+       if (IS_VAR != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+               }
+
+               /* First, locate the function. */
+               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(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);
+               }
+       }
+
+       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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -37075,7 +37004,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
        if (IS_CV != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -38138,7 +38067,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
        if (IS_CV != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -39551,8 +39480,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,48 +39498,47 @@ 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;
 
-       if (EXPECTED(call->object != NULL)) {
-               call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+       if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+               if (UNEXPECTED(EG(exception) != NULL)) {
 
-               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;
+                       HANDLE_EXCEPTION();
+               }
+               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 (UNEXPECTED(object->handlers->get_method == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
-                       }
+       obj = Z_OBJ_P(object);
+       called_scope = zend_get_class_entry(obj TSRMLS_CC);
 
-                       /* 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));
-                       }
-                       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);
-                       }
+       if (IS_CV != IS_CONST ||
+           (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+           zend_object *orig_obj = obj;
+
+               if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
-       } else {
-               if (UNEXPECTED(EG(exception) != NULL)) {
 
-                       HANDLE_EXCEPTION();
+               /* First, locate the function. */
+               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(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);
                }
-               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, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -40039,7 +39969,7 @@ static int ZEND_FASTCALL  ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        if (IS_CV != IS_UNUSED) {
 
 
-               if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+               if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        /* Constants and temporary variables aren't yieldable by reference,
                         * but we still allow them with a notice. */
                        if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -41678,56 +41608,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 +44368,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 fa976cb6783001698b4d8338f1a92b752584c8fc..41a834de958b714ffda69d4d6563d3d1869e97bc 100644 (file)
@@ -33,10 +33,21 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
 
 ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value TSRMLS_DC)
 {
+       zend_execute_data *execute_data;
+
        if (EG(exception) != NULL) {
                return;
-       } 
-       zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
+       }
+
+       if (EG(current_execute_data) && EG(current_execute_data)->call) {
+               execute_data = EG(current_execute_data)->call;
+       } else {
+               execute_data = zend_vm_stack_push_call_frame(
+                       (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC);
+       }
+       EX(prev_execute_data) = EG(current_execute_data);
+       i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+       zend_{%EXECUTOR_NAME%}_ex(execute_data TSRMLS_CC);
 }
 
 {%EXTERNAL_EXECUTOR%}
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 b5f2c95efe6c6369bedcabdca520545560c0d828..048362d3ec96bfc34188ea5b45d43b806972e8fe 100644 (file)
@@ -286,6 +286,10 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
                                EG(active_op_array) = new_op_array;
 
                                zend_try {
+                                       if (EG(current_execute_data)) {
+                                               EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+                                                       (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+                                       }
                                        zend_execute(new_op_array, &result TSRMLS_CC);
                                        if (PHAR_G(cwd)) {
                                                efree(PHAR_G(cwd));
index 22e2a0c67192e75401b96649940a634bf80149ba..5ec20cd563774c780ded771237df0fdadc7054f0 100644 (file)
@@ -292,6 +292,10 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha
                        }
 
                        ZVAL_UNDEF(&result);
+                       if (EG(current_execute_data)) {
+                               EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+                                       (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+                       }
                        zend_execute(new_op_array, &result TSRMLS_CC);
        
                        destroy_op_array(new_op_array TSRMLS_CC);
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..d5b4242fc3a03d514d2c8e0fa00662d497c7bdca 100644 (file)
@@ -42,6 +42,8 @@
 
 static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) /* {{{ */
 {
+// TODO: fpm_php_trace_dump() has to be reimplemented ???
+#if 0
        int callers_limit = 20;
        pid_t pid = child->pid;
        struct timeval tv;
@@ -131,6 +133,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
                        break;
                }
        }
+#endif
        return 0;
 }
 /* }}} */