]> granicus.if.org Git - php/commitdiff
Refactoring: merge call_frame and end_execute_data into single data structure. Keep...
authorDmitry Stogov <dmitry@zend.com>
Thu, 26 Jun 2014 19:51:14 +0000 (23:51 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 26 Jun 2014 19:51:14 +0000 (23:51 +0400)
16 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_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
ext/phar/phar_object.c
ext/spl/php_spl.c
sapi/fpm/fpm/fpm_php_trace.c

index 569a21fdc42b013baaf397592a92a25f6c2b9c67..a3d37793db737fbd2a7b6362da1679c69b282afb 100644 (file)
@@ -142,7 +142,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS
                if (Z_REFCOUNTED_P(param_ptr)) {
                        Z_ADDREF_P(param_ptr);
                }
-               add_next_index_zval(argument_array, param_ptr);
+               zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
                param_ptr++;
        }
 
index f0ed68b703925c403d71154924c6928089cad47e..15c1d689708d370ae4fba18a0e1542103a1b8443 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->call) {
-               RETURN_LONG(ex->call->num_args);
+       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);
@@ -412,7 +412,7 @@ ZEND_FUNCTION(func_get_arg)
        int arg_count;
        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;
@@ -423,19 +423,24 @@ ZEND_FUNCTION(func_get_arg)
                RETURN_FALSE;
        }
 
-       if (!ex || !ex->call) {
+       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;
        }
 
-       arg_count = ex->call->num_args;
+       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 = ZEND_CALL_ARG(ex->call, requested_offset + 1);
+       if (ex->extra_args && requested_offset >= ex->func->op_array.num_args) {
+               arg = ex->extra_args + (requested_offset - ex->func->op_array.num_args);
+       } else {
+               arg = ZEND_CALL_ARG(ex, requested_offset + 1);
+       }
        RETURN_ZVAL_FAST(arg);
 }
 /* }}} */
@@ -447,23 +452,39 @@ ZEND_FUNCTION(func_get_args)
        zval *p;
        int arg_count;
        int i;
-       zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+       zend_execute_data *ex = EG(current_execute_data);
 
-       if (!ex || !ex->call) {
+       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;
        }
 
-       arg_count = ex->call->num_args;
+       arg_count = ex->num_args;
 
        array_init_size(return_value, arg_count);
        if (arg_count) {
                Bucket *q;              
 
-               p = ZEND_CALL_ARG(ex->call, 1);
                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->extra_args) {
+                       while (i < ex->func->op_array.num_args) {
+                               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->extra_args;
+               }
+               while (i < arg_count) {
                        q->h = i;
                        q->key = NULL;
                        if (!Z_ISREF_P(p)) {
@@ -473,6 +494,7 @@ ZEND_FUNCTION(func_get_args)
                    }
                        p++;
                        q++;
+                       i++;
                }
                Z_ARRVAL_P(return_value)->nNumUsed = i;
                Z_ARRVAL_P(return_value)->nNumOfElements = i;
@@ -1954,24 +1976,30 @@ ZEND_FUNCTION(get_defined_constants)
 /* }}} */
 
 
-static void debug_backtrace_get_args(zend_call_frame *call, zval *arg_array TSRMLS_DC)
+static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TSRMLS_DC)
 {
-       zval *p;
-       zval *arg;
-       int arg_count = call->num_args;
+       int num_args = call->num_args;
 
-       array_init_size(arg_array, arg_count);
-       if (arg_count > 0) {
-               p = ZEND_CALL_ARG(call, 1);
+       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->extra_args) {
+                       while (i < call->func->op_array.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++;
                        }
+                       p = call->extra_args;
+               }
+
+               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++;
                }
        }
 }
@@ -2025,7 +2053,7 @@ ZEND_FUNCTION(debug_print_backtrace)
 
                skip = ptr;
                /* skip internal handler */
-               if (!skip->op_array &&
+               if ((!skip->func || (skip->func->common.type != ZEND_USER_FUNCTION && skip->func->common.type != ZEND_EVAL_CODE)) &&
                    skip->prev_execute_data &&
                    skip->prev_execute_data->opline &&
                    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
@@ -2033,8 +2061,8 @@ ZEND_FUNCTION(debug_print_backtrace)
                        skip = skip->prev_execute_data;
                }
 
-               if (skip->op_array) {
-                       filename = skip->op_array->filename->val;
+               if (skip->func && (skip->func->common.type == ZEND_USER_FUNCTION || skip->func->common.type == ZEND_EVAL_CODE)) {
+                       filename = skip->func->op_array.filename->val;
                        lineno = skip->opline->lineno;
                } else {
                        filename = NULL;
@@ -2060,7 +2088,7 @@ ZEND_FUNCTION(debug_print_backtrace)
                                (func->common.function_name ? 
                                        func->common.function_name->val : NULL);
                } else {
-                       func = (zend_function*)(ptr->op_array);
+                       func = ptr->func;
                        function_name = func && func->common.function_name ? 
                                func->common.function_name->val : NULL;
                }
@@ -2081,7 +2109,7 @@ ZEND_FUNCTION(debug_print_backtrace)
                                class_name = NULL;
                                call_type = NULL;
                        }
-                       if (!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL) {
+                       if (func->type != ZEND_EVAL_CODE) {
                                if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
                                        debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
                                }
@@ -2144,12 +2172,13 @@ ZEND_FUNCTION(debug_print_backtrace)
                        while (prev) {
                                if (prev->call &&
                                    prev->call->func &&
-                                       prev->call->func->common.type != ZEND_USER_FUNCTION) {
+                                       prev->call->func->common.type != ZEND_USER_FUNCTION &&
+                                       prev->call->func->common.type != ZEND_EVAL_CODE) {
                                        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 && (prev->func->common.type == ZEND_USER_FUNCTION || prev->func->common.type == ZEND_EVAL_CODE)) {
+                                       zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
                                        break;
                                }
                                prev = prev->prev_execute_data;
@@ -2201,7 +2230,7 @@ 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 || (skip->func->common.type != ZEND_USER_FUNCTION && skip->func->common.type != ZEND_EVAL_CODE)) &&
                    skip->prev_execute_data &&
                    skip->prev_execute_data->opline &&
                    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
@@ -2209,8 +2238,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                        skip = skip->prev_execute_data;
                }
 
-               if (skip->op_array) {
-                       filename = skip->op_array->filename->val;
+               if (skip->func && (skip->func->common.type == ZEND_USER_FUNCTION || skip->func->common.type == ZEND_EVAL_CODE)) {
+                       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);
@@ -2225,13 +2254,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                if (prev->call &&
                                    prev->call->func &&
                                        prev->call->func->common.type != ZEND_USER_FUNCTION &&
+                                       prev->call->func->common.type != ZEND_EVAL_CODE &&
                                        !(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 && (prev->func->common.type == ZEND_USER_FUNCTION || prev->func->common.type == ZEND_EVAL_CODE)) {
 // 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;
                                }
@@ -2259,7 +2289,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                (func->common.function_name ? 
                                        func->common.function_name->val : NULL);
                } else {
-                       func = (zend_function*)(ptr->op_array);
+                       func = ptr->func;
                        function_name = func && func->common.function_name ? 
                                func->common.function_name->val : NULL;
                }
@@ -2289,7 +2319,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                        }
 
                        if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && 
-                               (!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL)) {
+                               func->type != ZEND_EVAL_CODE) {
                                if (ptr->call) {
                                        zval args;
                                        debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
@@ -2346,7 +2376,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 85056d3cd559d92ae7ae9c22958d528b85eeffcd..053a5eb199a33f7eb266cabda01260f5102a4530 100644 (file)
@@ -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 690020a67d22fbaebeea628845fb2169398fba71..0434e7c754677fb328281bdb0bfffd524467de91 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,7 +182,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
        CG(context).literals_size = 0;
        CG(context).current_brk_cont = -1;
        CG(context).backpatch_count = 0;
-       CG(context).used_stack = 0;
        CG(context).in_finally = 0;
        CG(context).labels = NULL;
 }
@@ -1949,6 +1948,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
+       zend_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,14 +1977,14 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
        STR_RELEASE(Z_STR(function_name->u.constant));
        Z_STR(function_name->u.constant) = lcname;
 
+       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 TSRMLS_CC);
-       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
+       zend_push_function_call_entry(function, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 0;
 }
