mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Refactoring: merge call_frame and end_execute_data into single data structure. Keep only single copy of each argument on VM stack (previously ZE kept two copies of each arguments for user functions)
This commit is contained in:
parent
0f9d5baba2
commit
c69781393c
16 changed files with 999 additions and 946 deletions
|
@ -142,7 +142,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS
|
||||||
if (Z_REFCOUNTED_P(param_ptr)) {
|
if (Z_REFCOUNTED_P(param_ptr)) {
|
||||||
Z_ADDREF_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++;
|
param_ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -394,10 +394,10 @@ ZEND_FUNCTION(gc_disable)
|
||||||
Get the number of arguments that were passed to the function */
|
Get the number of arguments that were passed to the function */
|
||||||
ZEND_FUNCTION(func_num_args)
|
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) {
|
if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) {
|
||||||
RETURN_LONG(ex->call->num_args);
|
RETURN_LONG(ex->num_args);
|
||||||
} else {
|
} else {
|
||||||
zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
|
zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
|
||||||
RETURN_LONG(-1);
|
RETURN_LONG(-1);
|
||||||
|
@ -412,7 +412,7 @@ ZEND_FUNCTION(func_get_arg)
|
||||||
int arg_count;
|
int arg_count;
|
||||||
zval *arg;
|
zval *arg;
|
||||||
long requested_offset;
|
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) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
|
@ -423,19 +423,24 @@ ZEND_FUNCTION(func_get_arg)
|
||||||
RETURN_FALSE;
|
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");
|
zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_count = ex->call->num_args;
|
arg_count = ex->num_args;
|
||||||
|
|
||||||
if (requested_offset >= arg_count) {
|
if (requested_offset >= arg_count) {
|
||||||
zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
|
zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
|
||||||
RETURN_FALSE;
|
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);
|
RETURN_ZVAL_FAST(arg);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -447,23 +452,25 @@ ZEND_FUNCTION(func_get_args)
|
||||||
zval *p;
|
zval *p;
|
||||||
int arg_count;
|
int arg_count;
|
||||||
int i;
|
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");
|
zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_count = ex->call->num_args;
|
arg_count = ex->num_args;
|
||||||
|
|
||||||
array_init_size(return_value, arg_count);
|
array_init_size(return_value, arg_count);
|
||||||
if (arg_count) {
|
if (arg_count) {
|
||||||
Bucket *q;
|
Bucket *q;
|
||||||
|
|
||||||
p = ZEND_CALL_ARG(ex->call, 1);
|
|
||||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
||||||
|
i = 0;
|
||||||
q = Z_ARRVAL_P(return_value)->arData;
|
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->h = i;
|
||||||
q->key = NULL;
|
q->key = NULL;
|
||||||
if (!Z_ISREF_P(p)) {
|
if (!Z_ISREF_P(p)) {
|
||||||
|
@ -473,6 +480,21 @@ ZEND_FUNCTION(func_get_args)
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
q++;
|
q++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
p = ex->extra_args;
|
||||||
|
}
|
||||||
|
while (i < arg_count) {
|
||||||
|
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++;
|
||||||
}
|
}
|
||||||
Z_ARRVAL_P(return_value)->nNumUsed = i;
|
Z_ARRVAL_P(return_value)->nNumUsed = i;
|
||||||
Z_ARRVAL_P(return_value)->nNumOfElements = i;
|
Z_ARRVAL_P(return_value)->nNumOfElements = i;
|
||||||
|
@ -1954,24 +1976,30 @@ ZEND_FUNCTION(get_defined_constants)
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
static void debug_backtrace_get_args(zend_call_frame *call, zval *arg_array TSRMLS_DC)
|
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zval *p;
|
int num_args = call->num_args;
|
||||||
zval *arg;
|
|
||||||
int arg_count = call->num_args;
|
|
||||||
|
|
||||||
array_init_size(arg_array, arg_count);
|
array_init_size(arg_array, num_args);
|
||||||
if (arg_count > 0) {
|
if (num_args) {
|
||||||
p = ZEND_CALL_ARG(call, 1);
|
int i = 0;
|
||||||
|
zval *p = ZEND_CALL_ARG(call, 1);
|
||||||
|
|
||||||
while (--arg_count >= 0) {
|
if (call->extra_args) {
|
||||||
arg = p++;
|
while (i < call->func->op_array.num_args) {
|
||||||
if (arg) {
|
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
|
||||||
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
|
||||||
add_next_index_zval(arg_array, arg);
|
p++;
|
||||||
} else {
|
i++;
|
||||||
add_next_index_null(arg_array);
|
|
||||||
}
|
}
|
||||||
|
p = call->extra_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < num_args) {
|
||||||
|
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
|
||||||
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
|
||||||
|
p++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2025,7 +2053,7 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||||
|
|
||||||
skip = ptr;
|
skip = ptr;
|
||||||
/* skip internal handler */
|
/* 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 &&
|
||||||
skip->prev_execute_data->opline &&
|
skip->prev_execute_data->opline &&
|
||||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||||
|
@ -2033,8 +2061,8 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||||
skip = skip->prev_execute_data;
|
skip = skip->prev_execute_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip->op_array) {
|
if (skip->func && (skip->func->common.type == ZEND_USER_FUNCTION || skip->func->common.type == ZEND_EVAL_CODE)) {
|
||||||
filename = skip->op_array->filename->val;
|
filename = skip->func->op_array.filename->val;
|
||||||
lineno = skip->opline->lineno;
|
lineno = skip->opline->lineno;
|
||||||
} else {
|
} else {
|
||||||
filename = NULL;
|
filename = NULL;
|
||||||
|
@ -2060,7 +2088,7 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||||
(func->common.function_name ?
|
(func->common.function_name ?
|
||||||
func->common.function_name->val : NULL);
|
func->common.function_name->val : NULL);
|
||||||
} else {
|
} else {
|
||||||
func = (zend_function*)(ptr->op_array);
|
func = ptr->func;
|
||||||
function_name = func && func->common.function_name ?
|
function_name = func && func->common.function_name ?
|
||||||
func->common.function_name->val : NULL;
|
func->common.function_name->val : NULL;
|
||||||
}
|
}
|
||||||
|
@ -2081,7 +2109,7 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||||
class_name = NULL;
|
class_name = NULL;
|
||||||
call_type = 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) {
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
||||||
debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
|
debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
@ -2144,12 +2172,13 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||||
while (prev) {
|
while (prev) {
|
||||||
if (prev->call &&
|
if (prev->call &&
|
||||||
prev->call->func &&
|
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;
|
prev = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (prev->op_array) {
|
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->op_array->filename->val, prev->opline->lineno);
|
zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev = prev->prev_execute_data;
|
prev = prev->prev_execute_data;
|
||||||
|
@ -2201,7 +2230,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
|
|
||||||
skip = ptr;
|
skip = ptr;
|
||||||
/* skip internal handler */
|
/* 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 &&
|
||||||
skip->prev_execute_data->opline &&
|
skip->prev_execute_data->opline &&
|
||||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||||
|
@ -2209,8 +2238,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
skip = skip->prev_execute_data;
|
skip = skip->prev_execute_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip->op_array) {
|
if (skip->func && (skip->func->common.type == ZEND_USER_FUNCTION || skip->func->common.type == ZEND_EVAL_CODE)) {
|
||||||
filename = skip->op_array->filename->val;
|
filename = skip->func->op_array.filename->val;
|
||||||
lineno = skip->opline->lineno;
|
lineno = skip->opline->lineno;
|
||||||
add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename);
|
add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename);
|
||||||
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
|
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
|
||||||
|
@ -2225,13 +2254,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
if (prev->call &&
|
if (prev->call &&
|
||||||
prev->call->func &&
|
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->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
|
!(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
|
||||||
(prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
(prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
||||||
break;
|
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 ???
|
// 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);
|
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2259,7 +2289,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
(func->common.function_name ?
|
(func->common.function_name ?
|
||||||
func->common.function_name->val : NULL);
|
func->common.function_name->val : NULL);
|
||||||
} else {
|
} else {
|
||||||
func = (zend_function*)(ptr->op_array);
|
func = ptr->func;
|
||||||
function_name = func && func->common.function_name ?
|
function_name = func && func->common.function_name ?
|
||||||
func->common.function_name->val : NULL;
|
func->common.function_name->val : NULL;
|
||||||
}
|
}
|
||||||
|
@ -2289,7 +2319,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
||||||
(!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL)) {
|
func->type != ZEND_EVAL_CODE) {
|
||||||
if (ptr->call) {
|
if (ptr->call) {
|
||||||
zval args;
|
zval args;
|
||||||
debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
|
debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
|
||||||
|
@ -2346,7 +2376,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||||
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
|
add_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;
|
include_filename = filename;
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||||
if (closure->func.type == ZEND_USER_FUNCTION) {
|
if (closure->func.type == ZEND_USER_FUNCTION) {
|
||||||
zend_execute_data *ex = EG(current_execute_data);
|
zend_execute_data *ex = EG(current_execute_data);
|
||||||
while (ex) {
|
while (ex) {
|
||||||
if (ex->op_array == &closure->func.op_array) {
|
if (ex->func == &closure->func) {
|
||||||
zend_error(E_ERROR, "Cannot destroy active lambda function");
|
zend_error(E_ERROR, "Cannot destroy active lambda function");
|
||||||
}
|
}
|
||||||
ex = ex->prev_execute_data;
|
ex = ex->prev_execute_data;
|
||||||
|
|
|
@ -97,9 +97,9 @@ ZEND_API zend_compiler_globals compiler_globals;
|
||||||
ZEND_API zend_executor_globals executor_globals;
|
ZEND_API zend_executor_globals executor_globals;
|
||||||
#endif
|
#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);
|
zend_stack_push(&CG(function_call_stack), &fcall);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -182,7 +182,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
|
||||||
CG(context).literals_size = 0;
|
CG(context).literals_size = 0;
|
||||||
CG(context).current_brk_cont = -1;
|
CG(context).current_brk_cont = -1;
|
||||||
CG(context).backpatch_count = 0;
|
CG(context).backpatch_count = 0;
|
||||||
CG(context).used_stack = 0;
|
|
||||||
CG(context).in_finally = 0;
|
CG(context).in_finally = 0;
|
||||||
CG(context).labels = NULL;
|
CG(context).labels = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1949,6 +1948,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
|
||||||
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
|
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_op *opline;
|
zend_op *opline;
|
||||||
|
zend_uint op_number;
|
||||||
zend_function *function;
|
zend_function *function;
|
||||||
zend_string *lcname;
|
zend_string *lcname;
|
||||||
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
|
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
|
||||||
|
@ -1977,14 +1977,14 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
|
||||||
STR_RELEASE(Z_STR(function_name->u.constant));
|
STR_RELEASE(Z_STR(function_name->u.constant));
|
||||||
Z_STR(function_name->u.constant) = lcname;
|
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 = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
opline->opcode = ZEND_INIT_FCALL;
|
opline->opcode = ZEND_INIT_FCALL;
|
||||||
SET_UNUSED(opline->op1);
|
SET_UNUSED(opline->op1);
|
||||||
SET_NODE(opline->op2, function_name);
|
SET_NODE(opline->op2, function_name);
|
||||||
GET_CACHE_SLOT(opline->op2.constant);
|
GET_CACHE_SLOT(opline->op2.constant);
|
||||||
|
|
||||||
zend_push_function_call_entry(function TSRMLS_CC);
|
zend_push_function_call_entry(function, op_number TSRMLS_CC);
|
||||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
|
||||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2035,8 +2035,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
zend_push_function_call_entry(NULL, last_op_number TSRMLS_CC);
|
||||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
|
||||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -2056,8 +2055,10 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC) /* {{{ */
|
||||||
|
|
||||||
void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
|
void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
|
zend_uint op_number;
|
||||||
zend_op *opline;
|
zend_op *opline;
|
||||||
|
|
||||||
|
op_number = get_next_op_number(CG(active_op_array));
|
||||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
if (ns_call) {
|
if (ns_call) {
|
||||||
/* In run-time PHP will check for function with full name and
|
/* In run-time PHP will check for function with full name and
|
||||||
|
@ -2079,8 +2080,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
|
||||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
|
||||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -2477,6 +2477,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
|
||||||
int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
|
int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
znode class_node;
|
znode class_node;
|
||||||
|
zend_uint op_number;
|
||||||
zend_op *opline;
|
zend_op *opline;
|
||||||
|
|
||||||
if (method_name->op_type == IS_CONST) {
|
if (method_name->op_type == IS_CONST) {
|
||||||
|
@ -2497,11 +2498,12 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||||
ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
|
ZEND_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);
|
zend_resolve_class_name(class_name TSRMLS_CC);
|
||||||
class_node = *class_name;
|
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);
|
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
|
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 = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
opline->extended_value = class_node.EA ;
|
|
||||||
}
|
}
|
||||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||||
if (class_node.op_type == IS_CONST) {
|
if (class_node.op_type == IS_CONST) {
|
||||||
|
@ -2524,8 +2526,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||||
SET_NODE(opline->op2, method_name);
|
SET_NODE(opline->op2, method_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
|
||||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
|
||||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||||
return 1; /* Dynamic */
|
return 1; /* Dynamic */
|
||||||
}
|
}
|
||||||
|
@ -2543,6 +2544,9 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
|
||||||
}
|
}
|
||||||
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
|
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
|
||||||
} else {
|
} 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 = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
opline->opcode = ZEND_DO_FCALL;
|
opline->opcode = ZEND_DO_FCALL;
|
||||||
SET_UNUSED(opline->op1);
|
SET_UNUSED(opline->op1);
|
||||||
|
@ -2554,10 +2558,6 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
|
||||||
GET_NODE(result, opline->result);
|
GET_NODE(result, opline->result);
|
||||||
opline->extended_value = fcall->arg_num;
|
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));
|
zend_stack_del_top(&CG(function_call_stack));
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -2666,8 +2666,6 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
|
||||||
SET_NODE(opline->op1, param);
|
SET_NODE(opline->op1, param);
|
||||||
opline->op2.opline_num = fcall->arg_num;
|
opline->op2.opline_num = fcall->arg_num;
|
||||||
SET_UNUSED(opline->op2);
|
SET_UNUSED(opline->op2);
|
||||||
|
|
||||||
CG(context).used_stack++;
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -5578,8 +5576,7 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
|
||||||
SET_NODE(opline->op1, class_type);
|
SET_NODE(opline->op1, class_type);
|
||||||
SET_UNUSED(opline->op2);
|
SET_UNUSED(opline->op2);
|
||||||
|
|
||||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
zend_push_function_call_entry(NULL, new_token->u.op.opline_num TSRMLS_CC);
|
||||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -5771,6 +5768,7 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
|
||||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
|
|
||||||
opline->opcode = ZEND_INIT_FCALL;
|
opline->opcode = ZEND_INIT_FCALL;
|
||||||
|
opline->extended_value = 1;
|
||||||
SET_UNUSED(opline->op1);
|
SET_UNUSED(opline->op1);
|
||||||
opline->op2_type = IS_CONST;
|
opline->op2_type = IS_CONST;
|
||||||
LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
|
LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
|
||||||
|
@ -5800,10 +5798,6 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
|
||||||
SET_UNUSED(opline->op1);
|
SET_UNUSED(opline->op1);
|
||||||
SET_UNUSED(opline->op2);
|
SET_UNUSED(opline->op2);
|
||||||
GET_NODE(result, opline->result);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ typedef struct _zend_compiler_context {
|
||||||
int literals_size;
|
int literals_size;
|
||||||
int current_brk_cont;
|
int current_brk_cont;
|
||||||
int backpatch_count;
|
int backpatch_count;
|
||||||
int used_stack;
|
|
||||||
int in_finally;
|
int in_finally;
|
||||||
HashTable *labels;
|
HashTable *labels;
|
||||||
} zend_compiler_context;
|
} zend_compiler_context;
|
||||||
|
@ -265,8 +264,6 @@ struct _zend_op_array {
|
||||||
|
|
||||||
zend_uint T;
|
zend_uint T;
|
||||||
|
|
||||||
zend_uint used_stack;
|
|
||||||
|
|
||||||
zend_brk_cont_element *brk_cont_array;
|
zend_brk_cont_element *brk_cont_array;
|
||||||
int last_brk_cont;
|
int last_brk_cont;
|
||||||
|
|
||||||
|
@ -336,6 +333,7 @@ union _zend_function {
|
||||||
|
|
||||||
typedef struct _zend_function_call_entry {
|
typedef struct _zend_function_call_entry {
|
||||||
zend_function *fbc;
|
zend_function *fbc;
|
||||||
|
zend_uint op_number;
|
||||||
zend_uint arg_num;
|
zend_uint arg_num;
|
||||||
zend_bool uses_argument_unpacking;
|
zend_bool uses_argument_unpacking;
|
||||||
} zend_function_call_entry;
|
} zend_function_call_entry;
|
||||||
|
@ -353,27 +351,6 @@ typedef struct _list_llist_element {
|
||||||
znode value;
|
znode value;
|
||||||
} list_llist_element;
|
} 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 {
|
typedef enum _vm_frame_kind {
|
||||||
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
|
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
|
||||||
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
|
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
|
||||||
|
@ -383,26 +360,39 @@ typedef enum _vm_frame_kind {
|
||||||
|
|
||||||
struct _zend_execute_data {
|
struct _zend_execute_data {
|
||||||
struct _zend_op *opline; /* executed opline */
|
struct _zend_op *opline; /* executed opline */
|
||||||
zend_op_array *op_array; /* executed op_array */
|
zend_function *func; /* executed op_array */
|
||||||
zend_call_frame *call; /* current call */
|
zend_execute_data *call; /* current call */
|
||||||
zend_object *object; /* current $this */
|
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 *scope; /* function scope (self) */
|
||||||
zend_class_entry *called_scope; /* function called scope (static) */
|
|
||||||
zend_array *symbol_table;
|
zend_array *symbol_table;
|
||||||
void **run_time_cache;
|
void **run_time_cache;
|
||||||
zend_execute_data *prev_execute_data;
|
zend_execute_data *prev_execute_data;
|
||||||
zval *return_value;
|
zval *return_value;
|
||||||
|
zval *extra_args;
|
||||||
vm_frame_kind frame_kind;
|
vm_frame_kind frame_kind;
|
||||||
// TODO: simplify call sequence and remove call_* ???
|
|
||||||
zval old_error_reporting;
|
zval old_error_reporting;
|
||||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||||
zend_object *delayed_exception;
|
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(element) execute_data.element
|
||||||
|
|
||||||
#define EX_VAR_2(ex, n) ((zval*)(((char*)(ex)) + ((int)(n))))
|
#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(n) EX_VAR_2(execute_data, n)
|
||||||
#define EX_VAR_NUM(n) EX_VAR_NUM_2(execute_data, n)
|
#define EX_VAR_NUM(n) EX_VAR_NUM_2(execute_data, n)
|
||||||
|
@ -732,8 +722,8 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
|
||||||
#define ZEND_FETCH_CLASS_DEFAULT 0
|
#define ZEND_FETCH_CLASS_DEFAULT 0
|
||||||
#define ZEND_FETCH_CLASS_SELF 1
|
#define ZEND_FETCH_CLASS_SELF 1
|
||||||
#define ZEND_FETCH_CLASS_PARENT 2
|
#define ZEND_FETCH_CLASS_PARENT 2
|
||||||
#define ZEND_FETCH_CLASS_MAIN 3 /* unused */
|
#define ZEND_FETCH_CLASS_MAIN 3 /* unused ??? */
|
||||||
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused */
|
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused ??? */
|
||||||
#define ZEND_FETCH_CLASS_AUTO 5
|
#define ZEND_FETCH_CLASS_AUTO 5
|
||||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||||
#define ZEND_FETCH_CLASS_STATIC 7
|
#define ZEND_FETCH_CLASS_STATIC 7
|
||||||
|
|
|
@ -525,12 +525,13 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
|
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
|
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
|
||||||
const char *fname = zf->common.function_name->val;
|
const char *fname = zf->common.function_name->val;
|
||||||
const char *fsep;
|
const char *fsep;
|
||||||
const char *fclass;
|
const char *fclass;
|
||||||
|
zval old_arg;
|
||||||
|
|
||||||
if (zf->common.scope) {
|
if (zf->common.scope) {
|
||||||
fsep = "::";
|
fsep = "::";
|
||||||
|
@ -540,11 +541,20 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen
|
||||||
fclass = "";
|
fclass = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr && ptr->op_array) {
|
if (arg && zf->common.type == ZEND_USER_FUNCTION) {
|
||||||
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);
|
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 {
|
} 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);
|
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)
|
static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
|
||||||
|
@ -572,21 +582,21 @@ static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg
|
||||||
if (Z_TYPE_P(arg) == IS_OBJECT) {
|
if (Z_TYPE_P(arg) == IS_OBJECT) {
|
||||||
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
|
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)) {
|
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) {
|
} 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);
|
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) {
|
} else if (cur_arg_info->type_hint) {
|
||||||
if (cur_arg_info->type_hint == IS_ARRAY) {
|
if (cur_arg_info->type_hint == IS_ARRAY) {
|
||||||
ZVAL_DEREF(arg);
|
ZVAL_DEREF(arg);
|
||||||
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
|
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) {
|
} 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)) {
|
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
|
#if ZEND_DEBUG
|
||||||
} else {
|
} else {
|
||||||
|
@ -618,12 +628,12 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
|
||||||
char *class_name;
|
char *class_name;
|
||||||
|
|
||||||
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
|
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) {
|
} else if (cur_arg_info->type_hint) {
|
||||||
if (cur_arg_info->type_hint == IS_ARRAY) {
|
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) {
|
} 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
|
#if ZEND_DEBUG
|
||||||
} else {
|
} else {
|
||||||
zend_error(E_ERROR, "Unknown typehint");
|
zend_error(E_ERROR, "Unknown typehint");
|
||||||
|
@ -635,15 +645,15 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
|
||||||
|
|
||||||
static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
|
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)) ||
|
if (EXPECTED(!(EX(func)->common.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)) {
|
zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
|
||||||
const char *class_name = EX(op_array)->scope ? EX(op_array)->scope->name->val : "";
|
const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : "";
|
||||||
const char *space = EX(op_array)->scope ? "::" : "";
|
const char *space = EX(func)->common.scope ? "::" : "";
|
||||||
const char *func_name = EX(op_array)->function_name ? EX(op_array)->function_name->val : "main";
|
const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main";
|
||||||
zend_execute_data *ptr = EX(prev_execute_data);
|
zend_execute_data *ptr = EX(prev_execute_data);
|
||||||
|
|
||||||
if(ptr && ptr->op_array) {
|
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->op_array->filename->val, ptr->opline->lineno);
|
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 {
|
} else {
|
||||||
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
|
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
|
||||||
}
|
}
|
||||||
|
@ -1495,9 +1505,9 @@ void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{
|
||||||
|
|
||||||
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
|
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 *cv = EX_VAR_NUM(0);
|
||||||
zval *end = cv + EX(op_array)->last_var;
|
zval *end = cv + EX(func)->op_array.last_var;
|
||||||
do {
|
do {
|
||||||
zval_ptr_dtor(cv);
|
zval_ptr_dtor(cv);
|
||||||
cv++;
|
cv++;
|
||||||
|
@ -1517,104 +1527,22 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
|
||||||
* ==================
|
* ==================
|
||||||
*
|
*
|
||||||
* +========================================+
|
* +========================================+
|
||||||
* | zend_execute_data |<---+
|
* EG(current_execute_data) -> | 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) |----+
|
|
||||||
* +----------------------------------------+
|
* +----------------------------------------+
|
||||||
* 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-1] |
|
||||||
* | VAR[op_array->last_var] |
|
* | VAR[op_array->last_var] |
|
||||||
* | ... |
|
* | ... |
|
||||||
* | VAR[op_array->last_var+op_array->T-1] |
|
* | 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;
|
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
|
||||||
|
ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
|
||||||
/*
|
ZEND_ASSERT(EX(called_scope) == EG(called_scope));
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
EX(return_value) = return_value;
|
EX(return_value) = return_value;
|
||||||
EX(frame_kind) = frame_kind;
|
EX(frame_kind) = frame_kind;
|
||||||
|
@ -1624,23 +1552,32 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||||
|
|
||||||
EG(opline_ptr) = &EX(opline);
|
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(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(func) = (zend_function*)op_array;
|
||||||
EX(object) = Z_OBJ(EG(This));
|
|
||||||
EX(scope) = EG(scope);
|
EX(scope) = EG(scope);
|
||||||
EX(called_scope) = EG(called_scope);
|
|
||||||
EX(symbol_table) = EG(active_symbol_table);
|
EX(symbol_table) = EG(active_symbol_table);
|
||||||
|
|
||||||
if (EX(symbol_table)) {
|
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||||
zend_attach_symbol_table(execute_data);
|
zend_attach_symbol_table(execute_data);
|
||||||
} else {
|
} else {
|
||||||
do {
|
|
||||||
/* Initialize CV variables */
|
|
||||||
zval *var = EX_VAR_NUM(0);
|
|
||||||
zval *end = var + op_array->last_var;
|
|
||||||
|
|
||||||
while (var != end) {
|
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 (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);
|
||||||
|
|
||||||
|
do {
|
||||||
ZVAL_UNDEF(var);
|
ZVAL_UNDEF(var);
|
||||||
var++;
|
var++;
|
||||||
|
} while (var != end);
|
||||||
}
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -1659,64 +1596,120 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||||
}
|
}
|
||||||
EX(run_time_cache) = op_array->run_time_cache;
|
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;
|
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;
|
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;
|
zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
|
||||||
return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
|
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_execute_data *new_call;
|
||||||
zend_call_frame *new_call;
|
int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
|
||||||
zend_vm_stack p = EG(argument_stack);
|
|
||||||
|
|
||||||
zend_vm_stack_extend(ZEND_CALL_FRAME_SLOT + call->num_args TSRMLS_CC);
|
/* copy call frame into new stack segment */
|
||||||
|
zend_vm_stack_extend(used_stack TSRMLS_CC);
|
||||||
new_call = (zend_call_frame*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
|
new_call = (zend_execute_data*)EG(argument_stack)->top;
|
||||||
|
EG(argument_stack)->top += used_stack;
|
||||||
*new_call = *call;
|
*new_call = *call;
|
||||||
EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT + call->num_args;
|
if (passed_args) {
|
||||||
count = call->num_args;
|
zval *src = ZEND_CALL_ARG(call, 1);
|
||||||
while (count-- > 0) {
|
zval *dst = ZEND_CALL_ARG(new_call, 1);
|
||||||
zval *data = --p->top;
|
do {
|
||||||
ZVAL_COPY_VALUE(ZEND_CALL_ARG(new_call, count), data);
|
ZVAL_COPY_VALUE(dst, src);
|
||||||
|
passed_args--;
|
||||||
|
src++;
|
||||||
|
dst++;
|
||||||
|
} while (passed_args);
|
||||||
|
}
|
||||||
|
|
||||||
if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
|
/* delete old call_frame from previous stack segment */
|
||||||
zend_vm_stack r = p;
|
EG(argument_stack)->prev->top = (zval*)call;
|
||||||
|
|
||||||
EG(argument_stack)->prev = p->prev;
|
/* delete previous stack segment if it becames empty */
|
||||||
p = p->prev;
|
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);
|
efree(r);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return new_call;
|
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)
|
if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
|
||||||
|| UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
|
EG(argument_stack)->top += additional_args;
|
||||||
*call = zend_vm_stack_copy_call_frame(*call TSRMLS_CC);
|
} else {
|
||||||
|
*call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
#define ZEND_VM_NEXT_OPCODE() \
|
#define ZEND_VM_NEXT_OPCODE() \
|
||||||
CHECK_SYMBOL_TABLES() \
|
CHECK_SYMBOL_TABLES() \
|
||||||
ZEND_VM_INC_OPCODE(); \
|
ZEND_VM_INC_OPCODE(); \
|
||||||
|
|
|
@ -35,7 +35,8 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
|
||||||
void init_executor(TSRMLS_D);
|
void init_executor(TSRMLS_D);
|
||||||
void shutdown_executor(TSRMLS_D);
|
void shutdown_executor(TSRMLS_D);
|
||||||
void shutdown_destructors(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 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_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 void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
|
||||||
|
@ -48,7 +49,7 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
|
||||||
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
|
ZEND_API 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 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)
|
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
|
||||||
{
|
{
|
||||||
|
@ -149,7 +150,7 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s
|
||||||
ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
|
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! */
|
/* 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 {
|
struct _zend_vm_stack {
|
||||||
zval *top;
|
zval *top;
|
||||||
|
@ -157,8 +158,11 @@ struct _zend_vm_stack {
|
||||||
zend_vm_stack prev;
|
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) \
|
#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) \
|
#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -169,10 +173,10 @@ struct _zend_vm_stack {
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
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->top = ZEND_VM_STACK_ELEMETS(page);
|
||||||
page->end = page->top + count;
|
page->end = (zval*)page + count;
|
||||||
page->prev = NULL;
|
page->prev = NULL;
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
@ -180,6 +184,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
||||||
static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
|
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) = 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_destroy(TSRMLS_D)
|
||||||
|
@ -195,90 +200,87 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
|
||||||
|
|
||||||
static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
|
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);
|
p->prev = EG(argument_stack);
|
||||||
EG(argument_stack) = p;
|
EG(argument_stack) = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_always_inline zval *zend_vm_stack_top(TSRMLS_D)
|
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)
|
||||||
{
|
{
|
||||||
return EG(argument_stack)->top;
|
int used_stack = ZEND_CALL_FRAME_SLOT;
|
||||||
}
|
zend_execute_data *call;
|
||||||
|
|
||||||
static zend_always_inline zval *zend_vm_stack_top_inc(TSRMLS_D)
|
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);
|
||||||
return EG(argument_stack)->top++;
|
} else {
|
||||||
|
used_stack += num_args;
|
||||||
}
|
}
|
||||||
|
ZEND_VM_STACK_GROW_IF_NEEDED(used_stack);
|
||||||
static zend_always_inline void zend_vm_stack_push(zval *ptr TSRMLS_DC)
|
call = (zend_execute_data*)EG(argument_stack)->top;
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
zend_call_frame * call = (zend_call_frame*)EG(argument_stack)->top;
|
|
||||||
call->func = func;
|
call->func = func;
|
||||||
call->num_args = num_args;
|
call->num_args = 0; //??? num_args;
|
||||||
call->flags = flags;
|
call->flags = flags;
|
||||||
call->called_scope = called_scope;
|
call->called_scope = called_scope;
|
||||||
call->object = object;
|
call->object = object;
|
||||||
call->prev = prev;
|
call->prev_nested_call = prev;
|
||||||
EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT;
|
call->extra_args = NULL;
|
||||||
|
EG(argument_stack)->top += used_stack;
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
|
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zval *ret;
|
if (UNEXPECTED(call->extra_args != NULL)) {
|
||||||
int count = (size + (sizeof(zval) - 1)) / sizeof(zval);
|
zval *p = call->extra_args + (call->num_args - call->func->op_array.num_args);
|
||||||
|
zval *end = call->extra_args;
|
||||||
ZEND_VM_STACK_GROW_IF_NEEDED(count);
|
do {
|
||||||
ret = (void*)EG(argument_stack)->top;
|
p--;
|
||||||
EG(argument_stack)->top += count;
|
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||||
return ret;
|
} while (p != end);
|
||||||
}
|
efree(end);
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
zend_uint num_args = call->num_args;
|
||||||
|
|
||||||
if (num_args > 0) {
|
if (num_args > 0) {
|
||||||
zval *p = ZEND_CALL_ARG(call, num_args + 1);
|
zval *p;
|
||||||
zval *end = p - num_args;
|
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 {
|
do {
|
||||||
p--;
|
p--;
|
||||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||||
} while (p != end);
|
} 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 {
|
} else {
|
||||||
zend_vm_stack_free((zval*)call TSRMLS_CC);
|
EG(argument_stack)->top = (zval*)call;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,6 @@ void init_executor(TSRMLS_D) /* {{{ */
|
||||||
EG(error_handling) = EH_NORMAL;
|
EG(error_handling) = EH_NORMAL;
|
||||||
|
|
||||||
zend_vm_stack_init(TSRMLS_C);
|
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);
|
zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0);
|
||||||
GC_REFCOUNT(&EG(symbol_table)) = 1;
|
GC_REFCOUNT(&EG(symbol_table)) = 1;
|
||||||
|
@ -401,10 +400,11 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||||
func = EG(current_execute_data)->call->func;
|
func = EG(current_execute_data)->call->func;
|
||||||
} else {
|
} else {
|
||||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
func = EG(current_execute_data)->func;
|
||||||
}
|
}
|
||||||
switch (func->type) {
|
switch (func->type) {
|
||||||
case ZEND_USER_FUNCTION:
|
case ZEND_USER_FUNCTION:
|
||||||
|
@ -436,7 +436,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||||
func = EG(current_execute_data)->call->func;
|
func = EG(current_execute_data)->call->func;
|
||||||
} else {
|
} else {
|
||||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
func = EG(current_execute_data)->func;
|
||||||
}
|
}
|
||||||
switch (func->type) {
|
switch (func->type) {
|
||||||
case ZEND_USER_FUNCTION: {
|
case ZEND_USER_FUNCTION: {
|
||||||
|
@ -696,7 +696,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
EX(object) = Z_OBJ(EG(This));
|
EX(object) = Z_OBJ(EG(This));
|
||||||
EX(scope) = EG(scope);
|
EX(scope) = EG(scope);
|
||||||
EX(called_scope) = EG(called_scope);
|
EX(called_scope) = EG(called_scope);
|
||||||
EX(op_array) = NULL;
|
EX(func) = NULL;
|
||||||
EX(opline) = NULL;
|
EX(opline) = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* This only happens when we're called outside any execute()'s
|
/* This only happens when we're called outside any execute()'s
|
||||||
|
@ -734,8 +734,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
STR_RELEASE(callable_name);
|
STR_RELEASE(callable_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_VM_STACK_GROW_IF_NEEDED(ZEND_CALL_FRAME_SLOT + fci->param_count);
|
|
||||||
|
|
||||||
func = fci_cache->function_handler;
|
func = fci_cache->function_handler;
|
||||||
EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
|
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;
|
calling_scope = fci_cache->calling_scope;
|
||||||
|
@ -783,12 +781,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
|
|
||||||
if (fci->no_separation &&
|
if (fci->no_separation &&
|
||||||
!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
|
!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
|
||||||
if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
|
if (i) {
|
||||||
/* hack to clean up the stack */
|
/* hack to clean up the stack */
|
||||||
ZVAL_LONG(&tmp, i);
|
EX(call)->num_args = i;
|
||||||
zend_vm_stack_push(&tmp TSRMLS_CC);
|
zend_vm_stack_free_args(EX(call) TSRMLS_CC);
|
||||||
zend_vm_stack_free_call_frame(EX(call), 0 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",
|
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
||||||
i+1,
|
i+1,
|
||||||
|
@ -810,24 +808,26 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
} else if (Z_REFCOUNTED(fci->params[i])) {
|
} else if (Z_REFCOUNTED(fci->params[i])) {
|
||||||
Z_ADDREF(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]) &&
|
} else if (Z_ISREF(fci->params[i]) &&
|
||||||
/* don't separate references for __call */
|
/* don't separate references for __call */
|
||||||
(func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
(func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||||
param = &tmp;
|
param = &tmp;
|
||||||
|
param = ZEND_CALL_ARG(EX(call), i+1);
|
||||||
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
|
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
|
||||||
} else {
|
} else {
|
||||||
param = &tmp;
|
param = ZEND_CALL_ARG(EX(call), i+1);
|
||||||
ZVAL_COPY(param, &fci->params[i]);
|
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(scope) = calling_scope;
|
||||||
EG(called_scope) = called_scope;
|
EG(called_scope) = called_scope;
|
||||||
if (!fci->object ||
|
if (!fci->object ||
|
||||||
(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||||
Z_OBJ(EG(This)) = NULL;
|
Z_OBJ(EG(This)) = EX(call)->object = NULL;
|
||||||
} else {
|
} else {
|
||||||
Z_OBJ(EG(This)) = fci->object;
|
Z_OBJ(EG(This)) = fci->object;
|
||||||
Z_ADDREF(EG(This));
|
Z_ADDREF(EG(This));
|
||||||
|
@ -873,6 +873,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
} else {
|
} else {
|
||||||
zend_execute_internal(&execute_data, fci TSRMLS_CC);
|
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,
|
/* We shouldn't fix bad extensions here,
|
||||||
because it can break proper ones (Bug #34045)
|
because it can break proper ones (Bug #34045)
|
||||||
if (!EX(function_state).function->common.return_reference)
|
if (!EX(function_state).function->common.return_reference)
|
||||||
|
@ -908,7 +911,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||||
ZVAL_UNDEF(fci->retval);
|
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))) {
|
if (Z_OBJ(EG(This))) {
|
||||||
zval_ptr_dtor(&EG(This));
|
zval_ptr_dtor(&EG(This));
|
||||||
|
@ -1093,6 +1096,10 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
|
||||||
|
|
||||||
zend_try {
|
zend_try {
|
||||||
ZVAL_UNDEF(&local_retval);
|
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_execute(new_op_array, &local_retval TSRMLS_CC);
|
||||||
} zend_catch {
|
} zend_catch {
|
||||||
destroy_op_array(new_op_array TSRMLS_CC);
|
destroy_op_array(new_op_array TSRMLS_CC);
|
||||||
|
@ -1596,15 +1603,17 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
|
||||||
|
|
||||||
/* Search for last called user function */
|
/* Search for last called user function */
|
||||||
ex = EG(current_execute_data);
|
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;
|
ex = ex->prev_execute_data;
|
||||||
}
|
}
|
||||||
if (ex && ex->symbol_table) {
|
if (!ex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ex->symbol_table) {
|
||||||
EG(active_symbol_table) = ex->symbol_table;
|
EG(active_symbol_table) = ex->symbol_table;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex && ex->op_array) {
|
|
||||||
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
|
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
|
||||||
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
|
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
|
||||||
EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
|
EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
|
||||||
|
@ -1612,17 +1621,16 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
|
||||||
EG(active_symbol_table) = emalloc(sizeof(zend_array));
|
EG(active_symbol_table) = emalloc(sizeof(zend_array));
|
||||||
GC_REFCOUNT(EG(active_symbol_table)) = 0;
|
GC_REFCOUNT(EG(active_symbol_table)) = 0;
|
||||||
GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
|
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);
|
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));*/
|
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
|
||||||
}
|
}
|
||||||
ex->symbol_table = EG(active_symbol_table);
|
ex->symbol_table = EG(active_symbol_table);
|
||||||
for (i = 0; i < ex->op_array->last_var; i++) {
|
for (i = 0; i < ex->func->op_array.last_var; i++) {
|
||||||
zval zv;
|
zval zv;
|
||||||
|
|
||||||
ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
|
ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
|
||||||
zend_hash_add_new(&EG(active_symbol_table)->ht,
|
zend_hash_add_new(&EG(active_symbol_table)->ht,
|
||||||
ex->op_array->vars[i], &zv);
|
ex->func->op_array.vars[i], &zv);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1631,7 +1639,7 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
|
||||||
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
||||||
{
|
{
|
||||||
int i;
|
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;
|
HashTable *ht = &execute_data->symbol_table->ht;
|
||||||
|
|
||||||
/* copy real values from symbol table into CV slots and create
|
/* copy real values from symbol table into CV slots and create
|
||||||
|
@ -1662,7 +1670,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
|
||||||
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
||||||
{
|
{
|
||||||
int i;
|
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;
|
HashTable *ht = &execute_data->symbol_table->ht;
|
||||||
|
|
||||||
/* copy real values from CV slots into symbol table */
|
/* copy real values from CV slots into symbol table */
|
||||||
|
@ -1682,7 +1690,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS
|
||||||
if (!EG(active_symbol_table)) {
|
if (!EG(active_symbol_table)) {
|
||||||
int i;
|
int i;
|
||||||
zend_execute_data *execute_data = EG(current_execute_data);
|
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);
|
zend_ulong h = STR_HASH_VAL(name);
|
||||||
|
|
||||||
if (op_array) {
|
if (op_array) {
|
||||||
|
@ -1715,7 +1723,7 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int
|
||||||
if (!EG(active_symbol_table)) {
|
if (!EG(active_symbol_table)) {
|
||||||
int i;
|
int i;
|
||||||
zend_execute_data *execute_data = EG(current_execute_data);
|
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);
|
zend_ulong h = zend_hash_func(name, len);
|
||||||
|
|
||||||
if (op_array) {
|
if (op_array) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC
|
||||||
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
|
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_execute_data *execute_data = 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 (generator->send_target) {
|
if (generator->send_target) {
|
||||||
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
|
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
|
||||||
|
@ -75,23 +75,13 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any backed up stack arguments */
|
|
||||||
{
|
|
||||||
zval *ptr = generator->stack->top - 1;
|
|
||||||
zval *end = zend_vm_stack_frame_base(execute_data);
|
|
||||||
|
|
||||||
for (; ptr >= end; --ptr) {
|
|
||||||
zval_ptr_dtor((zval*) ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If yield was used as a function argument there may be active
|
/* If yield was used as a function argument there may be active
|
||||||
* method calls those objects need to be freed */
|
* method calls those objects need to be freed */
|
||||||
while (execute_data->call) {
|
while (execute_data->call) {
|
||||||
if (execute_data->call->object) {
|
if (execute_data->call->object) {
|
||||||
OBJ_RELEASE(execute_data->call->object);
|
OBJ_RELEASE(execute_data->call->object);
|
||||||
}
|
}
|
||||||
execute_data->call = execute_data->call->prev;
|
execute_data->call = execute_data->call->prev_nested_call;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -110,7 +100,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||||
|
|
||||||
if (generator->execute_data) {
|
if (generator->execute_data) {
|
||||||
zend_execute_data *execute_data = 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) {
|
if (!execute_data->symbol_table) {
|
||||||
zend_free_compiled_variables(execute_data TSRMLS_CC);
|
zend_free_compiled_variables(execute_data TSRMLS_CC);
|
||||||
|
@ -128,22 +118,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have added an additional stack frame in prev_execute_data, so we
|
zend_vm_stack_free_extra_args(generator->execute_data TSRMLS_CC);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some cleanups are only necessary if the generator was closued
|
/* Some cleanups are only necessary if the generator was closued
|
||||||
* before it could finish execution (reach a return statement). */
|
* before it could finish execution (reach a return statement). */
|
||||||
|
@ -157,6 +132,10 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||||
efree(op_array);
|
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);
|
efree(generator->stack);
|
||||||
generator->execute_data = NULL;
|
generator->execute_data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -170,18 +149,18 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||||
zend_uint op_num, finally_op_num;
|
zend_uint op_num, finally_op_num;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!ex || !ex->op_array->has_finally_block) {
|
if (!ex || !ex->func->op_array.has_finally_block) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -1 required because we want the last run opcode, not the
|
/* -1 required because we want the last run opcode, not the
|
||||||
* next to-be-run one. */
|
* 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 */
|
/* Find next finally block */
|
||||||
finally_op_num = 0;
|
finally_op_num = 0;
|
||||||
for (i = 0; i < ex->op_array->last_try_catch; i++) {
|
for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
|
||||||
zend_try_catch_element *try_catch = &ex->op_array->try_catch_array[i];
|
zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
|
||||||
|
|
||||||
if (op_num < try_catch->try_op) {
|
if (op_num < try_catch->try_op) {
|
||||||
break;
|
break;
|
||||||
|
@ -195,7 +174,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||||
/* If a finally block was found we jump directly to it and
|
/* If a finally block was found we jump directly to it and
|
||||||
* resume the generator. */
|
* resume the generator. */
|
||||||
if (finally_op_num) {
|
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;
|
ex->fast_ret = NULL;
|
||||||
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
|
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
|
||||||
zend_generator_resume(generator TSRMLS_CC);
|
zend_generator_resume(generator TSRMLS_CC);
|
||||||
|
@ -287,7 +266,7 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
|
||||||
opline_ptr = EG(opline_ptr);
|
opline_ptr = EG(opline_ptr);
|
||||||
current_symbol_table = EG(active_symbol_table);
|
current_symbol_table = EG(active_symbol_table);
|
||||||
EG(active_symbol_table) = NULL;
|
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(active_symbol_table) = current_symbol_table;
|
||||||
EG(current_execute_data) = current_execute_data;
|
EG(current_execute_data) = current_execute_data;
|
||||||
EG(opline_ptr) = opline_ptr;
|
EG(opline_ptr) = opline_ptr;
|
||||||
|
@ -299,8 +278,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save execution context in generator object. */
|
/* 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);
|
generator = (zend_generator *) Z_OBJ_P(return_value);
|
||||||
|
execute_data->prev_execute_data = NULL;
|
||||||
generator->execute_data = execute_data;
|
generator->execute_data = execute_data;
|
||||||
generator->stack = EG(argument_stack);
|
generator->stack = EG(argument_stack);
|
||||||
EG(argument_stack) = current_stack;
|
EG(argument_stack) = current_stack;
|
||||||
|
@ -342,13 +321,14 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
|
||||||
zend_class_entry *original_scope = EG(scope);
|
zend_class_entry *original_scope = EG(scope);
|
||||||
zend_class_entry *original_called_scope = EG(called_scope);
|
zend_class_entry *original_called_scope = EG(called_scope);
|
||||||
zend_vm_stack original_stack = EG(argument_stack);
|
zend_vm_stack original_stack = EG(argument_stack);
|
||||||
|
zend_execute_data *prev_execute_data;
|
||||||
|
|
||||||
original_This = Z_OBJ(EG(This));
|
original_This = Z_OBJ(EG(This));
|
||||||
|
|
||||||
/* Set executor globals */
|
/* Set executor globals */
|
||||||
EG(current_execute_data) = generator->execute_data;
|
EG(current_execute_data) = generator->execute_data;
|
||||||
EG(opline_ptr) = &generator->execute_data->opline;
|
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;
|
EG(active_symbol_table) = generator->execute_data->symbol_table;
|
||||||
Z_OBJ(EG(This)) = generator->execute_data->object;
|
Z_OBJ(EG(This)) = generator->execute_data->object;
|
||||||
EG(scope) = generator->execute_data->scope;
|
EG(scope) = generator->execute_data->scope;
|
||||||
|
@ -357,17 +337,32 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
|
||||||
|
|
||||||
/* We want the backtrace to look as if the generator function was
|
/* We want the backtrace to look as if the generator function was
|
||||||
* called from whatever method we are current running (e.g. next()).
|
* called from whatever method we are current running (e.g. next()).
|
||||||
* The first prev_execute_data contains an additional stack frame,
|
* So we have to link generator call frame with caller call frames */
|
||||||
* which makes the generator function show up in the backtrace and
|
|
||||||
* makes the arguments available to func_get_args(). So we have to
|
prev_execute_data = original_execute_data;
|
||||||
* set the prev_execute_data of that prev_execute_data :) */
|
if (prev_execute_data &&
|
||||||
generator->execute_data->prev_execute_data->prev_execute_data = original_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 */
|
/* Resume execution */
|
||||||
generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
|
generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
|
||||||
zend_execute_ex(generator->execute_data TSRMLS_CC);
|
zend_execute_ex(generator->execute_data TSRMLS_CC);
|
||||||
generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;
|
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 */
|
/* Restore executor globals */
|
||||||
EG(current_execute_data) = original_execute_data;
|
EG(current_execute_data) = original_execute_data;
|
||||||
EG(opline_ptr) = original_opline_ptr;
|
EG(opline_ptr) = original_opline_ptr;
|
||||||
|
@ -669,7 +664,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
|
||||||
return NULL;
|
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);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
|
||||||
|
|
||||||
op_array->T = 0;
|
op_array->T = 0;
|
||||||
|
|
||||||
op_array->used_stack = 0;
|
|
||||||
|
|
||||||
op_array->function_name = NULL;
|
op_array->function_name = NULL;
|
||||||
op_array->filename = zend_get_compiled_filename(TSRMLS_C);
|
op_array->filename = zend_get_compiled_filename(TSRMLS_C);
|
||||||
op_array->doc_comment = NULL;
|
op_array->doc_comment = NULL;
|
||||||
|
|
|
@ -1772,7 +1772,8 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
|
||||||
ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
{
|
{
|
||||||
vm_frame_kind frame_kind = EX(frame_kind);
|
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);
|
EG(current_execute_data) = EX(prev_execute_data);
|
||||||
|
|
||||||
|
@ -1781,19 +1782,23 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||||
zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
|
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) {
|
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
|
||||||
zval_ptr_dtor((zval*)EX(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);
|
execute_data = EG(current_execute_data);
|
||||||
|
EX(call) = prev_nested_call;
|
||||||
EG(opline_ptr) = &EX(opline);
|
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);
|
EG(active_symbol_table) = EX(symbol_table);
|
||||||
|
|
||||||
if (Z_OBJ(EG(This))) {
|
if (Z_OBJ(EG(This))) {
|
||||||
if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
|
if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
|
||||||
if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
|
if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
|
||||||
Z_DELREF(EG(This));
|
Z_DELREF(EG(This));
|
||||||
}
|
}
|
||||||
if (Z_REFCOUNT(EG(This)) == 1) {
|
if (Z_REFCOUNT(EG(This)) == 1) {
|
||||||
|
@ -1810,10 +1815,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
EG(scope) = EX(scope);
|
EG(scope) = EX(scope);
|
||||||
EG(called_scope) = EX(called_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)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
zend_op *opline = EX(opline);
|
zend_op *opline = EX(opline);
|
||||||
zend_throw_exception_internal(NULL TSRMLS_CC);
|
zend_throw_exception_internal(NULL TSRMLS_CC);
|
||||||
|
@ -1828,17 +1829,16 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
ZEND_VM_LEAVE();
|
ZEND_VM_LEAVE();
|
||||||
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
|
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
|
||||||
zend_detach_symbol_table(execute_data);
|
zend_detach_symbol_table(execute_data);
|
||||||
destroy_op_array(EX(op_array) TSRMLS_CC);
|
destroy_op_array(&EX(func)->op_array TSRMLS_CC);
|
||||||
efree(EX(op_array));
|
efree(EX(func));
|
||||||
zend_vm_stack_free((char*)execute_data TSRMLS_CC);
|
prev_nested_call = EX(prev_nested_call);
|
||||||
|
zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
|
||||||
|
|
||||||
execute_data = EG(current_execute_data);
|
execute_data = EG(current_execute_data);
|
||||||
|
EX(call) = prev_nested_call;
|
||||||
zend_attach_symbol_table(execute_data);
|
zend_attach_symbol_table(execute_data);
|
||||||
EG(opline_ptr) = &EX(opline);
|
EG(opline_ptr) = &EX(opline);
|
||||||
EG(active_op_array) = EX(op_array);
|
EG(active_op_array) = &EX(func)->op_array;
|
||||||
call = EX(call);
|
|
||||||
EX(call) = EX(call)->prev;
|
|
||||||
zend_vm_stack_free((zval*)call TSRMLS_CC);
|
|
||||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
zend_throw_exception_internal(NULL TSRMLS_CC);
|
zend_throw_exception_internal(NULL TSRMLS_CC);
|
||||||
HANDLE_EXCEPTION_LEAVE();
|
HANDLE_EXCEPTION_LEAVE();
|
||||||
|
@ -1850,6 +1850,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
} else {
|
} else {
|
||||||
if (frame_kind == VM_FRAME_TOP_FUNCTION) {
|
if (frame_kind == VM_FRAME_TOP_FUNCTION) {
|
||||||
i_free_compiled_variables(execute_data TSRMLS_CC);
|
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) */ {
|
} else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
|
||||||
zend_array *symbol_table = EX(symbol_table);
|
zend_array *symbol_table = EX(symbol_table);
|
||||||
zend_execute_data *old_execute_data;
|
zend_execute_data *old_execute_data;
|
||||||
|
@ -1857,7 +1858,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
zend_detach_symbol_table(execute_data);
|
zend_detach_symbol_table(execute_data);
|
||||||
old_execute_data = EX(prev_execute_data);
|
old_execute_data = EX(prev_execute_data);
|
||||||
while (old_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) {
|
if (old_execute_data->symbol_table == symbol_table) {
|
||||||
zend_attach_symbol_table(old_execute_data);
|
zend_attach_symbol_table(old_execute_data);
|
||||||
}
|
}
|
||||||
|
@ -1866,10 +1867,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||||
old_execute_data = old_execute_data->prev_execute_data;
|
old_execute_data = old_execute_data->prev_execute_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
|
if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
|
||||||
zval_ptr_dtor((zval*)EX(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;
|
EG(opline_ptr) = NULL;
|
||||||
ZEND_VM_RETURN();
|
ZEND_VM_RETURN();
|
||||||
}
|
}
|
||||||
|
@ -2255,7 +2261,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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_OP2();
|
||||||
FREE_OP1_IF_VAR();
|
FREE_OP1_IF_VAR();
|
||||||
|
@ -2279,7 +2285,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
|
||||||
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
|
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
|
||||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
|
||||||
} else {
|
} 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)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
HANDLE_EXCEPTION();
|
HANDLE_EXCEPTION();
|
||||||
}
|
}
|
||||||
|
@ -2365,13 +2371,14 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OP1_TYPE != IS_CONST) {
|
if (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);
|
ce = EG(called_scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -2398,7 +2405,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();*/
|
/*CHECK_EXCEPTION();*/
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -2425,7 +2432,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||||
FREE_OP2();
|
FREE_OP2();
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -2445,7 +2452,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -2503,7 +2510,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
FREE_OP2();
|
||||||
CHECK_EXCEPTION();
|
CHECK_EXCEPTION();
|
||||||
|
@ -2544,7 +2551,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
@ -2568,7 +2575,7 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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();
|
FREE_OP2();
|
||||||
|
|
||||||
|
@ -2578,14 +2585,12 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
|
||||||
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_function *fbc = EX(call)->func;
|
zend_execute_data *call = EX(call);
|
||||||
zend_object *object;
|
zend_function *fbc = call->func;
|
||||||
zend_uint num_args;
|
zend_uint call_flags = call->flags;
|
||||||
zend_call_frame *call;
|
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
EX(call)->flags |= ZEND_CALL_DONE;
|
call->flags |= ZEND_CALL_DONE;
|
||||||
object = EX(call)->object;
|
|
||||||
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
||||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 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);
|
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
|
||||||
|
@ -2602,7 +2607,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
}
|
}
|
||||||
if (fbc->common.scope &&
|
if (fbc->common.scope &&
|
||||||
!(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
|
!(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
|
||||||
!object) {
|
!call->object) {
|
||||||
|
|
||||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||||
/* FIXME: output identifiers properly */
|
/* FIXME: output identifiers properly */
|
||||||
|
@ -2617,37 +2622,33 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EXPECTED(EX(call)->num_args == 0)) {
|
//???
|
||||||
EX(call)->num_args = num_args = opline->extended_value;
|
call->num_args += opline->extended_value;
|
||||||
} else {
|
|
||||||
EX(call)->num_args += opline->extended_value;
|
|
||||||
num_args = EX(call)->num_args;
|
|
||||||
zend_vm_stack_adjust_call_frame(&EX(call) TSRMLS_CC);
|
|
||||||
}
|
|
||||||
LOAD_OPLINE();
|
LOAD_OPLINE();
|
||||||
|
|
||||||
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
|
if (UNEXPECTED(fbc->type == ZEND_INTERNAL_FUNCTION)) {
|
||||||
int should_change_scope = 0;
|
int should_change_scope = 0;
|
||||||
zval *ret;
|
zval *ret;
|
||||||
|
|
||||||
if (fbc->common.scope) {
|
if (fbc->common.scope) {
|
||||||
should_change_scope = 1;
|
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 ??? */
|
/* TODO: we don't set scope if we call an object method ??? */
|
||||||
/* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
|
/* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
|
||||||
#if 1
|
#if 1
|
||||||
EG(scope) = (object) ? NULL : fbc->common.scope;
|
EG(scope) = (call->object) ? NULL : fbc->common.scope;
|
||||||
#else
|
#else
|
||||||
EG(scope) = fbc->common.scope;
|
EG(scope) = fbc->common.scope;
|
||||||
#endif
|
#endif
|
||||||
EG(called_scope) = EX(call)->called_scope;
|
EG(called_scope) = call->called_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
|
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
|
||||||
zend_uint i;
|
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);
|
zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
@ -2669,11 +2670,16 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
|
|
||||||
if (!zend_execute_internal) {
|
if (!zend_execute_internal) {
|
||||||
/* saves one function call if zend_execute_internal is not used */
|
/* 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 {
|
} else {
|
||||||
zend_execute_internal(execute_data, NULL TSRMLS_CC);
|
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)) {
|
if (!RETURN_VALUE_USED(opline)) {
|
||||||
zval_ptr_dtor(ret);
|
zval_ptr_dtor(ret);
|
||||||
}
|
}
|
||||||
|
@ -2683,12 +2689,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
} else {
|
} else {
|
||||||
ZEND_VM_C_GOTO(fcall_end);
|
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;
|
zval *return_value = NULL;
|
||||||
|
|
||||||
Z_OBJ(EG(This)) = object;
|
Z_OBJ(EG(This)) = call->object;
|
||||||
EG(scope) = fbc->common.scope;
|
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_symbol_table) = NULL;
|
||||||
EG(active_op_array) = &fbc->op_array;
|
EG(active_op_array) = &fbc->op_array;
|
||||||
if (RETURN_VALUE_USED(opline)) {
|
if (RETURN_VALUE_USED(opline)) {
|
||||||
|
@ -2698,40 +2704,50 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
|
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)) {
|
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);
|
|
||||||
ZEND_VM_ENTER();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX(call) = call->prev_nested_call;
|
||||||
|
zend_vm_stack_free_call_frame(call TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
zend_execute(EG(active_op_array), return_value TSRMLS_CC);
|
call->prev_execute_data = EG(current_execute_data);
|
||||||
|
i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
|
||||||
|
|
||||||
|
if (EXPECTED(zend_execute_ex == execute_ex)) {
|
||||||
|
ZEND_VM_ENTER();
|
||||||
|
} else {
|
||||||
|
execute_ex(call TSRMLS_CC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EG(opline_ptr) = &EX(opline);
|
EG(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)) {
|
if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
|
||||||
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
|
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
|
||||||
}
|
}
|
||||||
EG(active_symbol_table) = EX(symbol_table);
|
EG(active_symbol_table) = EX(symbol_table);
|
||||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
} else { /* ZEND_OVERLOADED_FUNCTION */
|
||||||
Z_OBJ(EG(This)) = object;
|
Z_OBJ(EG(This)) = call->object;
|
||||||
//??? EG(scope) = NULL;
|
//??? EG(scope) = NULL;
|
||||||
EG(scope) = fbc->common.scope;
|
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));
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||||
|
|
||||||
/* Not sure what should be done here if it's a static method */
|
/* Not sure what should be done here if it's a static method */
|
||||||
if (EXPECTED(object != NULL)) {
|
if (EXPECTED(call->object != NULL)) {
|
||||||
object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
|
call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
|
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) {
|
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||||
STR_RELEASE(fbc->common.function_name);
|
STR_RELEASE(fbc->common.function_name);
|
||||||
}
|
}
|
||||||
|
@ -2748,8 +2764,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||||
|
|
||||||
ZEND_VM_C_LABEL(fcall_end_change_scope):
|
ZEND_VM_C_LABEL(fcall_end_change_scope):
|
||||||
if (Z_OBJ(EG(This))) {
|
if (Z_OBJ(EG(This))) {
|
||||||
if (UNEXPECTED(EG(exception) != NULL) && (EX(call)->flags & ZEND_CALL_CTOR)) {
|
if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
|
||||||
if (EX(call)->flags & ZEND_CALL_CTOR_RESULT_USED) {
|
if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
|
||||||
Z_DELREF(EG(This));
|
Z_DELREF(EG(This));
|
||||||
}
|
}
|
||||||
if (Z_REFCOUNT(EG(This)) == 1) {
|
if (Z_REFCOUNT(EG(This)) == 1) {
|
||||||
|
@ -2757,7 +2773,6 @@ ZEND_VM_C_LABEL(fcall_end_change_scope):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Z_DELREF(EG(This))) {
|
if (!Z_DELREF(EG(This))) {
|
||||||
EX(call)->flags &= ~ZEND_CALL_DONE;
|
|
||||||
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
|
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
|
||||||
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
|
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
|
||||||
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
|
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
|
||||||
|
@ -2768,10 +2783,6 @@ ZEND_VM_C_LABEL(fcall_end_change_scope):
|
||||||
EG(called_scope) = EX(called_scope);
|
EG(called_scope) = EX(called_scope);
|
||||||
|
|
||||||
ZEND_VM_C_LABEL(fcall_end):
|
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)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
zend_throw_exception_internal(NULL TSRMLS_CC);
|
zend_throw_exception_internal(NULL TSRMLS_CC);
|
||||||
if (RETURN_VALUE_USED(opline)) {
|
if (RETURN_VALUE_USED(opline)) {
|
||||||
|
@ -2923,7 +2934,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
|
||||||
/* Check whether an exception has been thrown, if not, jump over code */
|
/* Check whether an exception has been thrown, if not, jump over code */
|
||||||
zend_exception_restore(TSRMLS_C);
|
zend_exception_restore(TSRMLS_C);
|
||||||
if (EG(exception) == NULL) {
|
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 */
|
ZEND_VM_CONTINUE(); /* CHECK_ME */
|
||||||
}
|
}
|
||||||
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
|
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
|
||||||
|
@ -2947,7 +2958,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
|
||||||
zend_throw_exception_internal(NULL TSRMLS_CC);
|
zend_throw_exception_internal(NULL TSRMLS_CC);
|
||||||
HANDLE_EXCEPTION();
|
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_CONTINUE(); /* CHECK_ME */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2969,7 +2980,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
|
||||||
ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
|
ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zval *value, *top;
|
zval *value, *arg;
|
||||||
zend_free_op free_op1;
|
zend_free_op free_op1;
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
|
@ -2980,11 +2991,11 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
|
||||||
}
|
}
|
||||||
|
|
||||||
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||||
top = zend_vm_stack_top_inc(TSRMLS_C);
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
||||||
ZVAL_COPY_VALUE(top, value);
|
ZVAL_COPY_VALUE(arg, value);
|
||||||
if (OP1_TYPE == IS_CONST) {
|
if (OP1_TYPE == IS_CONST) {
|
||||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
|
||||||
zval_copy_ctor_func(top);
|
zval_copy_ctor_func(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -2993,18 +3004,18 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
|
||||||
ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
|
ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zval *varptr, *top;
|
zval *varptr, *arg;
|
||||||
zend_free_op free_op1;
|
zend_free_op free_op1;
|
||||||
|
|
||||||
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
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)) {
|
if (Z_ISREF_P(varptr)) {
|
||||||
ZVAL_COPY(top, Z_REFVAL_P(varptr));
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
||||||
FREE_OP1();
|
FREE_OP1();
|
||||||
} else {
|
} else {
|
||||||
ZVAL_COPY_VALUE(top, varptr);
|
ZVAL_COPY_VALUE(arg, varptr);
|
||||||
if (OP1_TYPE == IS_CV) {
|
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();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -3014,7 +3025,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_free_op free_op1;
|
zend_free_op free_op1;
|
||||||
zval *varptr, *top;
|
zval *varptr, *arg;
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
|
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
|
||||||
|
@ -3039,15 +3050,16 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
|
||||||
if (OP1_TYPE == IS_CV) {
|
if (OP1_TYPE == IS_CV) {
|
||||||
Z_ADDREF_P(varptr);
|
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 {
|
} else {
|
||||||
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
|
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
|
||||||
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
|
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
|
||||||
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||||
zend_error(E_STRICT, "Only variables should be passed by reference");
|
zend_error(E_STRICT, "Only variables should be passed by reference");
|
||||||
}
|
}
|
||||||
top = zend_vm_stack_top_inc(TSRMLS_C);
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
||||||
ZVAL_COPY(top, varptr);
|
ZVAL_COPY(arg, varptr);
|
||||||
FREE_OP1_IF_VAR();
|
FREE_OP1_IF_VAR();
|
||||||
}
|
}
|
||||||
CHECK_EXCEPTION();
|
CHECK_EXCEPTION();
|
||||||
|
@ -3058,7 +3070,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_free_op free_op1;
|
zend_free_op free_op1;
|
||||||
zval *varptr, *top;
|
zval *varptr, *arg;
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
|
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
|
||||||
|
@ -3067,23 +3079,23 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
|
||||||
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
|
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))) {
|
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();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Z_ISREF_P(varptr)) {
|
if (Z_ISREF_P(varptr)) {
|
||||||
Z_ADDREF_P(varptr);
|
Z_ADDREF_P(varptr);
|
||||||
ZVAL_COPY_VALUE(top, varptr);
|
ZVAL_COPY_VALUE(arg, varptr);
|
||||||
} else if (OP1_TYPE == IS_VAR &&
|
} else if (OP1_TYPE == IS_VAR &&
|
||||||
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
|
||||||
ZVAL_COPY_VALUE(top, varptr);
|
ZVAL_COPY_VALUE(arg, varptr);
|
||||||
ZVAL_MAKE_REF(top);
|
ZVAL_MAKE_REF(arg);
|
||||||
} else {
|
} else {
|
||||||
ZVAL_MAKE_REF(varptr);
|
ZVAL_MAKE_REF(varptr);
|
||||||
Z_ADDREF_P(varptr);
|
Z_ADDREF_P(varptr);
|
||||||
ZVAL_REF(top, Z_REF_P(varptr));
|
ZVAL_REF(arg, Z_REF_P(varptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_OP1_VAR_PTR();
|
FREE_OP1_VAR_PTR();
|
||||||
|
@ -3093,7 +3105,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
|
||||||
ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
|
ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zval *varptr, *top;
|
zval *varptr, *arg;
|
||||||
zend_free_op free_op1;
|
zend_free_op free_op1;
|
||||||
|
|
||||||
if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
|
if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
|
||||||
|
@ -3103,14 +3115,14 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
|
||||||
}
|
}
|
||||||
|
|
||||||
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
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)) {
|
if (Z_ISREF_P(varptr)) {
|
||||||
ZVAL_COPY(top, Z_REFVAL_P(varptr));
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
||||||
FREE_OP1();
|
FREE_OP1();
|
||||||
} else {
|
} else {
|
||||||
ZVAL_COPY_VALUE(top, varptr);
|
ZVAL_COPY_VALUE(arg, varptr);
|
||||||
if (OP1_TYPE == IS_CV) {
|
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();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -3134,7 +3146,7 @@ ZEND_VM_C_LABEL(send_again):
|
||||||
zval *arg, *top;
|
zval *arg, *top;
|
||||||
zend_string *name;
|
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)) {
|
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -3161,7 +3173,7 @@ ZEND_VM_C_LABEL(send_again):
|
||||||
ZEND_VM_NEXT_OPCODE();
|
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 (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
|
||||||
if (!Z_IMMUTABLE_P(args)) {
|
if (!Z_IMMUTABLE_P(args)) {
|
||||||
ZVAL_MAKE_REF(arg);
|
ZVAL_MAKE_REF(arg);
|
||||||
|
@ -3171,6 +3183,7 @@ ZEND_VM_C_LABEL(send_again):
|
||||||
ZVAL_DUP(top, arg);
|
ZVAL_DUP(top, arg);
|
||||||
}
|
}
|
||||||
} else if (Z_ISREF_P(arg)) {
|
} else if (Z_ISREF_P(arg)) {
|
||||||
|
//TODO: change into ZVAL_COPY()???
|
||||||
ZVAL_DUP(top, Z_REFVAL_P(arg));
|
ZVAL_DUP(top, Z_REFVAL_P(arg));
|
||||||
} else {
|
} else {
|
||||||
ZVAL_COPY(top, arg);
|
ZVAL_COPY(top, arg);
|
||||||
|
@ -3210,7 +3223,7 @@ ZEND_VM_C_LABEL(send_again):
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
|
for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
|
||||||
zval *arg;
|
zval *arg, *top;
|
||||||
|
|
||||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
ZEND_VM_C_GOTO(unpack_iter_dtor);
|
ZEND_VM_C_GOTO(unpack_iter_dtor);
|
||||||
|
@ -3254,8 +3267,9 @@ ZEND_VM_C_LABEL(send_again):
|
||||||
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_VM_STACK_GROW_IF_NEEDED(1);
|
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1 TSRMLS_DC);
|
||||||
zend_vm_stack_push(arg TSRMLS_CC);
|
top = ZEND_CALL_ARG(EX(call), arg_num);
|
||||||
|
ZVAL_COPY_VALUE(top, arg);
|
||||||
EX(call)->num_args++;
|
EX(call)->num_args++;
|
||||||
|
|
||||||
iter->funcs->move_forward(iter TSRMLS_CC);
|
iter->funcs->move_forward(iter TSRMLS_CC);
|
||||||
|
@ -3285,24 +3299,18 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_uint arg_num = opline->op1.num;
|
zend_uint arg_num = opline->op1.num;
|
||||||
zend_uint arg_count = EX(prev_execute_data)->call->num_args;
|
|
||||||
|
|
||||||
SAVE_OPLINE();
|
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);
|
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_EXCEPTION();
|
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);
|
||||||
|
|
||||||
|
zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
|
||||||
|
CHECK_EXCEPTION();
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3310,29 +3318,24 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_uint arg_num = opline->op1.num;
|
zend_uint arg_num = opline->op1.num;
|
||||||
zend_uint arg_count = EX(prev_execute_data)->call->num_args;
|
zval *param;
|
||||||
zval *var_ptr;
|
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
|
param = _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 > EX(num_args)) {
|
||||||
if (arg_num > arg_count) {
|
ZVAL_COPY_VALUE(param, opline->op2.zv);
|
||||||
ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
|
if (Z_OPT_CONSTANT_P(param)) {
|
||||||
if (Z_OPT_CONSTANT_P(var_ptr)) {
|
zval_update_constant(param, 0 TSRMLS_CC);
|
||||||
zval_update_constant(var_ptr, 0 TSRMLS_CC);
|
|
||||||
} else {
|
} else {
|
||||||
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
||||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
|
||||||
zval_copy_ctor_func(var_ptr);
|
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)) {
|
if (UNEXPECTED((EX(func)->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);
|
zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_EXCEPTION();
|
CHECK_EXCEPTION();
|
||||||
|
@ -3343,30 +3346,39 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_uint arg_num = opline->op1.num;
|
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;
|
zval *params;
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
|
|
||||||
params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
|
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) {
|
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);
|
array_init_size(params, arg_count - arg_num + 1);
|
||||||
if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
|
param = EX(extra_args);
|
||||||
do {
|
if (UNEXPECTED((EX(func)->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);
|
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);
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
|
||||||
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
||||||
param++;
|
param++;
|
||||||
} while (++arg_num <= arg_count);
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
do {
|
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);
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
|
||||||
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
||||||
param++;
|
param++;
|
||||||
} while (++arg_num <= arg_count);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
array_init(params);
|
array_init(params);
|
||||||
|
@ -3398,8 +3410,8 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
|
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
|
||||||
EX(op_array), execute_data TSRMLS_CC);
|
&EX(func)->op_array, execute_data TSRMLS_CC);
|
||||||
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
|
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
|
ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
|
||||||
|
@ -3409,8 +3421,8 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
|
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
|
||||||
EX(op_array), execute_data TSRMLS_CC);
|
&EX(func)->op_array, execute_data TSRMLS_CC);
|
||||||
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
|
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
|
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
|
||||||
|
@ -3421,9 +3433,9 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
|
||||||
|
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
|
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->opcode == ZEND_SWITCH_FREE) {
|
||||||
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
||||||
|
@ -3492,7 +3504,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
|
||||||
} else {
|
} else {
|
||||||
/* We are not handling overloaded classes right now */
|
/* We are not handling overloaded classes right now */
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
EX(call) = zend_vm_stack_push_call_frame(
|
||||||
constructor, 0,
|
constructor, opline->extended_value,
|
||||||
RETURN_VALUE_USED(opline) ?
|
RETURN_VALUE_USED(opline) ?
|
||||||
(ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
|
(ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
|
||||||
Z_CE_P(EX_VAR(opline->op1.var)),
|
Z_CE_P(EX_VAR(opline->op1.var)),
|
||||||
|
@ -3981,7 +3993,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
|
||||||
HANDLE_EXCEPTION();
|
HANDLE_EXCEPTION();
|
||||||
} else if (EXPECTED(new_op_array != NULL)) {
|
} else if (EXPECTED(new_op_array != NULL)) {
|
||||||
zval *return_value = NULL;
|
zval *return_value = NULL;
|
||||||
zend_call_frame *call;
|
|
||||||
|
|
||||||
EG(active_op_array) = new_op_array;
|
EG(active_op_array) = new_op_array;
|
||||||
if (RETURN_VALUE_USED(opline)) {
|
if (RETURN_VALUE_USED(opline)) {
|
||||||
|
@ -3989,24 +4000,22 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
|
||||||
}
|
}
|
||||||
|
|
||||||
EX(call) = zend_vm_stack_push_call_frame(
|
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)) {
|
if (!EG(active_symbol_table)) {
|
||||||
zend_rebuild_symbol_table(TSRMLS_C);
|
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)) {
|
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();
|
ZEND_VM_ENTER();
|
||||||
} else {
|
} else {
|
||||||
zend_execute(new_op_array, return_value TSRMLS_CC);
|
execute_ex(EG(current_execute_data) TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
EG(opline_ptr) = &EX(opline);
|
EG(opline_ptr) = &EX(opline);
|
||||||
EG(active_op_array) = EX(op_array);
|
EG(active_op_array) = &EX(func)->op_array;
|
||||||
call = EX(call);
|
|
||||||
EX(call) = EX(call)->prev;
|
|
||||||
zend_vm_stack_free((zval*)call TSRMLS_CC);
|
|
||||||
destroy_op_array(new_op_array TSRMLS_CC);
|
destroy_op_array(new_op_array TSRMLS_CC);
|
||||||
efree(new_op_array);
|
efree(new_op_array);
|
||||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||||
|
@ -4837,7 +4846,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
|
||||||
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
|
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
|
||||||
{
|
{
|
||||||
SAVE_OPLINE();
|
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 */
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4963,7 +4972,7 @@ ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
|
||||||
{
|
{
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
if (!EG(no_extensions)) {
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -4973,7 +4982,7 @@ ZEND_VM_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
|
||||||
{
|
{
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
if (!EG(no_extensions)) {
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -4983,7 +4992,7 @@ ZEND_VM_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
|
||||||
{
|
{
|
||||||
SAVE_OPLINE();
|
SAVE_OPLINE();
|
||||||
if (!EG(no_extensions)) {
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -4994,7 +5003,7 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY)
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
|
|
||||||
SAVE_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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
@ -5004,7 +5013,7 @@ ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
|
|
||||||
SAVE_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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
@ -5018,7 +5027,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
|
||||||
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
|
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 &&
|
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
|
||||||
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
|
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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
|
@ -5029,7 +5038,7 @@ ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
|
|
||||||
SAVE_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();
|
CHECK_EXCEPTION();
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
@ -5159,28 +5168,24 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
|
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) {
|
if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
|
||||||
finally_op_num = EX(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 &&
|
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
|
||||||
op_num < EG(active_op_array)->try_catch_array[i].finally_end) {
|
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
|
||||||
finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end;
|
finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EX(call)) {
|
if (EX(call)) {
|
||||||
zend_call_frame *call = EX(call);
|
zend_execute_data *call = EX(call);
|
||||||
do {
|
do {
|
||||||
zval *args = ZEND_CALL_ARG(call, 1);
|
|
||||||
|
|
||||||
/* If the exception was thrown during a function call there might be
|
/* If the exception was thrown during a function call there might be
|
||||||
* arguments pushed to the stack that have to be dtor'ed. */
|
* arguments pushed to the stack that have to be dtor'ed. */
|
||||||
while (zend_vm_stack_top(TSRMLS_C) != args) {
|
zend_vm_stack_free_args(EX(call) TSRMLS_CC);
|
||||||
zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
|
|
||||||
zval_ptr_dtor(stack_zval_p);
|
|
||||||
}
|
|
||||||
if (call->object) {
|
if (call->object) {
|
||||||
if (call->flags & ZEND_CALL_CTOR) {
|
if (call->flags & ZEND_CALL_CTOR) {
|
||||||
if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
|
if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
|
||||||
|
@ -5192,22 +5197,22 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
|
||||||
}
|
}
|
||||||
OBJ_RELEASE(call->object);
|
OBJ_RELEASE(call->object);
|
||||||
}
|
}
|
||||||
EG(argument_stack)->top = (zval*)call;
|
EX(call) = call->prev_nested_call;
|
||||||
call = call->prev;
|
zend_vm_stack_free_call_frame(call TSRMLS_CC);
|
||||||
|
call = EX(call);
|
||||||
} while (call);
|
} while (call);
|
||||||
EX(call) = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<EX(op_array)->last_brk_cont; i++) {
|
for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
|
||||||
if (EX(op_array)->brk_cont_array[i].start < 0) {
|
if (EX(func)->op_array.brk_cont_array[i].start < 0) {
|
||||||
continue;
|
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... */
|
/* further blocks will not be relevant... */
|
||||||
break;
|
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 ||
|
if (!catch_op_num ||
|
||||||
catch_op_num >= 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(op_array)->opcodes[EX(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->opcode == ZEND_SWITCH_FREE) {
|
||||||
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
||||||
|
@ -5243,7 +5248,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
|
||||||
EX(delayed_exception) = EG(exception);
|
EX(delayed_exception) = EG(exception);
|
||||||
EG(exception) = NULL;
|
EG(exception) = NULL;
|
||||||
EX(fast_ret) = 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();
|
ZEND_VM_CONTINUE();
|
||||||
} else if (catch_op_num) {
|
} else if (catch_op_num) {
|
||||||
if (finally_op_end && catch_op_num > finally_op_end) {
|
if (finally_op_end && catch_op_num > finally_op_end) {
|
||||||
|
@ -5253,14 +5258,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
|
||||||
EX(delayed_exception) = NULL;
|
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();
|
ZEND_VM_CONTINUE();
|
||||||
} else {
|
} else {
|
||||||
if (EX(delayed_exception)) {
|
if (EX(delayed_exception)) {
|
||||||
zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
|
zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
|
||||||
EX(delayed_exception) = NULL;
|
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);
|
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
|
||||||
} else {
|
} else {
|
||||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||||
|
@ -5291,7 +5296,7 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
|
||||||
case ZEND_USER_OPCODE_CONTINUE:
|
case ZEND_USER_OPCODE_CONTINUE:
|
||||||
ZEND_VM_CONTINUE();
|
ZEND_VM_CONTINUE();
|
||||||
case ZEND_USER_OPCODE_RETURN:
|
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);
|
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
|
||||||
} else {
|
} else {
|
||||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||||
|
@ -5405,7 +5410,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
|
||||||
if (OP1_TYPE != IS_UNUSED) {
|
if (OP1_TYPE != IS_UNUSED) {
|
||||||
zend_free_op free_op1;
|
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,
|
/* Constants and temporary variables aren't yieldable by reference,
|
||||||
* but we still allow them with a notice. */
|
* but we still allow them with a notice. */
|
||||||
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
|
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
|
||||||
|
@ -5533,7 +5538,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
|
||||||
if (opline->extended_value &&
|
if (opline->extended_value &&
|
||||||
UNEXPECTED(EG(prev_exception) != NULL)) {
|
UNEXPECTED(EG(prev_exception) != NULL)) {
|
||||||
/* in case of unhandled exception jump to catch block instead of finally */
|
/* 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();
|
ZEND_VM_CONTINUE();
|
||||||
}
|
}
|
||||||
EX(fast_ret) = opline + 1;
|
EX(fast_ret) = opline + 1;
|
||||||
|
@ -5552,15 +5557,15 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
|
|
||||||
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
|
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();
|
ZEND_VM_CONTINUE();
|
||||||
} else {
|
} else {
|
||||||
EG(exception) = EX(delayed_exception);
|
EG(exception) = EX(delayed_exception);
|
||||||
EX(delayed_exception) = NULL;
|
EX(delayed_exception) = NULL;
|
||||||
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
|
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();
|
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);
|
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
|
||||||
} else {
|
} else {
|
||||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -33,10 +33,21 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
|
||||||
|
|
||||||
ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value TSRMLS_DC)
|
ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value TSRMLS_DC)
|
||||||
{
|
{
|
||||||
|
zend_execute_data *execute_data;
|
||||||
|
|
||||||
if (EG(exception) != NULL) {
|
if (EG(exception) != NULL) {
|
||||||
return;
|
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%}
|
{%EXTERNAL_EXECUTOR%}
|
||||||
|
|
|
@ -286,6 +286,10 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
|
||||||
EG(active_op_array) = new_op_array;
|
EG(active_op_array) = new_op_array;
|
||||||
|
|
||||||
zend_try {
|
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);
|
zend_execute(new_op_array, &result TSRMLS_CC);
|
||||||
if (PHAR_G(cwd)) {
|
if (PHAR_G(cwd)) {
|
||||||
efree(PHAR_G(cwd));
|
efree(PHAR_G(cwd));
|
||||||
|
|
|
@ -292,6 +292,10 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha
|
||||||
}
|
}
|
||||||
|
|
||||||
ZVAL_UNDEF(&result);
|
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);
|
zend_execute(new_op_array, &result TSRMLS_CC);
|
||||||
|
|
||||||
destroy_op_array(new_op_array TSRMLS_CC);
|
destroy_op_array(new_op_array TSRMLS_CC);
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) /* {{{ */
|
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;
|
int callers_limit = 20;
|
||||||
pid_t pid = child->pid;
|
pid_t pid = child->pid;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
@ -74,10 +76,9 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
|
||||||
|
|
||||||
fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
|
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)) {
|
||||||
//??? if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
|
return -1;
|
||||||
//??? return -1;
|
}
|
||||||
//??? }
|
|
||||||
|
|
||||||
function = l;
|
function = l;
|
||||||
|
|
||||||
|
@ -132,6 +133,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue