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++;
}
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);
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;
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);
}
/* }}} */
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)) {
}
p++;
q++;
+ i++;
}
Z_ARRVAL_P(return_value)->nNumUsed = i;
Z_ARRVAL_P(return_value)->nNumOfElements = i;
/* }}} */
-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++;
}
}
}
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 &&
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;
(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;
}
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);
}
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;
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 &&
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);
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;
}
(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;
}
}
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);
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;
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;
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);
}
/* }}} */
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;
}
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));
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;
}
}
}
- 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);
}
/* }}} */
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
}
}
- 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);
}
/* }}} */
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) {
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) {
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 */
}
}
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);
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));
}
/* }}} */
SET_NODE(opline->op1, param);
opline->op2.opline_num = fcall->arg_num;
SET_UNUSED(opline->op2);
-
- CG(context).used_stack++;
}
/* }}} */
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);
}
/* }}} */
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));
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;
- }
}
/* }}} */
int literals_size;
int current_brk_cont;
int backpatch_count;
- int used_stack;
int in_finally;
HashTable *labels;
} zend_compiler_context;
zend_uint T;
- zend_uint used_stack;
-
zend_brk_cont_element *brk_cont_array;
int last_brk_cont;
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;
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 */
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)
#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
}
}
-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 = "::";
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)
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 {
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");
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);
}
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++;
* ==================
*
* +========================================+
- * | 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;
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);
}
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(); \
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);
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)
{
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;
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 { \
} 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;
}
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)
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;
}
}
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;
}
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:
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: {
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
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;
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,
} 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));
} 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)
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));
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);
/* 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);
}
}
}
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
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 */
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) {
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) {
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);
}
}
- /* 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;
}
}
/* }}} */
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);
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). */
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;
}
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;
/* 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);
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;
}
/* 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;
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;
/* 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;
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;
}
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;
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);
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) {
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);
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();
} 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;
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);
}
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();
}
}
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();
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();
}
}
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();
}
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();
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();
}
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();
}
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();
}
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();
}
}
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();
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);
}
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 */
}
}
- 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++;
}
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);
} 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)) {
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);
}
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) {
}
}
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);
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)) {
/* 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))) {
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 */
}
}
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();
}
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();
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();
{
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 */
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();
{
USE_OPLINE
zend_free_op free_op1;
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
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();
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) {
}
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();
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;
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);
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);
}
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);
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);
{
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();
}
{
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();
{
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);
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)
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)
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)) {
} 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)),
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)) {
}
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)) {
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 */
}
{
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();
{
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();
{
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();
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();
}
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();
}
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();
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();
}
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) {
}
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)) {
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) {
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);
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);
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) {
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;
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);
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);
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) {
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);
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();
} 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;
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);
}
old_execute_data = old_execute_data->prev_execute_data;
}
}
- if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
- zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
+ zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
+ }
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
+
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = prev_nested_call;
}
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
EG(opline_ptr) = NULL;
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_DO_FCALL_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);
}
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 */
}
}
- 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++;
}
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);
}
} 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)) {
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);
}
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) {
}
}
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);
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)) {
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;
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);
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);
}
for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
- zval *arg;
+ zval *arg, *top;
if (UNEXPECTED(EG(exception) != NULL)) {
goto unpack_iter_dtor;
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);
{
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();
}
{
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);
} 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)),
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 */
}
{
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();
{
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();
{
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();
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();
}
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();
}
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();
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();
}
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) {
}
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)) {
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) {
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);
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);
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;
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);
}
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();
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();
}
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();
}
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();
}
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();
}
}
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();
}
{
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();
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)
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)
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)) {
}
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();
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();
}
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();
}
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();
}
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();
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();
}
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();
}
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();
}
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();
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();
}
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();
}
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();
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *value, *top;
+ zval *value, *arg;
SAVE_OPLINE();
}
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();
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)) {
}
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)) {
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();
}
}
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();
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) {
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();
}
}
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();
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) {
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();
}
}
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();
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) {
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();
}
}
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();
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) {
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();
}
}
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();
/* 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))) {
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 */
}
}
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) {
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();
}
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();
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)) {
}
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)) {
}
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();
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) {
}
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);
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) {
}
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);
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) {
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) {
}
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();
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) {
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();
{
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 */
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();
{
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);
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);};
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) {
}
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();
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)) {
}
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)) {
}
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);
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();
}
}
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();
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) {
}
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);
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();
}
}
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();
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) {
}
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);
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();
}
}
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();
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) {
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();
}
}
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();
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) {
}
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);
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();
}
}
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();
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) {
}
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();
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) {
}
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);
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) {
}
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);
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) {
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) {
}
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();
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) {
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();
{
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 */
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();
{
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);
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();
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) {
}
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();
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)) {
}
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)) {
}
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();
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) {
}
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);
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) {
}
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);
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) {
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) {
}
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();
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) {
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%}
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));
}
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);
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;
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;
break;
}
}
+#endif
return 0;
}
/* }}} */