@@ -2035,8 +2035,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
                }
        }
 
-       zend_push_function_call_entry(NULL TSRMLS_CC);
-       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
+       zend_push_function_call_entry(NULL, last_op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2056,8 +2055,10 @@ 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
@@ -2079,8 +2080,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
                }
        }
 
-       zend_push_function_call_entry(NULL TSRMLS_CC);
-       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
+       zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
 /* }}} */
@@ -2477,6 +2477,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) {
@@ -2497,11 +2498,12 @@ 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;
        if (class_node.op_type == IS_CONST) {
@@ -2524,8 +2526,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);
-       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
+       zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
        zend_do_extended_fcall_begin(TSRMLS_C);
        return 1; /* Dynamic */
 }
@@ -2543,6 +2544,9 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
                }
                opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
        } else {
+               opline = &CG(active_op_array)->opcodes[fcall->op_number];
+               opline->extended_value = fcall->arg_num;
+
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                opline->opcode = ZEND_DO_FCALL;
                SET_UNUSED(opline->op1);
@@ -2554,10 +2558,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 > CG(active_op_array)->used_stack) {
-               CG(active_op_array)->used_stack = CG(context).used_stack;
-       }
-       CG(context).used_stack -= ZEND_CALL_FRAME_SLOT + fcall->arg_num;
        zend_stack_del_top(&CG(function_call_stack));
 }
 /* }}} */
@@ -2666,8 +2666,6 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
        SET_NODE(opline->op1, param);
        opline->op2.opline_num = fcall->arg_num;
        SET_UNUSED(opline->op2);
-
-       CG(context).used_stack++;
 }
 /* }}} */
 
@@ -5578,8 +5576,7 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
        SET_NODE(opline->op1, class_type);
        SET_UNUSED(opline->op2);
 
-       zend_push_function_call_entry(NULL TSRMLS_CC);
-       CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
+       zend_push_function_call_entry(NULL, new_token->u.op.opline_num TSRMLS_CC);
 }
 /* }}} */
 
@@ -5771,6 +5768,7 @@ 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));
@@ -5800,10 +5798,6 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
        SET_UNUSED(opline->op1);
        SET_UNUSED(opline->op2);
        GET_NODE(result, opline->result);
-
-       if (CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1 > CG(active_op_array)->used_stack) {
-               CG(active_op_array)->used_stack = CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1;
-       }
 }
 /* }}} */
 
index 35be52f2f70bedf30f32e4e78a77b61d55e86ab0..46732f25d0aa87a7a206b31ff67c3f9e3c1d7544 100644 (file)
@@ -59,7 +59,6 @@ typedef struct _zend_compiler_context {
        int        literals_size;
        int        current_brk_cont;
        int        backpatch_count;
-       int        used_stack;
        int        in_finally;
        HashTable *labels;
 } zend_compiler_context;
