mirror of
https://github.com/php/php-src.git
synced 2025-01-19 02:03:47 +08:00
Refactoring: use call_frames instead of call_slots
This commit is contained in:
parent
ba45650d63
commit
43477bc7a2
@ -44,14 +44,13 @@ static zend_class_entry **class_cleanup_handlers;
|
||||
/* this function doesn't check for too many parameters */
|
||||
ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
va_list ptr;
|
||||
zval **param, *param_ptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
@ -61,7 +60,6 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
|
||||
while (param_count-->0) {
|
||||
param = va_arg(ptr, zval **);
|
||||
param_ptr = (p-arg_count);
|
||||
if (!Z_ISREF_P(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
|
||||
zval new_tmp;
|
||||
|
||||
@ -70,7 +68,7 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
ZVAL_COPY_VALUE(param_ptr, &new_tmp);
|
||||
}
|
||||
*param = param_ptr;
|
||||
arg_count--;
|
||||
param_ptr++;
|
||||
}
|
||||
va_end(ptr);
|
||||
|
||||
@ -80,19 +78,17 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
|
||||
ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
zval *param_ptr;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
param_ptr = (p-arg_count);
|
||||
if (Z_REFCOUNTED_P(param_ptr) &&
|
||||
!Z_ISREF_P(param_ptr) &&
|
||||
Z_REFCOUNT_P(param_ptr) > 1) {
|
||||
@ -105,7 +101,7 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_
|
||||
ZVAL_COPY_VALUE(argument_array, param_ptr);
|
||||
}
|
||||
argument_array++;
|
||||
arg_count--;
|
||||
param_ptr++;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -116,14 +112,13 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_
|
||||
/* this function doesn't check for too many parameters */
|
||||
ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
va_list ptr;
|
||||
zval **param;
|
||||
zval **param, *param_ptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
@ -132,7 +127,8 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
va_start(ptr, param_count);
|
||||
while (param_count-->0) {
|
||||
param = va_arg(ptr, zval **);
|
||||
*param = p-(arg_count--);
|
||||
*param = param_ptr;
|
||||
param_ptr++;
|
||||
}
|
||||
va_end(ptr);
|
||||
|
||||
@ -142,22 +138,20 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
|
||||
ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
zval *param_ptr;
|
||||
int arg_count;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
zval *value = (p-arg_count);
|
||||
|
||||
ZVAL_COPY_VALUE(argument_array, value);
|
||||
ZVAL_COPY_VALUE(argument_array, param_ptr);
|
||||
argument_array++;
|
||||
arg_count--;
|
||||
param_ptr++;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -166,22 +160,22 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array
|
||||
|
||||
ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
zval *param_ptr;
|
||||
int arg_count;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
zval *param = p-(arg_count--);
|
||||
if (Z_REFCOUNTED_P(param)) {
|
||||
Z_ADDREF_P(param);
|
||||
if (Z_REFCOUNTED_P(param_ptr)) {
|
||||
Z_ADDREF_P(param_ptr);
|
||||
}
|
||||
add_next_index_zval(argument_array, param);
|
||||
add_next_index_zval(argument_array, param_ptr);
|
||||
param_ptr++;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -841,7 +835,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
case '+':
|
||||
if (have_varargs) {
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->call->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
|
||||
class_name,
|
||||
@ -861,7 +855,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
default:
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->call->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
|
||||
class_name,
|
||||
@ -884,7 +878,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->call->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
|
||||
class_name,
|
||||
@ -898,7 +892,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
arg_count = Z_LVAL_P(zend_vm_stack_top(TSRMLS_C) - 1);
|
||||
arg_count = EG(current_execute_data)->call->num_args;
|
||||
|
||||
if (num_args > arg_count) {
|
||||
zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
|
||||
@ -922,7 +916,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
if (num_varargs > 0) {
|
||||
*n_varargs = num_varargs;
|
||||
*varargs = (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
|
||||
*varargs = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
|
||||
/* adjust how many args we have left and restart loop */
|
||||
num_args += 1 - num_varargs;
|
||||
i += num_varargs;
|
||||
@ -933,7 +927,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
}
|
||||
}
|
||||
|
||||
arg = zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i);
|
||||
arg = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
|
||||
|
||||
if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
|
||||
/* clean up varargs array if it was used */
|
||||
@ -1004,7 +998,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
|
||||
* Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
|
||||
* In that case EG(This) would still be the $this from the calling code and we'd take the
|
||||
* wrong branch here. */
|
||||
zend_bool is_method = EG(current_execute_data)->function_state.function->common.scope != NULL;
|
||||
zend_bool is_method = EG(current_execute_data)->call->func->common.scope != NULL;
|
||||
if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
|
||||
RETURN_IF_ZERO_ARGS(num_args, p, 0);
|
||||
|
||||
|
@ -396,8 +396,8 @@ ZEND_FUNCTION(func_num_args)
|
||||
{
|
||||
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
|
||||
|
||||
if (ex && ex->function_state.arguments) {
|
||||
RETURN_LONG(Z_LVAL_P(ex->function_state.arguments));
|
||||
if (ex && ex->call) {
|
||||
RETURN_LONG(ex->call->num_args);
|
||||
} else {
|
||||
zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
|
||||
RETURN_LONG(-1);
|
||||
@ -409,7 +409,6 @@ ZEND_FUNCTION(func_num_args)
|
||||
Get the $arg_num'th argument that was passed to the function */
|
||||
ZEND_FUNCTION(func_get_arg)
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
zval *arg;
|
||||
long requested_offset;
|
||||
@ -424,20 +423,19 @@ ZEND_FUNCTION(func_get_arg)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (!ex || !ex->function_state.arguments) {
|
||||
if (!ex || !ex->call) {
|
||||
zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
p = ex->function_state.arguments;
|
||||
arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_arg(); */
|
||||
arg_count = ex->call->num_args;
|
||||
|
||||
if (requested_offset >= arg_count) {
|
||||
zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
arg = p-(arg_count-requested_offset);
|
||||
arg = ZEND_CALL_ARG(ex->call, requested_offset + 1);
|
||||
RETURN_ZVAL_FAST(arg);
|
||||
}
|
||||
/* }}} */
|
||||
@ -451,19 +449,18 @@ ZEND_FUNCTION(func_get_args)
|
||||
int i;
|
||||
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
|
||||
|
||||
if (!ex || !ex->function_state.arguments) {
|
||||
if (!ex || !ex->call) {
|
||||
zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
p = ex->function_state.arguments;
|
||||
arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_args(); */
|
||||
arg_count = ex->call->num_args;
|
||||
|
||||
array_init_size(return_value, arg_count);
|
||||
if (arg_count) {
|
||||
Bucket *q;
|
||||
|
||||
p -= arg_count;
|
||||
p = ZEND_CALL_ARG(ex->call, 1);
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
||||
q = Z_ARRVAL_P(return_value)->arData;
|
||||
for (i=0; i<arg_count; i++) {
|
||||
@ -1957,22 +1954,24 @@ ZEND_FUNCTION(get_defined_constants)
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void debug_backtrace_get_args(zval *curpos, zval *arg_array TSRMLS_DC)
|
||||
static void debug_backtrace_get_args(zend_call_frame *call, zval *arg_array TSRMLS_DC)
|
||||
{
|
||||
zval *p = curpos;
|
||||
zval *p;
|
||||
zval *arg;
|
||||
int arg_count = Z_LVAL_P(p);
|
||||
int arg_count = call->num_args;
|
||||
|
||||
array_init_size(arg_array, arg_count);
|
||||
p -= arg_count;
|
||||
if (arg_count > 0) {
|
||||
p = ZEND_CALL_ARG(call, 1);
|
||||
|
||||
while (--arg_count >= 0) {
|
||||
arg = p++;
|
||||
if (arg) {
|
||||
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
||||
add_next_index_zval(arg_array, arg);
|
||||
} else {
|
||||
add_next_index_null(arg_array);
|
||||
while (--arg_count >= 0) {
|
||||
arg = p++;
|
||||
if (arg) {
|
||||
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
||||
add_next_index_zval(arg_array, arg);
|
||||
} else {
|
||||
add_next_index_null(arg_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1996,6 +1995,7 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
zend_execute_data *ptr, *skip;
|
||||
zend_object *object;
|
||||
int lineno, frameno = 0;
|
||||
zend_function *func;
|
||||
const char *function_name;
|
||||
const char *filename;
|
||||
zend_string *class_name = NULL;
|
||||
@ -2029,7 +2029,6 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
skip->prev_execute_data &&
|
||||
skip->prev_execute_data->opline &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
skip = skip->prev_execute_data;
|
||||
}
|
||||
@ -2044,41 +2043,47 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
|
||||
/* $this may be passed into regular internal functions */
|
||||
if (object &&
|
||||
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->function_state.function->common.scope) {
|
||||
ptr->call &&
|
||||
ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->call->func->common.scope) {
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
function_name = (ptr->function_state.function->common.scope &&
|
||||
ptr->function_state.function->common.scope->trait_aliases) ?
|
||||
if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
|
||||
func = ptr->call->func;
|
||||
function_name = (func->common.scope &&
|
||||
func->common.scope->trait_aliases) ?
|
||||
zend_resolve_method_name(
|
||||
object ?
|
||||
(object ?
|
||||
zend_get_class_entry(object TSRMLS_CC) :
|
||||
ptr->function_state.function->common.scope,
|
||||
ptr->function_state.function)->val :
|
||||
(ptr->function_state.function->common.function_name ?
|
||||
ptr->function_state.function->common.function_name->val :
|
||||
NULL);
|
||||
func->common.scope), func)->val :
|
||||
(func->common.function_name ?
|
||||
func->common.function_name->val : NULL);
|
||||
} else {
|
||||
func = (zend_function*)(ptr->op_array);
|
||||
function_name = func && func->common.function_name ?
|
||||
func->common.function_name->val : NULL;
|
||||
}
|
||||
|
||||
if (function_name) {
|
||||
if (object) {
|
||||
if (ptr->function_state.function->common.scope) {
|
||||
class_name = ptr->function_state.function->common.scope->name;
|
||||
if (func->common.scope) {
|
||||
class_name = func->common.scope->name;
|
||||
} else {
|
||||
class_name = zend_get_object_classname(object TSRMLS_CC);
|
||||
}
|
||||
|
||||
call_type = "->";
|
||||
} else if (ptr->function_state.function->common.scope) {
|
||||
class_name = ptr->function_state.function->common.scope->name;
|
||||
} else if (func->common.scope) {
|
||||
class_name = func->common.scope->name;
|
||||
call_type = "::";
|
||||
} else {
|
||||
class_name = NULL;
|
||||
call_type = NULL;
|
||||
}
|
||||
if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
|
||||
if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
||||
debug_backtrace_get_args(ptr->function_state.arguments, &arg_array TSRMLS_CC);
|
||||
if (!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL) {
|
||||
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
||||
debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -2137,8 +2142,9 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
zend_execute_data *prev = skip->prev_execute_data;
|
||||
|
||||
while (prev) {
|
||||
if (prev->function_state.function &&
|
||||
prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
|
||||
if (prev->call &&
|
||||
prev->call->func &&
|
||||
prev->call->func->common.type != ZEND_USER_FUNCTION) {
|
||||
prev = NULL;
|
||||
break;
|
||||
}
|
||||
@ -2166,6 +2172,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
zend_execute_data *ptr, *skip;
|
||||
zend_object *object = Z_OBJ(EG(This));
|
||||
int lineno, frameno = 0;
|
||||
zend_function *func;
|
||||
const char *function_name;
|
||||
const char *filename;
|
||||
zend_string *class_name;
|
||||
@ -2198,7 +2205,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
skip->prev_execute_data &&
|
||||
skip->prev_execute_data->opline &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
skip = skip->prev_execute_data;
|
||||
}
|
||||
@ -2216,10 +2222,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
zend_execute_data *prev = skip->prev_execute_data;
|
||||
|
||||
while (prev) {
|
||||
if (prev->function_state.function &&
|
||||
prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
|
||||
!(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
|
||||
(prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
||||
if (prev->call &&
|
||||
prev->call->func &&
|
||||
prev->call->func->common.type != ZEND_USER_FUNCTION &&
|
||||
!(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
|
||||
(prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
||||
break;
|
||||
}
|
||||
if (prev->op_array) {
|
||||
@ -2235,28 +2242,34 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
|
||||
/* $this may be passed into regular internal functions */
|
||||
if (object &&
|
||||
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->function_state.function->common.scope) {
|
||||
ptr->call &&
|
||||
ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->call->func->common.scope) {
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
function_name = (ptr->function_state.function->common.scope &&
|
||||
ptr->function_state.function->common.scope->trait_aliases) ?
|
||||
if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
|
||||
func = ptr->call->func;
|
||||
function_name = (func->common.scope &&
|
||||
func->common.scope->trait_aliases) ?
|
||||
zend_resolve_method_name(
|
||||
object ?
|
||||
(object ?
|
||||
zend_get_class_entry(object TSRMLS_CC) :
|
||||
ptr->function_state.function->common.scope,
|
||||
ptr->function_state.function)->val :
|
||||
(ptr->function_state.function->common.function_name ?
|
||||
ptr->function_state.function->common.function_name->val :
|
||||
NULL);
|
||||
func->common.scope), func)->val :
|
||||
(func->common.function_name ?
|
||||
func->common.function_name->val : NULL);
|
||||
} else {
|
||||
func = (zend_function*)(ptr->op_array);
|
||||
function_name = func && func->common.function_name ?
|
||||
func->common.function_name->val : NULL;
|
||||
}
|
||||
|
||||
if (function_name) {
|
||||
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
|
||||
|
||||
if (object) {
|
||||
if (ptr->function_state.function->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
|
||||
if (func->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
|
||||
} else {
|
||||
class_name = zend_get_object_classname(object TSRMLS_CC);
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
|
||||
@ -2270,16 +2283,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
}
|
||||
|
||||
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
|
||||
} else if (ptr->function_state.function->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
|
||||
} else if (func->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
|
||||
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
|
||||
}
|
||||
|
||||
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
||||
((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
|
||||
if (ptr->function_state.arguments) {
|
||||
(!ptr->opline || ptr->opline->opcode == ZEND_DO_FCALL)) {
|
||||
if (ptr->call) {
|
||||
zval args;
|
||||
debug_backtrace_get_args(ptr->function_state.arguments, &args TSRMLS_CC);
|
||||
debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
|
||||
add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers;
|
||||
|
||||
ZEND_METHOD(Closure, __invoke) /* {{{ */
|
||||
{
|
||||
zend_function *func = EG(current_execute_data)->function_state.function;
|
||||
zend_function *func = EG(current_execute_data)->call->func;
|
||||
zval *arguments;
|
||||
|
||||
arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
|
||||
|
@ -182,7 +182,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
|
||||
CG(context).literals_size = 0;
|
||||
CG(context).current_brk_cont = -1;
|
||||
CG(context).backpatch_count = 0;
|
||||
CG(context).nested_calls = 0;
|
||||
CG(context).used_stack = 0;
|
||||
CG(context).in_finally = 0;
|
||||
CG(context).labels = NULL;
|
||||
@ -1949,6 +1948,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
|
||||
|
||||
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
zend_function *function;
|
||||
zend_string *lcname;
|
||||
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
|
||||
@ -1977,10 +1977,14 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
|
||||
STR_RELEASE(Z_STR(function_name->u.constant));
|
||||
Z_STR(function_name->u.constant) = lcname;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_FCALL;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_NODE(opline->op2, function_name);
|
||||
GET_CACHE_SLOT(opline->op2.constant);
|
||||
|
||||
zend_push_function_call_entry(function TSRMLS_CC);
|
||||
if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
|
||||
}
|
||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
return 0;
|
||||
}
|
||||
@ -2017,12 +2021,10 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
last_op->opcode = ZEND_INIT_METHOD_CALL;
|
||||
last_op->result_type = IS_UNUSED;
|
||||
last_op->result.num = CG(context).nested_calls;
|
||||
Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
|
||||
} else {
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
if (left_bracket->op_type == IS_CONST) {
|
||||
opline->op2_type = IS_CONST;
|
||||
@ -2034,9 +2036,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
|
||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
||||
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls;
|
||||
}
|
||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
}
|
||||
/* }}} */
|
||||
@ -2063,14 +2063,12 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
|
||||
/* In run-time PHP will check for function with full name and
|
||||
internal function with short name */
|
||||
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
|
||||
GET_CACHE_SLOT(opline->op2.constant);
|
||||
} else {
|
||||
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
if (function_name->op_type == IS_CONST) {
|
||||
opline->op2_type = IS_CONST;
|
||||
@ -2082,9 +2080,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
|
||||
}
|
||||
|
||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
||||
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls;
|
||||
}
|
||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
}
|
||||
/* }}} */
|
||||
@ -2508,7 +2504,6 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||
opline->extended_value = class_node.EA ;
|
||||
}
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
if (class_node.op_type == IS_CONST) {
|
||||
opline->op1_type = IS_CONST;
|
||||
opline->op1.constant =
|
||||
@ -2530,9 +2525,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||
}
|
||||
|
||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
||||
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls;
|
||||
}
|
||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
return 1; /* Dynamic */
|
||||
}
|
||||
@ -2551,25 +2544,9 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
|
||||
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
|
||||
} else {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
if (fcall->fbc) {
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
SET_NODE(opline->op1, function_name);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.num = CG(context).nested_calls;
|
||||
GET_CACHE_SLOT(opline->op1.constant);
|
||||
} else {
|
||||
opline->opcode = ZEND_DO_FCALL_BY_NAME;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.num = --CG(context).nested_calls;
|
||||
|
||||
/* This would normally be a ZEND_DO_FCALL, but was forced to use
|
||||
* ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
|
||||
* free the function_name */
|
||||
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
|
||||
zval_dtor(&function_name->u.constant);
|
||||
}
|
||||
}
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
}
|
||||
|
||||
opline->result.var = get_temporary_variable(CG(active_op_array));
|
||||
@ -2577,10 +2554,10 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
|
||||
GET_NODE(result, opline->result);
|
||||
opline->extended_value = fcall->arg_num;
|
||||
|
||||
if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + 1;
|
||||
if (CG(context).used_stack > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack;
|
||||
}
|
||||
CG(context).used_stack -= fcall->arg_num;
|
||||
CG(context).used_stack -= ZEND_CALL_FRAME_SLOT + fcall->arg_num;
|
||||
zend_stack_del_top(&CG(function_call_stack));
|
||||
}
|
||||
/* }}} */
|
||||
@ -2682,9 +2659,7 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
} else {
|
||||
if (function_ptr) {
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
} else {
|
||||
opline->extended_value = ZEND_DO_FCALL_BY_NAME;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
}
|
||||
opline->opcode = op;
|
||||
@ -2692,9 +2667,7 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
|
||||
opline->op2.opline_num = fcall->arg_num;
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack;
|
||||
}
|
||||
CG(context).used_stack++;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -2705,25 +2678,6 @@ void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
|
||||
|
||||
fcall->uses_argument_unpacking = 1;
|
||||
|
||||
if (fcall->fbc) {
|
||||
/* If argument unpacking is used argument numbers and sending modes can no longer be
|
||||
* computed at compile time, thus we need access to EX(call). In order to have it we
|
||||
* retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
|
||||
zval func_name;
|
||||
ZVAL_STR(&func_name, STR_COPY(fcall->fbc->common.function_name));
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
|
||||
GET_CACHE_SLOT(opline->op2.constant);
|
||||
|
||||
++CG(context).nested_calls;
|
||||
fcall->fbc = NULL;
|
||||
}
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_SEND_UNPACK;
|
||||
SET_NODE(opline->op1, params);
|
||||
@ -5619,16 +5573,13 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
|
||||
new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_NEW;
|
||||
opline->extended_value = CG(context).nested_calls;
|
||||
opline->result_type = IS_VAR;
|
||||
opline->result.var = get_temporary_variable(CG(active_op_array));
|
||||
SET_NODE(opline->op1, class_type);
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
zend_push_function_call_entry(NULL TSRMLS_CC);
|
||||
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls;
|
||||
}
|
||||
CG(context).used_stack += ZEND_CALL_FRAME_SLOT;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -5819,6 +5770,13 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
opline->opcode = ZEND_INIT_FCALL;
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->op2_type = IS_CONST;
|
||||
LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
|
||||
GET_CACHE_SLOT(opline->op2.constant);
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
switch (cmd->op_type) {
|
||||
case IS_CONST:
|
||||
case IS_TMP_VAR:
|
||||
@ -5830,27 +5788,21 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
SET_NODE(opline->op1, cmd);
|
||||
opline->op2.opline_num = 1;
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
/* FIXME: exception support not added to this op2 */
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
opline->extended_value = 1;
|
||||
opline->result.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result_type = IS_VAR;
|
||||
LITERAL_STR(opline->op1, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
|
||||
opline->op1_type = IS_CONST;
|
||||
GET_CACHE_SLOT(opline->op1.constant);
|
||||
opline->extended_value = 1;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.num = CG(context).nested_calls;
|
||||
GET_NODE(result, opline->result);
|
||||
|
||||
if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
|
||||
}
|
||||
if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + 2;
|
||||
if (CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + ZEND_CALL_FRAME_SLOT + 1;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -59,7 +59,6 @@ typedef struct _zend_compiler_context {
|
||||
int literals_size;
|
||||
int current_brk_cont;
|
||||
int backpatch_count;
|
||||
int nested_calls;
|
||||
int used_stack;
|
||||
int in_finally;
|
||||
HashTable *labels;
|
||||
@ -266,7 +265,6 @@ struct _zend_op_array {
|
||||
|
||||
zend_uint T;
|
||||
|
||||
zend_uint nested_calls;
|
||||
zend_uint used_stack;
|
||||
|
||||
zend_brk_cont_element *brk_cont_array;
|
||||
@ -336,12 +334,6 @@ union _zend_function {
|
||||
zend_internal_function internal_function;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _zend_function_state {
|
||||
zend_function *function;
|
||||
zval *arguments;
|
||||
} zend_function_state;
|
||||
|
||||
typedef struct _zend_function_call_entry {
|
||||
zend_function *fbc;
|
||||
zend_uint arg_num;
|
||||
@ -361,14 +353,26 @@ typedef struct _list_llist_element {
|
||||
znode value;
|
||||
} list_llist_element;
|
||||
|
||||
typedef struct _call_slot {
|
||||
zend_function *fbc;
|
||||
zend_class_entry *called_scope;
|
||||
zend_object *object;
|
||||
zend_uint num_additional_args;
|
||||
zend_bool is_ctor_call;
|
||||
zend_bool is_ctor_result_used;
|
||||
} call_slot;
|
||||
typedef struct _zend_call_frame zend_call_frame;
|
||||
|
||||
struct _zend_call_frame {
|
||||
zend_function *func;
|
||||
zend_uint num_args;
|
||||
zend_uint flags;
|
||||
zend_class_entry *called_scope;
|
||||
zend_object *object;
|
||||
zend_call_frame *prev;
|
||||
};
|
||||
|
||||
#define ZEND_CALL_CTOR (1 << 0)
|
||||
#define ZEND_CALL_CTOR_RESULT_USED (1 << 1)
|
||||
#define ZEND_CALL_DONE (1 << 2)
|
||||
|
||||
#define ZEND_CALL_FRAME_SLOT \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(zend_call_frame)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_CALL_ARG(call, n) \
|
||||
(((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
|
||||
|
||||
typedef enum _vm_frame_kind {
|
||||
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
|
||||
@ -380,7 +384,7 @@ typedef enum _vm_frame_kind {
|
||||
struct _zend_execute_data {
|
||||
struct _zend_op *opline; /* executed opline */
|
||||
zend_op_array *op_array; /* executed op_array */
|
||||
zend_function_state function_state; /* called function and arguments */
|
||||
zend_call_frame *call; /* current call */
|
||||
zend_object *object; /* current $this */
|
||||
zend_class_entry *scope; /* function scope (self) */
|
||||
zend_class_entry *called_scope; /* function called scope (static) */
|
||||
@ -393,8 +397,6 @@ struct _zend_execute_data {
|
||||
zval old_error_reporting;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zend_object *delayed_exception;
|
||||
call_slot *call_slots;
|
||||
call_slot *call;
|
||||
};
|
||||
|
||||
#define EX(element) execute_data.element
|
||||
@ -877,7 +879,7 @@ END_EXTERN_C()
|
||||
/* call op_array handler of extendions */
|
||||
#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
|
||||
|
||||
/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of ZEND_DO_FCALL */
|
||||
/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
|
||||
#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
|
||||
|
||||
/* don't perform early binding for classes inherited form internal ones;
|
||||
|
@ -1468,13 +1468,13 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC)
|
||||
{
|
||||
if (fci != NULL) {
|
||||
execute_data_ptr->function_state.function->internal_function.handler(
|
||||
execute_data_ptr->call->func->internal_function.handler(
|
||||
fci->param_count, fci->retval TSRMLS_CC
|
||||
);
|
||||
} else {
|
||||
zval *return_value = EX_VAR_2(execute_data_ptr, execute_data_ptr->opline->result.var);
|
||||
execute_data_ptr->function_state.function->internal_function.handler(
|
||||
execute_data_ptr->opline->extended_value + execute_data_ptr->call->num_additional_args, return_value TSRMLS_CC
|
||||
execute_data_ptr->call->func->internal_function.handler(
|
||||
execute_data_ptr->call->num_args, return_value TSRMLS_CC
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1536,12 +1536,10 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
|
||||
* | VAR[op_array->last_var] |
|
||||
* | ... |
|
||||
* | VAR[op_array->last_var+op_array->T-1] |
|
||||
* zend_vm_stack_frame_base -> +----------------------------------------+
|
||||
* EX(call_slot) -> | CALL_SLOT |
|
||||
* +----------------------------------------+
|
||||
* EX(call_slots) -> | CALL_SLOT[0] |
|
||||
* | ... |
|
||||
* | CALL_SLOT[op_array->nested_calls-1] |
|
||||
* +----------------------------------------+
|
||||
* zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
|
||||
* | ARGUMENTS STACK [0] |
|
||||
* | ... |
|
||||
* zend_vm_stack_top --------> | ... |
|
||||
* | ... |
|
||||
@ -1566,9 +1564,8 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
*/
|
||||
size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
|
||||
size_t vars_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (op_array->last_var + op_array->T);
|
||||
size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
|
||||
size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * op_array->used_stack;
|
||||
size_t total_size = execute_data_size + vars_size + call_slots_size + stack_size;
|
||||
size_t total_size = execute_data_size + vars_size + stack_size;
|
||||
|
||||
/*
|
||||
* Normally the execute_data is allocated on the VM stack (because it does
|
||||
@ -1585,7 +1582,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
* and the passed arguments
|
||||
*/
|
||||
int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
|
||||
size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (args_count + 1);
|
||||
size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (ZEND_CALL_FRAME_SLOT + args_count);
|
||||
|
||||
total_size += args_size + execute_data_size;
|
||||
|
||||
@ -1596,11 +1593,15 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
/* copy prev_execute_data */
|
||||
EX(prev_execute_data) = (zend_execute_data*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
|
||||
memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
|
||||
EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
|
||||
EX(prev_execute_data)->function_state.arguments = (zval*)(((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size - sizeof(zval)));
|
||||
EX(prev_execute_data)->call = (zend_call_frame*)(((char*)EX(prev_execute_data)) + sizeof(zend_execute_data));
|
||||
EX(prev_execute_data)->call->func = (zend_function*)op_array;
|
||||
EX(prev_execute_data)->call->num_args = args_count;
|
||||
EX(prev_execute_data)->call->flags = ZEND_CALL_DONE;
|
||||
EX(prev_execute_data)->call->called_scope = NULL;
|
||||
EX(prev_execute_data)->call->object = NULL;
|
||||
EX(prev_execute_data)->call->prev = NULL;
|
||||
|
||||
/* copy arguments */
|
||||
ZVAL_LONG(EX(prev_execute_data)->function_state.arguments, args_count);
|
||||
if (args_count > 0) {
|
||||
zval *arg_src = zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
|
||||
zval *arg_dst = zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
|
||||
@ -1619,13 +1620,10 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
EX(frame_kind) = frame_kind;
|
||||
ZVAL_UNDEF(&EX(old_error_reporting));
|
||||
EX(delayed_exception) = NULL;
|
||||
EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + vars_size);
|
||||
EX(call) = NULL;
|
||||
|
||||
EG(opline_ptr) = &EX(opline);
|
||||
EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
|
||||
EX(function_state).function = (zend_function *) op_array;
|
||||
EX(function_state).arguments = NULL;
|
||||
EX(op_array) = op_array;
|
||||
EX(object) = Z_OBJ(EG(This));
|
||||
EX(scope) = EG(scope);
|
||||
@ -1674,24 +1672,28 @@ ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, call_slot *call TSRMLS_DC) /* {{{ */
|
||||
static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, zend_call_frame *call TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
|
||||
return ARG_SHOULD_BE_SENT_BY_REF(call->fbc, arg_num);
|
||||
return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
|
||||
static zend_call_frame *zend_vm_stack_copy_call_frame(zend_call_frame *call TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_uint count;
|
||||
zend_call_frame *new_call;
|
||||
zend_vm_stack p = EG(argument_stack);
|
||||
|
||||
zend_vm_stack_extend(count + 1 TSRMLS_CC);
|
||||
zend_vm_stack_extend(ZEND_CALL_FRAME_SLOT + call->num_args TSRMLS_CC);
|
||||
|
||||
EG(argument_stack)->top += count;
|
||||
ZVAL_LONG(EG(argument_stack)->top, count);
|
||||
new_call = (zend_call_frame*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
|
||||
*new_call = *call;
|
||||
EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT + call->num_args;
|
||||
count = call->num_args;
|
||||
while (count-- > 0) {
|
||||
zval *data = --p->top;
|
||||
ZVAL_COPY_VALUE(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count, data);
|
||||
ZVAL_COPY_VALUE(ZEND_CALL_ARG(new_call, count), data);
|
||||
|
||||
if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
|
||||
zend_vm_stack r = p;
|
||||
@ -1701,18 +1703,16 @@ static zval *zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
|
||||
efree(r);
|
||||
}
|
||||
}
|
||||
return EG(argument_stack)->top++;
|
||||
return new_call;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline zval *zend_vm_stack_push_args(int count TSRMLS_DC) /* {{{ */
|
||||
static zend_always_inline void zend_vm_stack_adjust_call_frame(zend_call_frame **call TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
|
||||
if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < ZEND_CALL_FRAME_SLOT + (*call)->num_args)
|
||||
|| UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
|
||||
return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
|
||||
*call = zend_vm_stack_copy_call_frame(*call TSRMLS_CC);
|
||||
}
|
||||
ZVAL_LONG(EG(argument_stack)->top, count);
|
||||
return EG(argument_stack)->top++;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -221,6 +221,19 @@ static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
|
||||
return --EG(argument_stack)->top;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_call_frame *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_call_frame *prev TSRMLS_DC)
|
||||
{
|
||||
zend_call_frame * call = (zend_call_frame*)EG(argument_stack)->top;
|
||||
call->func = func;
|
||||
call->num_args = num_args;
|
||||
call->flags = flags;
|
||||
call->called_scope = called_scope;
|
||||
call->object = object;
|
||||
call->prev = prev;
|
||||
EG(argument_stack)->top += ZEND_CALL_FRAME_SLOT;
|
||||
return call;
|
||||
}
|
||||
|
||||
static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
|
||||
{
|
||||
zval *ret;
|
||||
@ -234,8 +247,7 @@ static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_frame_base(zend_execute_data *ex)
|
||||
{
|
||||
return (zval*)((char*)ex->call_slots +
|
||||
ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
|
||||
return EX_VAR_NUM_2(ex, ex->op_array->last_var + ex->op_array->T);
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
|
||||
@ -250,12 +262,13 @@ static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame(zend_call_frame *call, int nested TSRMLS_DC)
|
||||
{
|
||||
zval *p = EG(argument_stack)->top - 1;
|
||||
zend_uint num_args = call->num_args;
|
||||
|
||||
if (EXPECTED(Z_LVAL_P(p) > 0)) {
|
||||
zval *end = p - Z_LVAL_P(p);
|
||||
if (num_args > 0) {
|
||||
zval *p = ZEND_CALL_ARG(call, num_args + 1);
|
||||
zval *end = p - num_args;
|
||||
|
||||
do {
|
||||
p--;
|
||||
@ -263,27 +276,25 @@ static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC
|
||||
} while (p != end);
|
||||
}
|
||||
if (nested) {
|
||||
EG(argument_stack)->top = p;
|
||||
EG(argument_stack)->top = (zval*)call;
|
||||
} else {
|
||||
zend_vm_stack_free(p TSRMLS_CC);
|
||||
zend_vm_stack_free((zval*)call TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
|
||||
{
|
||||
zval *p = ex->function_state.arguments;
|
||||
return Z_LVAL_P(p);
|
||||
return ex->call->num_args;
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
|
||||
{
|
||||
zval *p = ex->function_state.arguments;
|
||||
int arg_count = Z_LVAL_P(p);
|
||||
int arg_count = ex->call->num_args;
|
||||
|
||||
if (UNEXPECTED(requested_arg > arg_count)) {
|
||||
return NULL;
|
||||
}
|
||||
return p - arg_count + requested_arg - 1;
|
||||
return ZEND_CALL_ARG(ex->call, requested_arg);
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
|
||||
|
@ -393,17 +393,24 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
|
||||
/* return class name and "::" or "". */
|
||||
ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
if (space) {
|
||||
*space = "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||
func = EG(current_execute_data)->call->func;
|
||||
} else {
|
||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
||||
}
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION:
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
{
|
||||
zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
|
||||
zend_class_entry *ce = func->common.scope;
|
||||
|
||||
if (space) {
|
||||
*space = ce ? "::" : "";
|
||||
@ -421,12 +428,19 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
|
||||
|
||||
ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||
func = EG(current_execute_data)->call->func;
|
||||
} else {
|
||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
||||
}
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION: {
|
||||
zend_string *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
|
||||
zend_string *function_name = func->common.function_name;
|
||||
|
||||
if (function_name) {
|
||||
return function_name->val;
|
||||
@ -436,7 +450,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
break;
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name->val;
|
||||
return func->common.function_name->val;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@ -655,6 +669,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_class_entry *called_scope = NULL;
|
||||
zend_execute_data execute_data;
|
||||
zend_fcall_info_cache fci_cache_local;
|
||||
zend_function *func;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
@ -719,7 +734,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
STR_RELEASE(callable_name);
|
||||
}
|
||||
|
||||
EX(function_state).function = fci_cache->function_handler;
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(ZEND_CALL_FRAME_SLOT + fci->param_count);
|
||||
|
||||
func = fci_cache->function_handler;
|
||||
EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
|
||||
calling_scope = fci_cache->calling_scope;
|
||||
called_scope = fci_cache->called_scope;
|
||||
fci->object = fci_cache->object;
|
||||
@ -729,24 +747,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
|
||||
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name->val, EX(function_state).function->common.function_name->val);
|
||||
if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
|
||||
if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", func->common.scope->name->val, func->common.function_name->val);
|
||||
}
|
||||
if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
|
||||
|
||||
for (i=0; i<fci->param_count; i++) {
|
||||
zval *param;
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
|
||||
// TODO: Scalar values don't have reference counters anymore.
|
||||
// They are assumed to be 1, and they may be easily passed by
|
||||
// reference now. However, previously scalars with refcount==1
|
||||
@ -766,19 +782,19 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
(!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) {
|
||||
|
||||
if (fci->no_separation &&
|
||||
!ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
|
||||
if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
|
||||
/* hack to clean up the stack */
|
||||
ZVAL_LONG(&tmp, i);
|
||||
zend_vm_stack_push(&tmp TSRMLS_CC);
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
||||
i+1,
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -797,7 +813,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
param = &fci->params[i];
|
||||
} else if (Z_ISREF(fci->params[i]) &&
|
||||
/* don't separate references for __call */
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
(func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
param = &tmp;
|
||||
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
|
||||
} else {
|
||||
@ -807,13 +823,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_vm_stack_push(param TSRMLS_CC);
|
||||
}
|
||||
|
||||
EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
|
||||
ZVAL_LONG(EX(function_state).arguments, fci->param_count);
|
||||
|
||||
EG(scope) = calling_scope;
|
||||
EG(called_scope) = called_scope;
|
||||
if (!fci->object ||
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
Z_OBJ(EG(This)) = NULL;
|
||||
} else {
|
||||
Z_OBJ(EG(This)) = fci->object;
|
||||
@ -823,9 +836,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
EX(prev_execute_data) = EG(current_execute_data);
|
||||
EG(current_execute_data) = &execute_data;
|
||||
|
||||
if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
|
||||
if (func->type == ZEND_USER_FUNCTION) {
|
||||
calling_symbol_table = EG(active_symbol_table);
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
EG(scope) = func->common.scope;
|
||||
if (fci->symbol_table) {
|
||||
EG(active_symbol_table) = fci->symbol_table;
|
||||
} else {
|
||||
@ -833,7 +846,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
}
|
||||
|
||||
original_op_array = EG(active_op_array);
|
||||
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
|
||||
EG(active_op_array) = (zend_op_array *) func;
|
||||
original_opline_ptr = EG(opline_ptr);
|
||||
|
||||
if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) {
|
||||
@ -848,15 +861,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
|
||||
}
|
||||
EG(active_symbol_table) = calling_symbol_table;
|
||||
} else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
ZVAL_NULL(fci->retval);
|
||||
if (EX(function_state).function->common.scope) {
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
if (func->common.scope) {
|
||||
EG(scope) = func->common.scope;
|
||||
}
|
||||
if (EXPECTED(zend_execute_internal == NULL)) {
|
||||
/* saves one function call if zend_execute_internal is not used */
|
||||
EX(function_state).function->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_execute_internal(&execute_data, fci TSRMLS_CC);
|
||||
}
|
||||
@ -880,22 +893,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
|
||||
/* Not sure what should be done here if it's a static method */
|
||||
if (fci->object) {
|
||||
fci->object->handlers->call_method(EX(function_state).function->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
|
||||
}
|
||||
|
||||
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
STR_RELEASE(EX(function_state).function->common.function_name);
|
||||
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
STR_RELEASE(func->common.function_name);
|
||||
}
|
||||
efree(EX(function_state).function);
|
||||
efree(func);
|
||||
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(fci->retval);
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
}
|
||||
}
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
|
||||
|
||||
if (Z_OBJ(EG(This))) {
|
||||
zval_ptr_dtor(&EG(This));
|
||||
|
@ -87,11 +87,11 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
|
||||
|
||||
/* If yield was used as a function argument there may be active
|
||||
* method calls those objects need to be freed */
|
||||
while (execute_data->call >= execute_data->call_slots) {
|
||||
while (execute_data->call) {
|
||||
if (execute_data->call->object) {
|
||||
OBJ_RELEASE(execute_data->call->object);
|
||||
}
|
||||
execute_data->call--;
|
||||
execute_data->call = execute_data->call->prev;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@ -133,11 +133,10 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
* generator (for func_get_args) so those have to be freed too. */
|
||||
{
|
||||
zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
|
||||
zval *arguments = prev_execute_data->function_state.arguments;
|
||||
|
||||
if (arguments) {
|
||||
int arguments_count = Z_LVAL_P(arguments);
|
||||
zval *arguments_start = arguments - arguments_count;
|
||||
if (prev_execute_data->call) {
|
||||
int arguments_count = prev_execute_data->call->num_args;
|
||||
zval *arguments_start = ZEND_CALL_ARG(prev_execute_data->call, 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < arguments_count; ++i) {
|
||||
|
@ -905,7 +905,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{
|
||||
|
||||
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
||||
{
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
|
||||
zval method_name, method_args;
|
||||
zval method_result;
|
||||
zend_class_entry *ce = Z_OBJCE_P(getThis());
|
||||
@ -1123,7 +1123,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str
|
||||
|
||||
ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
||||
{
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
|
||||
zval method_name, method_args;
|
||||
zval method_result;
|
||||
zend_class_entry *ce = EG(scope);
|
||||
|
@ -70,7 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
|
||||
|
||||
op_array->T = 0;
|
||||
|
||||
op_array->nested_calls = 0;
|
||||
op_array->used_stack = 0;
|
||||
|
||||
op_array->function_name = NULL;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -83,7 +83,7 @@ const char *zend_vm_opcodes_map[169] = {
|
||||
"ZEND_END_SILENCE",
|
||||
"ZEND_INIT_FCALL_BY_NAME",
|
||||
"ZEND_DO_FCALL",
|
||||
"ZEND_DO_FCALL_BY_NAME",
|
||||
"ZEND_INIT_FCALL",
|
||||
"ZEND_RETURN",
|
||||
"ZEND_RECV",
|
||||
"ZEND_RECV_INIT",
|
||||
|
@ -84,7 +84,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
||||
#define ZEND_END_SILENCE 58
|
||||
#define ZEND_INIT_FCALL_BY_NAME 59
|
||||
#define ZEND_DO_FCALL 60
|
||||
#define ZEND_DO_FCALL_BY_NAME 61
|
||||
#define ZEND_INIT_FCALL 61
|
||||
#define ZEND_RETURN 62
|
||||
#define ZEND_RECV 63
|
||||
#define ZEND_RECV_INIT 64
|
||||
|
@ -1958,7 +1958,6 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_ASSIGN_REF:
|
||||
case ZEND_DO_FCALL:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
|
||||
ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
|
||||
|
@ -108,8 +108,8 @@ static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_c
|
||||
end = opline + op_array->last;
|
||||
while (opline < end) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_DO_FCALL:
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_FUNC, 1, 1, 1);
|
||||
case ZEND_INIT_FCALL:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
|
||||
break;
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
|
||||
|
@ -12,9 +12,15 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
zend_op *opline = op_array->opcodes;
|
||||
zend_op *end = opline + op_array->last;
|
||||
int call = 0;
|
||||
void *checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
optimizer_call_info *call_stack = zend_arena_calloc(&ctx->arena, op_array->nested_calls + 1, sizeof(optimizer_call_info));
|
||||
void *checkpoint;
|
||||
optimizer_call_info *call_stack;
|
||||
|
||||
if (op_array->last < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
call_stack = zend_arena_calloc(&ctx->arena, op_array->last / 2, sizeof(optimizer_call_info));
|
||||
while (opline < end) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
@ -31,23 +37,27 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
case ZEND_NEW:
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_INIT_FCALL:
|
||||
call_stack[call].opline = opline;
|
||||
call++;
|
||||
break;
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
case ZEND_DO_FCALL:
|
||||
call--;
|
||||
if (call_stack[call].func && call_stack[call].opline) {
|
||||
zend_op *fcall = call_stack[call].opline;
|
||||
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
ZEND_OP1_TYPE(opline) = IS_CONST;
|
||||
opline->op1.constant = fcall->op2.constant + 1;
|
||||
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
|
||||
literal_dtor(&ZEND_OP2_LITERAL(fcall));
|
||||
if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
|
||||
if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
|
||||
fcall->opcode = ZEND_INIT_FCALL;
|
||||
literal_dtor(&ZEND_OP2_LITERAL(fcall));
|
||||
fcall->op2.constant = fcall->op2.constant + 1;
|
||||
} else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
|
||||
fcall->opcode = ZEND_INIT_FCALL;
|
||||
literal_dtor(&op_array->literals[fcall->op2.constant]);
|
||||
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
|
||||
fcall->op2.constant = fcall->op2.constant + 1;
|
||||
} else {
|
||||
ZEND_ASSERT(0);
|
||||
}
|
||||
MAKE_NOP(fcall);
|
||||
} else if (opline->extended_value == 0 &&
|
||||
call_stack[call].opline &&
|
||||
call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME &&
|
||||
@ -55,12 +65,9 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
|
||||
zend_op *fcall = call_stack[call].opline;
|
||||
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
ZEND_OP1_TYPE(opline) = IS_CONST;
|
||||
opline->op1.constant = fcall->op2.constant + 1;
|
||||
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
|
||||
fcall->opcode = ZEND_INIT_FCALL;
|
||||
literal_dtor(&ZEND_OP2_LITERAL(fcall));
|
||||
MAKE_NOP(fcall);
|
||||
fcall->op2.constant = fcall->op2.constant + 1;
|
||||
}
|
||||
call_stack[call].func = NULL;
|
||||
call_stack[call].opline = NULL;
|
||||
@ -79,21 +86,21 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAL:
|
||||
if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
|
||||
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
|
||||
if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
|
||||
/* We won't convert it into_DO_FCALL to emit error at run-time */
|
||||
call_stack[call - 1].opline = NULL;
|
||||
} else {
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR:
|
||||
if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
|
||||
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
|
||||
opline->opcode = ZEND_SEND_REF;
|
||||
}
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
@ -104,12 +111,12 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
} else {
|
||||
opline->opcode = ZEND_SEND_VAR;
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_REF:
|
||||
if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
|
||||
if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND && call_stack[call - 1].func) {
|
||||
/* We won't handle run-time pass by reference */
|
||||
call_stack[call - 1].opline = NULL;
|
||||
}
|
||||
|
@ -320,22 +320,25 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ZEND_DO_FCALL:
|
||||
case ZEND_INIT_FCALL:
|
||||
/* define("name", scalar); */
|
||||
if (collect_constants &&
|
||||
opline->extended_value == 2 &&
|
||||
ZEND_OP1_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 &&
|
||||
zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
|
||||
(opline-1)->opcode == ZEND_SEND_VAL &&
|
||||
ZEND_OP1_TYPE(opline-1) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_STRING &&
|
||||
(opline-2)->opcode == ZEND_SEND_VAL &&
|
||||
ZEND_OP1_TYPE(opline-2) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
|
||||
zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
|
||||
break;
|
||||
ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("define")-1 &&
|
||||
zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), "define", sizeof("define")-1) == 0) {
|
||||
|
||||
if ((opline+1)->opcode == ZEND_SEND_VAL &&
|
||||
ZEND_OP1_TYPE(opline+1) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline+1)) == IS_STRING &&
|
||||
(opline+2)->opcode == ZEND_SEND_VAL &&
|
||||
ZEND_OP1_TYPE(opline+2) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline+2)) <= IS_STRING &&
|
||||
(opline+3)->opcode == ZEND_DO_FCALL) {
|
||||
|
||||
zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline+1), &ZEND_OP1_LITERAL(opline+2));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* don't colllect constants after any other function call */
|
||||
collect_constants = 0;
|
||||
@ -348,40 +351,42 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
is_callable(x)
|
||||
extension_loaded(x)
|
||||
*/
|
||||
if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL &&
|
||||
ZEND_OP1_TYPE(opline - 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline - 1)) == IS_STRING &&
|
||||
ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
if ((opline + 1)->opcode == ZEND_SEND_VAL &&
|
||||
(opline + 2)->opcode == ZEND_DO_FCALL &&
|
||||
ZEND_OP1_TYPE(opline + 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline + 1)) == IS_STRING &&
|
||||
ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
if ((Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("function_exists")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"function_exists", sizeof("function_exists")-1)) ||
|
||||
(Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
(Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("is_callable")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"is_callable", sizeof("is_callable")))) {
|
||||
zend_internal_function *func;
|
||||
char *lc_name = zend_str_tolower_dup(
|
||||
Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
|
||||
Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
|
||||
|
||||
if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)))) != NULL &&
|
||||
if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)))) != NULL &&
|
||||
func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
func->module->type == MODULE_PERSISTENT) {
|
||||
zval t;
|
||||
ZVAL_BOOL(&t, 1);
|
||||
if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
|
||||
MAKE_NOP((opline - 1));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
|
||||
MAKE_NOP(opline + 1);
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
}
|
||||
efree(lc_name);
|
||||
} else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"extension_loaded", sizeof("extension_loaded")-1)) {
|
||||
zval t;
|
||||
char *lc_name = zend_str_tolower_dup(
|
||||
Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
|
||||
Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
|
||||
zend_module_entry *m = zend_hash_str_find_ptr(&module_registry,
|
||||
lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
|
||||
lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
|
||||
|
||||
efree(lc_name);
|
||||
if (!m) {
|
||||
@ -398,51 +403,55 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
}
|
||||
}
|
||||
|
||||
if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
|
||||
MAKE_NOP((opline - 1));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
|
||||
MAKE_NOP(opline + 1);
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
} else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("defined")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"defined", sizeof("defined")-1)) {
|
||||
zval t;
|
||||
|
||||
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) {
|
||||
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) {
|
||||
|
||||
ZVAL_BOOL(&t, 1);
|
||||
if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
|
||||
MAKE_NOP((opline - 1));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
|
||||
MAKE_NOP(opline + 1);
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
}
|
||||
} else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("constant")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"constant", sizeof("constant")-1)) {
|
||||
zval t;
|
||||
|
||||
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 1 TSRMLS_CC)) {
|
||||
if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
|
||||
MAKE_NOP((opline - 1));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) {
|
||||
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
|
||||
MAKE_NOP(opline + 1);
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
}
|
||||
} else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("strlen")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"strlen", sizeof("strlen")-1)) {
|
||||
zval t;
|
||||
|
||||
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
|
||||
if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
|
||||
MAKE_NOP((opline - 1));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
|
||||
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
|
||||
MAKE_NOP(opline + 1);
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -485,7 +494,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
case ZEND_FE_RESET:
|
||||
case ZEND_FE_FETCH:
|
||||
case ZEND_NEW:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
case ZEND_DO_FCALL:
|
||||
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
|
||||
case ZEND_JMP_SET:
|
||||
#endif
|
||||
|
@ -178,12 +178,6 @@ static void update_op1_const(zend_op_array *op_array,
|
||||
zend_optimizer_add_literal(op_array, val TSRMLS_CC);
|
||||
STR_HASH_VAL(Z_STR(op_array->literals[opline->op1.constant+1]));
|
||||
break;
|
||||
case ZEND_DO_FCALL:
|
||||
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
|
||||
STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
|
||||
break;
|
||||
default:
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
|
||||
STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
|
||||
@ -204,6 +198,13 @@ static void update_op2_const(zend_op_array *op_array,
|
||||
{
|
||||
ZEND_OP2_TYPE(opline) = IS_CONST;
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
|
||||
if (opline->opcode == ZEND_INIT_FCALL) {
|
||||
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
|
||||
STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
|
||||
return;
|
||||
}
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
|
||||
@ -340,9 +341,9 @@ static int replace_var_by_const(zend_op_array *op_array,
|
||||
if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
|
||||
return 0;
|
||||
}
|
||||
opline->extended_value = ZEND_DO_FCALL;
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
} else {
|
||||
opline->extended_value = ZEND_DO_FCALL_BY_NAME;
|
||||
opline->extended_value = 0;
|
||||
}
|
||||
opline->opcode = ZEND_SEND_VAL;
|
||||
break;
|
||||
|
@ -44,7 +44,7 @@
|
||||
#define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX)
|
||||
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
|
||||
# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; }
|
||||
# define MAKE_NOP(opline) { (opline)->opcode = ZEND_NOP; memset(&(opline)->result, 0, sizeof((opline)->result)); memset(&(opline)->op1, 0, sizeof((opline)->op1)); memset(&(opline)->op2, 0, sizeof((opline)->op2));(opline)->result_type=(opline)->op1_type=(opline)->op2_type=IS_UNUSED; (opline)->handler = zend_opcode_handlers[ZEND_NOP]; }
|
||||
# define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
|
||||
# define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)
|
||||
# define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
|
||||
|
@ -1102,7 +1102,6 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */
|
||||
|
||||
memset(&execute_data, 0, sizeof(zend_execute_data));
|
||||
EG(current_execute_data) = &execute_data;
|
||||
EX(function_state).function = pce->constructor;
|
||||
zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, &arg);
|
||||
|
||||
if (EG(exception)) {
|
||||
|
@ -74,9 +74,10 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
|
||||
|
||||
fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
|
||||
|
||||
if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
|
||||
return -1;
|
||||
}
|
||||
// TODO: fpm_php_trace_dump() has be reimplemented ???
|
||||
//??? if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
|
||||
//??? return -1;
|
||||
//??? }
|
||||
|
||||
function = l;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user