@@ -265,8 +264,6 @@ struct _zend_op_array {
 
        zend_uint T;
 
-       zend_uint used_stack;
-
        zend_brk_cont_element *brk_cont_array;
        int last_brk_cont;
 
@@ -336,6 +333,7 @@ union _zend_function {
 
 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;
@@ -353,27 +351,6 @@ typedef struct _list_llist_element {
        znode value;
 } list_llist_element;
 
-typedef struct _zend_call_frame zend_call_frame;
-
-struct _zend_call_frame {
-       zend_function         *func;
-       zend_uint              num_args;
-       zend_uint              flags;
-       zend_class_entry      *called_scope;
-       zend_object           *object;
-       zend_call_frame       *prev;
-};
-
-#define ZEND_CALL_CTOR               (1 << 0)
-#define ZEND_CALL_CTOR_RESULT_USED   (1 << 1)
-#define ZEND_CALL_DONE               (1 << 2)
-
-#define ZEND_CALL_FRAME_SLOT \
-       ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_call_frame)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
-
-#define ZEND_CALL_ARG(call, n) \
-       (((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
-
 typedef enum _vm_frame_kind {
        VM_FRAME_NESTED_FUNCTION,       /* stackless VM call to function */
        VM_FRAME_NESTED_CODE,           /* stackless VM call to include/require/eval */
@@ -383,26 +360,39 @@ typedef enum _vm_frame_kind {
 
 struct _zend_execute_data {
        struct _zend_op     *opline;           /* executed opline                */
-       zend_op_array       *op_array;         /* executed op_array              */
-       zend_call_frame     *call;             /* current call                   */
-       zend_object         *object;           /* current $this                  */
+       zend_function       *func;             /* executed op_array              */
+       zend_execute_data   *call;             /* current call                   */
+       zend_uint            num_args;
+       zend_uint            flags;
+       zend_class_entry    *called_scope;
+       zend_object         *object;
+       zend_execute_data   *prev_nested_call;
        zend_class_entry    *scope;            /* function scope (self)          */
-       zend_class_entry    *called_scope;     /* function called scope (static) */
        zend_array          *symbol_table;
        void               **run_time_cache;
        zend_execute_data   *prev_execute_data;
        zval                *return_value;
+       zval                *extra_args;
        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;
+       zval                 old_error_reporting;
+       struct _zend_op     *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
+       zend_object         *delayed_exception;
 };
 
+#define ZEND_CALL_CTOR               (1 << 0)
+#define ZEND_CALL_CTOR_RESULT_USED   (1 << 1)
+#define ZEND_CALL_DONE               (1 << 2)
+
+#define ZEND_CALL_FRAME_SLOT \
+       ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_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)
@@ -732,8 +722,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
index 4e5b811d7e0e11d49c929e9bb207d725e0c2dde7..e6e45674d05834ae99cc5b17169e83322afc0755 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 && (ptr->func->common.type == ZEND_USER_FUNCTION || ptr->func->common.type == ZEND_EVAL_CODE)) {
+               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 && (ptr->func->common.type == ZEND_USER_FUNCTION || ptr->func->common.type == ZEND_EVAL_CODE)) {
+                       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);
                }
@@ -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,104 +1527,22 @@ 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->last_var-1]              |
  *                             | VAR[op_array->last_var]                |
  *                             | ...                                    |
  *                             | VAR[op_array->last_var+op_array->T-1]  |
- * zend_vm_stack_frame_base -> +----------------------------------------+
- *           EX(call_slot)  -> | CALL_SLOT                              |
- *                             +----------------------------------------+
- *                             | 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 stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * op_array->used_stack;
-       size_t total_size = execute_data_size + vars_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)) * (ZEND_CALL_FRAME_SLOT + args_count);
-
-               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)->call = (zend_call_frame*)(((char*)EX(prev_execute_data)) + sizeof(zend_execute_data));
-               EX(prev_execute_data)->call->func = (zend_function*)op_array;
-               EX(prev_execute_data)->call->num_args = args_count;
-               EX(prev_execute_data)->call->flags = ZEND_CALL_DONE;
-               EX(prev_execute_data)->call->called_scope = NULL;
-               EX(prev_execute_data)->call->object = NULL;
-               EX(prev_execute_data)->call->prev = NULL;
-
-               /* copy arguments */
-               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;
@@ -1624,23 +1552,32 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
 
        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(op_array) = op_array;
-       EX(object) = Z_OBJ(EG(This));
+//???  EX(func) = (zend_function*)op_array;
        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 {
+
+               if (UNEXPECTED(EX(num_args) > op_array->num_args)) {
+                       /* move extra args into separate array */
+                       EX(extra_args) = safe_emalloc(EX(num_args) - op_array->num_args, sizeof(zval), 0);
+                       memcpy(EX(extra_args), EX_VAR_NUM(op_array->num_args), sizeof(zval) * (EX(num_args) - op_array->num_args));
+               }
+
                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));
+
+                       if (EXPECTED(num_args < op_array->last_var)) {
+                               zval *var = EX_VAR_NUM(num_args);
+                               zval *end = EX_VAR_NUM(op_array->last_var);
 
-                       while (var != end) {
-                               ZVAL_UNDEF(var);
-                               var++;
+                               do {
+                                       ZVAL_UNDEF(var);
+                                       var++;
+                               } while (var != end);
                        }
                } while (0);
 
@@ -1659,64 +1596,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, zend_call_frame *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->func, arg_num);
 }
 /* }}} */
 
-static zend_call_frame *zend_vm_stack_copy_call_frame(zend_call_frame *call TSRMLS_DC) /* {{{ */
+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_uint count;
-       zend_call_frame *new_call;
-       zend_vm_stack p = EG(argument_stack);
+       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);
+       }
 
-       zend_vm_stack_extend(ZEND_CALL_FRAME_SLOT + call->num_args TSRMLS_CC);
+       /* delete old call_frame from previous stack segment */
+       EG(argument_stack)->prev->top = (zval*)call;
 
-       new_call = (zend_call_frame*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
-       *new_call = *call;
-       EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT + call->num_args;
-       count = call->num_args;
-       while (count-- > 0) {
-               zval *data = --p->top;
-               ZVAL_COPY_VALUE(ZEND_CALL_ARG(new_call, count), data);
-
-               if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
-                       zend_vm_stack r = p;
-
-                       EG(argument_stack)->prev = p->prev;
-                       p = p->prev;
-                       efree(r);
-               }
+       /* 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 = r->prev;
+               efree(r);
        }
+
        return new_call;
 }
 /* }}} */
 
-static zend_always_inline void zend_vm_stack_adjust_call_frame(zend_call_frame **call 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)) < ZEND_CALL_FRAME_SLOT + (*call)->num_args)
-               || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
-               *call = zend_vm_stack_copy_call_frame(*call 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);
        }
 }
 /* }}} */
 
-
 #define ZEND_VM_NEXT_OPCODE() \
        CHECK_SYMBOL_TABLES() \
        ZEND_VM_INC_OPCODE(); \
index 49d9275bfa272bdfeff9f711aa0fa4e9f774c870..2127e1f2a1c2cea2ebf02909fb1c4311000729b4 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,8 +158,11 @@ 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))))
+       (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT)
 
 #define ZEND_VM_STACK_GROW_IF_NEEDED(count)                                                    \
        do {                                                                                                                    \
@@ -169,10 +173,10 @@ struct _zend_vm_stack {
        } 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 +184,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,90 +200,87 @@ 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);
+       zend_vm_stack p = zend_vm_stack_new_page(
+               (count >= ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) ? 
+                       ((count + ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE - 1) & ~(ZEND_VM_STACK_PAGE_SIZE-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)
-{
-       return EG(argument_stack)->top++;
-}
-
-static zend_always_inline void zend_vm_stack_push(zval *ptr TSRMLS_DC)
-{
-       ZVAL_COPY_VALUE(EG(argument_stack)->top, ptr);
-       EG(argument_stack)->top++;
-}
-
-static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
-{
-       return --EG(argument_stack)->top;
-}
-
-static zend_always_inline zend_call_frame *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_call_frame *prev TSRMLS_DC)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
 {
-       zend_call_frame * call = (zend_call_frame*)EG(argument_stack)->top;
+       int used_stack = ZEND_CALL_FRAME_SLOT;
+       zend_execute_data *call;
+       
+       if (func && (func->type == ZEND_USER_FUNCTION || func->type == ZEND_EVAL_CODE)) {
+               used_stack += MAX(func->op_array.last_var + func->op_array.T, num_args);
+       } else {
+               used_stack += num_args;
+       }
+       ZEND_VM_STACK_GROW_IF_NEEDED(used_stack);
+       call = (zend_execute_data*)EG(argument_stack)->top;
        call->func = func;
-       call->num_args = num_args;
+       call->num_args = 0; //??? num_args;
        call->flags = flags;
        call->called_scope = called_scope;
        call->object = object;
-       call->prev = prev;
-       EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT;
+       call->prev_nested_call = prev;
+       call->extra_args = NULL;
+       EG(argument_stack)->top += used_stack;
        return call;
 }
 
-static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
-{
-       zval *ret;
-       int count = (size + (sizeof(zval) - 1)) / sizeof(zval);
-
-       ZEND_VM_STACK_GROW_IF_NEEDED(count);
-       ret = (void*)EG(argument_stack)->top;
-       EG(argument_stack)->top += count;
-       return ret;
-}
-
-static zend_always_inline zval* zend_vm_stack_frame_base(zend_execute_data *ex)
-{
-       return EX_VAR_NUM_2(ex, ex->op_array->last_var + ex->op_array->T);
-}
-
-static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
 {
-       if (UNEXPECTED((void*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == ptr)) {
-               zend_vm_stack p = EG(argument_stack);
-
-               EG(argument_stack) = p->prev;
-               efree(p);
-       } else {
-               EG(argument_stack)->top = (zval*)ptr;
-       }
+       if (UNEXPECTED(call->extra_args != NULL)) {
+               zval *p = call->extra_args + (call->num_args - call->func->op_array.num_args);
+               zval *end = call->extra_args;
+               do {
+                       p--;
+                       i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+               } while (p != end);
+               efree(end);
+       }
 }
 
-static zend_always_inline void zend_vm_stack_free_call_frame(zend_call_frame *call, int nested TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
 {
        zend_uint num_args = call->num_args;    
 
        if (num_args > 0) {
-               zval *p = ZEND_CALL_ARG(call, num_args + 1);
-               zval *end = p - num_args;
-
+               zval *p;
+               zval *end;
+
+               if (UNEXPECTED(call->extra_args != NULL)) {
+                       p = call->extra_args + (num_args - call->func->op_array.num_args);
+                       end = call->extra_args;
+                       do {
+                               p--;
+                               i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+                       } while (p != end);
+                       efree(end);
+                       num_args = call->func->op_array.num_args;
+               }
+
+               p = ZEND_CALL_ARG(call, num_args + 1);
+               end = p - num_args;
                do {
                        p--;
                        i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
                } while (p != end);
        }
-       if (nested) {
-               EG(argument_stack)->top = (zval*)call;
+}
+
+static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
+{
+       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 {
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               EG(argument_stack)->top = (zval*)call;
        }
 }
 
index d326037b152dfea8a6bf3d9953c97eeb245f67fc..1efed55eb3e5d1f1d9493995a8a059cadeb67327 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;
@@ -401,10 +400,11 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
                }
                return "";
        }
+
        if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
                func = EG(current_execute_data)->call->func;
        } else {
-               func = (zend_function*)EG(current_execute_data)->op_array;
+               func = EG(current_execute_data)->func;
        }
        switch (func->type) {
                case ZEND_USER_FUNCTION:
@@ -436,7 +436,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
        if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
                func = EG(current_execute_data)->call->func;
        } else {
-               func = (zend_function*)EG(current_execute_data)->op_array;
+               func = EG(current_execute_data)->func;
        }
        switch (func->type) {
                case ZEND_USER_FUNCTION: {
@@ -696,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
@@ -734,8 +734,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                STR_RELEASE(callable_name);
        }
 
-       ZEND_VM_STACK_GROW_IF_NEEDED(ZEND_CALL_FRAME_SLOT + fci->param_count);
-
        func = fci_cache->function_handler;
        EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
        calling_scope = fci_cache->calling_scope;
@@ -783,12 +781,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
 
                                if (fci->no_separation &&
                                        !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
-                                       if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
+                                       if (i) {
                                                /* hack to clean up the stack */
-                                               ZVAL_LONG(&tmp, i);
-                                               zend_vm_stack_push(&tmp TSRMLS_CC);
-                                               zend_vm_stack_free_call_frame(EX(call), 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,
@@ -810,24 +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 */
                           (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(call)->num_args = fci->param_count;
 
        EG(scope) = calling_scope;
        EG(called_scope) = called_scope;
        if (!fci->object ||
            (func->common.fn_flags & ZEND_ACC_STATIC)) {
-               Z_OBJ(EG(This)) = NULL;
+               Z_OBJ(EG(This)) = EX(call)->object = NULL;
        } else {
                Z_OBJ(EG(This)) = fci->object;
                Z_ADDREF(EG(This));
@@ -873,6 +873,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                } 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)
@@ -908,7 +911,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        ZVAL_UNDEF(fci->retval);
                }
        }
-       zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
+//???  zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
 
        if (Z_OBJ(EG(This))) {
                zval_ptr_dtor(&EG(This));
@@ -1093,6 +1096,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);
@@ -1596,33 +1603,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 || (ex->func->common.type != ZEND_USER_FUNCTION && ex->func->common.type != ZEND_EVAL_CODE))) {
                        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);
                }
        }
 }
@@ -1631,7 +1639,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
@@ -1662,7 +1670,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 */
@@ -1682,7 +1690,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) {
@@ -1715,7 +1723,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 2f82922b7aa50cdc59f5516043ba470364d466e2..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) {
                if (execute_data->call->object) {
                        OBJ_RELEASE(execute_data->call->object);
                }
-               execute_data->call = execute_data->call->prev;
+               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,22 +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;
-
-                       if (prev_execute_data->call) {
-                               int arguments_count = prev_execute_data->call->num_args;
-                               zval *arguments_start = ZEND_CALL_ARG(prev_execute_data->call, 1);
-                               int i;
-
-                               for (i = 0; i < arguments_count; ++i) {
-                                       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). */
@@ -157,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;
        }
@@ -170,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;
@@ -195,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);
@@ -287,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;
@@ -299,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;
@@ -342,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;
@@ -357,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;
@@ -669,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 7fb1d9d87818c944e81d7b8cebd9b319c86bb8a6..713d1e2c41aef1c70132cfac5e2d30c10ca73cdb 100644 (file)
@@ -70,8 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
 
        op_array->T = 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;
index f6153d80ec56e872287b2f019396d384beb41ce2..e8ae1341fd240607e9f38d682302a141b2a7c992 100644 (file)
@@ -1772,7 +1772,8 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
 ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
-       zend_call_frame *call;
+       zend_execute_data *prev_nested_call;
+       zend_uint call_flags;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -1781,19 +1782,23 @@ 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);
+               call_flags = EX(flags);
+               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);
 
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
-                               if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
+                               if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -1810,10 +1815,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                EG(scope) = EX(scope);
                EG(called_scope) = EX(called_scope);
 
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
-
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
                        zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -1828,17 +1829,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);
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               EG(active_op_array) = &EX(func)->op_array;
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -1850,6 +1850,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;
@@ -1857,7 +1858,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 && (old_execute_data->func->op_array.type == ZEND_USER_FUNCTION || old_execute_data->func->op_array.type == ZEND_EVAL_CODE)) {
                                        if (old_execute_data->symbol_table == symbol_table) {
                                                zend_attach_symbol_table(old_execute_data);
                                        }
@@ -1866,10 +1867,15 @@ 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();
        }               
@@ -2255,7 +2261,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        FREE_OP2();
        FREE_OP1_IF_VAR();
@@ -2279,7 +2285,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();
                        }
@@ -2365,13 +2371,14 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
        }
 
        if (OP1_TYPE != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -2398,7 +2405,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2425,7 +2432,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                        FREE_OP2();
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                               Z_FUNC_P(func), opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2445,7 +2452,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2503,7 +2510,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        FREE_OP2();
                        CHECK_EXCEPTION();
@@ -2544,7 +2551,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -2568,7 +2575,7 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        FREE_OP2();
 
@@ -2578,14 +2585,12 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
 ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
 {
        USE_OPLINE
-       zend_function *fbc = EX(call)->func;
-       zend_object *object;
-       zend_uint num_args;
-       zend_call_frame *call;
+       zend_execute_data *call = EX(call);
+       zend_function *fbc = call->func;
+       zend_uint call_flags = call->flags;
 
        SAVE_OPLINE();
-       EX(call)->flags |= ZEND_CALL_DONE;
-       object = EX(call)->object;
+       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);
@@ -2602,7 +2607,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
        }
        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 */
@@ -2617,37 +2622,33 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                }
        }
 
-       if (EXPECTED(EX(call)->num_args == 0)) {
-               EX(call)->num_args = num_args = opline->extended_value;
-       } else {
-               EX(call)->num_args += opline->extended_value;
-               num_args = EX(call)->num_args;
-               zend_vm_stack_adjust_call_frame(&EX(call) TSRMLS_CC);
-       }
+//???
+       call->num_args += opline->extended_value;
+
        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 = ZEND_CALL_ARG(EX(call), 1);
+                       zval *p = ZEND_CALL_ARG(call, 1);
 
-                       for (i = 0; i < num_args; ++i) {
+                       for (i = 0; i < call->num_args; ++i) {
                                zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
                                p++;
                        }
@@ -2669,10 +2670,15 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
 
                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);
@@ -2683,12 +2689,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                } else {
                        ZEND_VM_C_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)) {
@@ -2698,40 +2704,50 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                        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);
                }
@@ -2748,8 +2764,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
 
 ZEND_VM_C_LABEL(fcall_end_change_scope):
        if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
-                       if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
+               if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
+                       if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -2757,7 +2773,6 @@ ZEND_VM_C_LABEL(fcall_end_change_scope):
                        }
                }
                if (!Z_DELREF(EG(This))) {
-                       EX(call)->flags &= ~ZEND_CALL_DONE;
                        _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
                } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
                        gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
@@ -2768,10 +2783,6 @@ ZEND_VM_C_LABEL(fcall_end_change_scope):
        EG(called_scope) = EX(called_scope);
 
 ZEND_VM_C_LABEL(fcall_end):
-       call = EX(call);
-       EX(call) = EX(call)->prev;
-       zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
-
        if (UNEXPECTED(EG(exception) != NULL)) {
                zend_throw_exception_internal(NULL TSRMLS_CC);
                if (RETURN_VALUE_USED(opline)) {
@@ -2923,7 +2934,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))) {
@@ -2947,7 +2958,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 */
                }
        }
@@ -2969,7 +2980,7 @@ 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();
@@ -2980,11 +2991,11 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
        }
 
        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);
+       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();
@@ -2993,18 +3004,18 @@ 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);
        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();
@@ -3014,7 +3025,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 */
@@ -3039,15 +3050,16 @@ 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);
+               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)->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);
+               ZVAL_COPY(arg, varptr);
                FREE_OP1_IF_VAR();
        }
        CHECK_EXCEPTION();
@@ -3058,7 +3070,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);
@@ -3067,23 +3079,23 @@ 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);
        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();
@@ -3093,7 +3105,7 @@ 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_ARG_COMPILE_TIME_BOUND) {
@@ -3103,14 +3115,14 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
        }
 
        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);
        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();
@@ -3134,7 +3146,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;
@@ -3161,7 +3173,7 @@ ZEND_VM_C_LABEL(send_again):
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               top = zend_vm_stack_top_inc(TSRMLS_C);
+                               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);
@@ -3171,6 +3183,7 @@ 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);
@@ -3210,7 +3223,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);
@@ -3254,8 +3267,9 @@ 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);
+                               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);
@@ -3285,24 +3299,18 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
 
        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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
+               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();
 }
 
@@ -3310,29 +3318,24 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
-       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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
-               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();
@@ -3343,30 +3346,39 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
+       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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
+               zval *param, tmp;
+
+               ZVAL_COPY_VALUE(&tmp, params);
                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);
-                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                               param++;
-                       } while (++arg_num <= arg_count);
+               param = EX(extra_args);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+                       zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC);
+                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
+                       if (param) {
+                               while (++arg_num <= arg_count) {
+                                       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++;
+                               }
+                       }
                } else {
-                       do {
-                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                               param++;
-                       } while (++arg_num <= arg_count);
+                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
+                       if (param) {
+                               while (++arg_num <= arg_count) {
+                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                                       param++;
+                               }
+                       }
                }
        } else {
                array_init(params);
@@ -3398,8 +3410,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)
@@ -3409,8 +3421,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)
@@ -3421,9 +3433,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)) {
@@ -3492,7 +3504,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
        } else {
                /* We are not handling overloaded classes right now */
                EX(call) = zend_vm_stack_push_call_frame(
-                       constructor, 0,
+                       constructor, opline->extended_value,
                        RETURN_VALUE_USED(opline) ?
                                (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
                        Z_CE_P(EX_VAR(opline->op1.var)),
@@ -3981,7 +3993,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
-               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -3989,24 +4000,22 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       (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);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               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)) {
@@ -4837,7 +4846,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 */
 }
 
@@ -4963,7 +4972,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();
@@ -4973,7 +4982,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();
@@ -4983,7 +4992,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();
@@ -4994,7 +5003,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();
 }
@@ -5004,7 +5013,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();
 }
@@ -5018,7 +5027,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();
@@ -5029,7 +5038,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();
 }
@@ -5159,28 +5168,24 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                        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;
+                       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)) {
-               zend_call_frame *call = EX(call);
+               zend_execute_data *call = EX(call);
                do {
-                       zval *args = ZEND_CALL_ARG(call, 1);
-
                        /* If the exception was thrown during a function call there might be
                         * arguments pushed to the stack that have to be dtor'ed. */
-                       while (zend_vm_stack_top(TSRMLS_C) != args) {
-                               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
-                               zval_ptr_dtor(stack_zval_p);
-                       }
+                       zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
                        if (call->object) {
                                if (call->flags & ZEND_CALL_CTOR) {
                                        if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
@@ -5192,22 +5197,22 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       EG(argument_stack)->top = (zval*)call;
-                       call = call->prev;
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+                       call = EX(call);
                } while (call);
-               EX(call) = NULL;
        }
 
-       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)) {
@@ -5243,7 +5248,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) {
@@ -5253,14 +5258,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);
@@ -5291,7 +5296,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);
@@ -5405,7 +5410,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) {
@@ -5533,7 +5538,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;
@@ -5552,15 +5557,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);
index f341e19fdb12c5fab8d396abb0a4863c8bda77a6..0534cfd8b1c65efad064491d72779818e6fdf869 100644 (file)
@@ -375,16 +375,28 @@ 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_call_frame *call;
+       zend_execute_data *prev_nested_call;
+       zend_uint call_flags;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -393,19 +405,23 @@ 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);
+               call_flags = EX(flags);
+               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);
 
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
-                               if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
+                               if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -422,10 +438,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                EG(scope) = EX(scope);
                EG(called_scope) = EX(called_scope);
 
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
-
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_op *opline = EX(opline);
                        zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -440,17 +452,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);
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               EG(active_op_array) = &EX(func)->op_array;
                if (UNEXPECTED(EG(exception) != NULL)) {
                        zend_throw_exception_internal(NULL TSRMLS_CC);
                        HANDLE_EXCEPTION_LEAVE();
@@ -462,6 +473,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;
@@ -469,7 +481,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 && (old_execute_data->func->op_array.type == ZEND_USER_FUNCTION || old_execute_data->func->op_array.type == ZEND_EVAL_CODE)) {
                                        if (old_execute_data->symbol_table == symbol_table) {
                                                zend_attach_symbol_table(old_execute_data);
                                        }
@@ -478,10 +490,15 @@ 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();
        }
@@ -509,14 +526,12 @@ static int ZEND_FASTCALL  ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_function *fbc = EX(call)->func;
-       zend_object *object;
-       zend_uint num_args;
-       zend_call_frame *call;
+       zend_execute_data *call = EX(call);
+       zend_function *fbc = call->func;
+       zend_uint call_flags = call->flags;
 
        SAVE_OPLINE();
-       EX(call)->flags |= ZEND_CALL_DONE;
-       object = EX(call)->object;
+       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);
@@ -533,7 +548,7 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        }
        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 */
@@ -548,37 +563,33 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
        }
 
-       if (EXPECTED(EX(call)->num_args == 0)) {
-               EX(call)->num_args = num_args = opline->extended_value;
-       } else {
-               EX(call)->num_args += opline->extended_value;
-               num_args = EX(call)->num_args;
-               zend_vm_stack_adjust_call_frame(&EX(call) TSRMLS_CC);
-       }
+//???
+       call->num_args += opline->extended_value;
+
        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 = ZEND_CALL_ARG(EX(call), 1);
+                       zval *p = ZEND_CALL_ARG(call, 1);
 
-                       for (i = 0; i < num_args; ++i) {
+                       for (i = 0; i < call->num_args; ++i) {
                                zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
                                p++;
                        }
@@ -600,11 +611,16 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
                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);
                }
@@ -614,12 +630,12 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                } 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)) {
@@ -629,40 +645,50 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        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);
                }
@@ -679,8 +705,8 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
 fcall_end_change_scope:
        if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
-                       if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
+               if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
+                       if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -688,7 +714,6 @@ fcall_end_change_scope:
                        }
                }
                if (!Z_DELREF(EG(This))) {
-                       EX(call)->flags &= ~ZEND_CALL_DONE;
                        _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
                } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
                        gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
@@ -699,10 +724,6 @@ fcall_end_change_scope:
        EG(called_scope) = EX(called_scope);
 
 fcall_end:
-       call = EX(call);
-       EX(call) = EX(call)->prev;
-       zend_vm_stack_free_call_frame(call, 1 TSRMLS_CC);
-
        if (UNEXPECTED(EG(exception) != NULL)) {
                zend_throw_exception_internal(NULL TSRMLS_CC);
                if (RETURN_VALUE_USED(opline)) {
@@ -744,7 +765,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;
@@ -771,7 +792,7 @@ send_again:
                                        ZEND_VM_NEXT_OPCODE();
                                }
 
-                               top = zend_vm_stack_top_inc(TSRMLS_C);
+                               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);
@@ -781,6 +802,7 @@ 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);
@@ -820,7 +842,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;
@@ -864,8 +886,9 @@ 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);
+                               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);
@@ -895,24 +918,18 @@ static int ZEND_FASTCALL  ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
 
        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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
+               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();
 }
 
@@ -920,30 +937,39 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
+       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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
+               zval *param, tmp;
+
+               ZVAL_COPY_VALUE(&tmp, params);
                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);
-                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                               param++;
-                       } while (++arg_num <= arg_count);
+               param = EX(extra_args);
+               if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+                       zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC);
+                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
+                       if (param) {
+                               while (++arg_num <= arg_count) {
+                                       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++;
+                               }
+                       }
                } else {
-                       do {
-                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                               param++;
-                       } while (++arg_num <= arg_count);
+                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
+                       if (param) {
+                               while (++arg_num <= arg_count) {
+                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                                       param++;
+                               }
+                       }
                }
        } else {
                array_init(params);
@@ -982,7 +1008,7 @@ static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                /* We are not handling overloaded classes right now */
                EX(call) = zend_vm_stack_push_call_frame(
-                       constructor, 0,
+                       constructor, opline->extended_value,
                        RETURN_VALUE_USED(opline) ?
                                (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
                        Z_CE_P(EX_VAR(opline->op1.var)),
@@ -1044,7 +1070,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 */
 }
 
@@ -1052,7 +1078,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();
@@ -1062,7 +1088,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();
@@ -1072,7 +1098,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();
@@ -1083,7 +1109,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();
 }
@@ -1093,7 +1119,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();
 }
@@ -1107,7 +1133,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();
@@ -1118,7 +1144,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();
 }
@@ -1200,28 +1226,24 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                        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;
+                       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)) {
-               zend_call_frame *call = EX(call);
+               zend_execute_data *call = EX(call);
                do {
-                       zval *args = ZEND_CALL_ARG(call, 1);
-
                        /* If the exception was thrown during a function call there might be
                         * arguments pushed to the stack that have to be dtor'ed. */
-                       while (zend_vm_stack_top(TSRMLS_C) != args) {
-                               zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
-                               zval_ptr_dtor(stack_zval_p);
-                       }
+                       zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
                        if (call->object) {
                                if (call->flags & ZEND_CALL_CTOR) {
                                        if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
@@ -1233,22 +1255,22 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
                                }
                                OBJ_RELEASE(call->object);
                        }
-                       EG(argument_stack)->top = (zval*)call;
-                       call = call->prev;
+                       EX(call) = call->prev_nested_call;
+                       zend_vm_stack_free_call_frame(call TSRMLS_CC);
+                       call = EX(call);
                } while (call);
-               EX(call) = NULL;
        }
 
-       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)) {
@@ -1284,7 +1306,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) {
@@ -1294,14 +1316,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);
@@ -1332,7 +1354,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);
@@ -1366,7 +1388,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;
@@ -1385,15 +1407,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);
@@ -1462,7 +1484,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -1488,7 +1510,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                        STR_FREE(lcname);
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                               Z_FUNC_P(func), opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1508,7 +1530,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1566,7 +1588,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1606,7 +1628,7 @@ static int ZEND_FASTCALL  ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1630,7 +1652,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -1639,29 +1661,24 @@ static int ZEND_FASTCALL  ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
 {
        USE_OPLINE
        zend_uint arg_num = opline->op1.num;
-       zend_uint arg_count = EX(prev_execute_data)->call->num_args;
-       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 = ZEND_CALL_ARG(EX(prev_execute_data)->call, arg_num);
-               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();
@@ -1675,8 +1692,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)
@@ -1686,8 +1703,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)
@@ -1698,9 +1715,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)) {
@@ -1802,7 +1819,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -1829,7 +1846,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                        zval_dtor(free_op2.var);
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                               Z_FUNC_P(func), opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1849,7 +1866,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -1907,7 +1924,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        zval_dtor(free_op2.var);
                        CHECK_EXCEPTION();
@@ -1984,7 +2001,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2011,7 +2028,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                        zval_ptr_dtor_nogc(free_op2.var);
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                               Z_FUNC_P(func), opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2031,7 +2048,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2089,7 +2106,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        zval_ptr_dtor_nogc(free_op2.var);
                        CHECK_EXCEPTION();
@@ -2204,7 +2221,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       fbc, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                /*CHECK_EXCEPTION();*/
                ZEND_VM_NEXT_OPCODE();
@@ -2230,7 +2247,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                        STR_FREE(lcname);
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               Z_FUNC_P(func), 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                               Z_FUNC_P(func), opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2250,7 +2267,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2308,7 +2325,7 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
                        }
 
                        EX(call) = zend_vm_stack_push_call_frame(
-                               fbc, 0, 0, called_scope, object, EX(call) TSRMLS_CC);
+                               fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
 
                        CHECK_EXCEPTION();
                        ZEND_VM_NEXT_OPCODE();
@@ -2654,7 +2671,7 @@ 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();
@@ -2665,11 +2682,11 @@ static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
        }
 
        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);
+       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();
@@ -2942,7 +2959,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
-               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -2950,24 +2966,22 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       (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);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               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)) {
@@ -3751,7 +3765,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();
                        }
@@ -3837,13 +3851,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
        }
 
        if (IS_CONST != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4287,7 +4302,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) {
@@ -4718,7 +4733,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();
                        }
@@ -4804,13 +4819,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
        }
 
        if (IS_CONST != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4972,7 +4988,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) {
@@ -5553,7 +5569,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();
                        }
@@ -5639,13 +5655,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
        }
 
        if (IS_CONST != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -5958,7 +5975,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) {
@@ -6247,7 +6264,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();
                        }
@@ -6333,13 +6350,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
        }
 
        if (IS_CONST != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -6661,7 +6679,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) {
@@ -7077,7 +7095,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();
                        }
@@ -7163,13 +7181,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
        }
 
        if (IS_CONST != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -7185,7 +7204,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))) {
@@ -7209,7 +7228,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 */
                }
        }
@@ -7383,7 +7402,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) {
@@ -7853,7 +7872,7 @@ 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();
@@ -7864,11 +7883,11 @@ static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
        }
 
        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);
+       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();
@@ -8143,7 +8162,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
-               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -8151,24 +8169,22 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       (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);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               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)) {
@@ -9087,7 +9103,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -9400,7 +9416,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) {
@@ -9923,7 +9939,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -10087,7 +10103,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) {
@@ -10760,7 +10776,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -11075,7 +11091,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) {
@@ -11640,7 +11656,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) {
@@ -12147,7 +12163,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -12309,7 +12325,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) {
@@ -12998,18 +13014,18 @@ 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);
        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();
@@ -13019,7 +13035,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 */
@@ -13044,15 +13060,16 @@ 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);
+               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)->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);
+               ZVAL_COPY(arg, varptr);
                zval_ptr_dtor_nogc(free_op1.var);
        }
        CHECK_EXCEPTION();
@@ -13063,7 +13080,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);
@@ -13072,23 +13089,23 @@ 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);
        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);};
@@ -13098,7 +13115,7 @@ 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_ARG_COMPILE_TIME_BOUND) {
@@ -13108,14 +13125,14 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
        }
 
        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);
        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();
@@ -13401,7 +13418,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
-               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -13409,24 +13425,22 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       (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);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               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)) {
@@ -15349,7 +15363,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -15372,7 +15386,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();
                        }
@@ -15458,13 +15472,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
        }
 
        if (IS_VAR != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -16144,7 +16159,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) {
@@ -17577,7 +17592,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
        zval_ptr_dtor_nogc(free_op1.var);
@@ -17601,7 +17616,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();
                        }
@@ -17687,13 +17702,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
        }
 
        if (IS_VAR != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -18126,7 +18142,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) {
@@ -19773,7 +19789,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               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);
@@ -19797,7 +19813,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();
                        }
@@ -19883,13 +19899,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
        }
 
        if (IS_VAR != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -20473,7 +20490,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) {
@@ -21262,7 +21279,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();
                        }
@@ -21348,13 +21365,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
        }
 
        if (IS_VAR != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -21669,7 +21687,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) {
@@ -23143,7 +23161,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op1.var);
 
@@ -23166,7 +23184,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();
                        }
@@ -23252,13 +23270,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
        }
 
        if (IS_VAR != IS_CONST) {
-               if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
+               /* 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);
                }
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, ce, object, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -23688,7 +23707,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) {
@@ -24720,7 +24739,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -25147,7 +25166,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) {
@@ -26094,7 +26113,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -26425,7 +26444,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) {
@@ -27372,7 +27391,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -27703,7 +27722,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) {
@@ -28219,7 +28238,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) {
@@ -29160,7 +29179,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -29488,7 +29507,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) {
@@ -30147,18 +30166,18 @@ 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);
        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();
@@ -30168,7 +30187,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 */
@@ -30193,15 +30212,16 @@ 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);
+               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)->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);
+               ZVAL_COPY(arg, varptr);
 
        }
        CHECK_EXCEPTION();
@@ -30212,7 +30232,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);
@@ -30221,23 +30241,23 @@ 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);
        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();
@@ -30246,7 +30266,7 @@ 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_ARG_COMPILE_TIME_BOUND) {
@@ -30256,14 +30276,14 @@ static int ZEND_FASTCALL  ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        }
 
        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);
        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();
@@ -30536,7 +30556,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                HANDLE_EXCEPTION();
        } else if (EXPECTED(new_op_array != NULL)) {
                zval *return_value = NULL;
-               zend_call_frame *call;
 
                EG(active_op_array) = new_op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -30544,24 +30563,22 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                }
 
                EX(call) = zend_vm_stack_push_call_frame(
-                       (zend_function*)new_op_array, 0, 0, NULL, NULL, EX(call) TSRMLS_CC);
+                       (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);
                }
 
                EG(opline_ptr) = &EX(opline);
-               EG(active_op_array) = EX(op_array);
-               call = EX(call);
-               EX(call) = EX(call)->prev;
-               zend_vm_stack_free((zval*)call TSRMLS_CC);
+               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)) {
@@ -32333,7 +32350,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -32915,7 +32932,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) {
@@ -34376,7 +34393,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_dtor(free_op2.var);
 
@@ -34811,7 +34828,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) {
@@ -36455,7 +36472,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
        zval_ptr_dtor_nogc(free_op2.var);
 
@@ -37041,7 +37058,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) {
@@ -38104,7 +38121,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) {
@@ -39575,7 +39592,7 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
        }
 
        EX(call) = zend_vm_stack_push_call_frame(
-               fbc, 0, 0, called_scope, obj, EX(call) TSRMLS_CC);
+               fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
 
 
        CHECK_EXCEPTION();
@@ -40006,7 +40023,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) {
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 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 22ccb8f2bb9e7828b651b48c025a4a7612abd9b8..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;
@@ -74,10 +76,9 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
 
                fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
 
-               // TODO: fpm_php_trace_dump() has be reimplemented ???
-//???          if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
-//???                  return -1;
-//???          }
+               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
+                       return -1;
+               }
 
                function = l;
 
@@ -132,6 +133,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
                        break;
                }
        }
+#endif
        return 0;
 }
 /* }}} */