Browse Source

Redesigned zend_execute_data layout now EX(object), EX(scope) and EX(called_scope) arr properties of the current function execution co

ntext. They are set during zend_execute_data initialization and never changed.
pull/678/head
Dmitry Stogov 12 years ago
parent
commit
65e2ed6e50
  1. 45
      Zend/zend_builtin_functions.c
  2. 25
      Zend/zend_compile.h
  3. 68
      Zend/zend_execute.c
  4. 34
      Zend/zend_execute_API.c
  5. 17
      Zend/zend_generators.c
  6. 131
      Zend/zend_vm_def.h
  7. 134
      Zend/zend_vm_execute.h
  8. 1
      sapi/phpdbg/phpdbg.c
  9. 12
      sapi/phpdbg/phpdbg_frame.c

45
Zend/zend_builtin_functions.c

@ -1991,6 +1991,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
ZEND_FUNCTION(debug_print_backtrace)
{
zend_execute_data *ptr, *skip;
zend_object *object;
int lineno, frameno = 0;
const char *function_name;
const char *filename;
@ -2010,6 +2011,7 @@ ZEND_FUNCTION(debug_print_backtrace)
ptr = EG(current_execute_data);
/* skip debug_backtrace() */
object = ptr->object;
ptr = ptr->prev_execute_data;
while (ptr && (limit == 0 || frameno < limit)) {
@ -2037,11 +2039,18 @@ ZEND_FUNCTION(debug_print_backtrace)
lineno = 0;
}
/* $this may be passed into regular internal functions */
if (object &&
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
!ptr->function_state.function->common.scope) {
object = NULL;
}
function_name = (ptr->function_state.function->common.scope &&
ptr->function_state.function->common.scope->trait_aliases) ?
zend_resolve_method_name(
ptr->object ?
zend_get_class_entry(ptr->object TSRMLS_CC) :
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 ?
@ -2049,11 +2058,11 @@ ZEND_FUNCTION(debug_print_backtrace)
NULL);
if (function_name) {
if (ptr->object) {
if (object) {
if (ptr->function_state.function->common.scope) {
class_name = ptr->function_state.function->common.scope->name;
} else {
class_name = zend_get_object_classname(ptr->object TSRMLS_CC);
class_name = zend_get_object_classname(object TSRMLS_CC);
}
call_type = "->";
@ -2141,6 +2150,7 @@ ZEND_FUNCTION(debug_print_backtrace)
}
}
include_filename = filename;
object = skip->object;
ptr = skip->prev_execute_data;
++indent;
}
@ -2151,6 +2161,7 @@ ZEND_FUNCTION(debug_print_backtrace)
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
{
zend_execute_data *ptr, *skip;
zend_object *object = Z_OBJ(EG(This));
int lineno, frameno = 0;
const char *function_name;
const char *filename;
@ -2162,11 +2173,13 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
/* skip "new Exception()" */
if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
object = ptr->object;
ptr = ptr->prev_execute_data;
}
/* skip debug_backtrace() */
if (skip_last-- && ptr) {
object = ptr->object;
ptr = ptr->prev_execute_data;
}
@ -2217,11 +2230,18 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
filename = NULL;
}
/* $this may be passed into regular internal functions */
if (object &&
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
!ptr->function_state.function->common.scope) {
object = NULL;
}
function_name = (ptr->function_state.function->common.scope &&
ptr->function_state.function->common.scope->trait_aliases) ?
zend_resolve_method_name(
ptr->object ?
zend_get_class_entry(ptr->object TSRMLS_CC) :
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 ?
@ -2231,19 +2251,19 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if (function_name) {
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
if (ptr->object) {
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));
} else {
class_name = zend_get_object_classname(ptr->object TSRMLS_CC);
class_name = zend_get_object_classname(object TSRMLS_CC);
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
}
if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
zval object;
ZVAL_OBJ(&object, ptr->object);
add_assoc_zval_ex(&stack_frame, "object", sizeof("object")-1, &object);
Z_ADDREF(object);
zval zv;
ZVAL_OBJ(&zv, object);
add_assoc_zval_ex(&stack_frame, "object", sizeof("object")-1, &zv);
Z_ADDREF(zv);
}
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
@ -2314,6 +2334,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
include_filename = filename;
object = skip->object;
ptr = skip->prev_execute_data;
}
}

25
Zend/zend_compile.h

@ -374,20 +374,19 @@ typedef enum _vm_frame_kind {
} vm_frame_kind;
struct _zend_execute_data {
struct _zend_op *opline;
void **run_time_cache;
zend_function_state function_state;
zend_op_array *op_array;
zend_object *object;
zend_array *symbol_table;
struct _zend_execute_data *prev_execute_data;
struct _zend_op *opline; /* executed opline */
zend_op_array *op_array; /* executed op_array */
zend_function_state function_state; /* called function and arguments */
zend_object *object; /* current $this */
zend_class_entry *scope; /* function scope (self) */
zend_class_entry *called_scope; /* function called scope (static) */
zend_array *symbol_table;
void **run_time_cache;
zend_execute_data *prev_execute_data;
zval *return_value;
vm_frame_kind frame_kind;
// TODO: simplify call sequence and remove call_* ???
zval old_error_reporting;
vm_frame_kind frame_kind;
zval *return_value;
// TODO: simplify call sequence and remove current_* and call_* ???
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zend_object *current_this;
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
zend_object *delayed_exception;
call_slot *call_slots;

68
Zend/zend_execute.c

@ -1624,52 +1624,50 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
EX(prev_execute_data) = EG(current_execute_data);
}
do {
/* Initialize CV variables */
zval *var = EX_VAR_NUM(0);
zval *end = var + op_array->last_var;
while (var != end) {
ZVAL_UNDEF(var);
var++;
}
} while (0);
EX(return_value) = return_value;
EX(frame_kind) = frame_kind;
ZVAL_UNDEF(&EX(old_error_reporting));
EX(delayed_exception) = NULL;
EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + vars_size);
EX(call) = NULL;
EG(opline_ptr) = &EX(opline);
EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL;
EX(op_array) = op_array;
EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
EX(object) = NULL;
EX(current_this) = NULL;
ZVAL_UNDEF(&EX(old_error_reporting));
EX(object) = Z_OBJ(EG(This));
EX(scope) = EG(scope);
EX(called_scope) = EG(called_scope);
EX(symbol_table) = EG(active_symbol_table);
EX(call) = NULL;
EG(current_execute_data) = execute_data;
EX(frame_kind) = frame_kind;
EX(delayed_exception) = NULL;
EX(return_value) = return_value;
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
if (EX(symbol_table)) {
zend_attach_symbol_table(execute_data);
}
} else {
do {
/* Initialize CV variables */
zval *var = EX_VAR_NUM(0);
zval *end = var + op_array->last_var;
while (var != end) {
ZVAL_UNDEF(var);
var++;
}
} while (0);
if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
ZVAL_COPY(EX_VAR(op_array->this_var), &EG(This));
if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EG(This)));
Z_ADDREF(EG(This));
}
}
EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
EG(opline_ptr) = &EX(opline);
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL;
EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
EG(current_execute_data) = execute_data;
return execute_data;
}

34
Zend/zend_execute_API.c

@ -770,11 +770,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_array *calling_symbol_table;
zend_op_array *original_op_array;
zend_op **original_opline_ptr;
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zend_class_entry *calling_scope = NULL;
zend_class_entry *called_scope = NULL;
zend_object *current_this;
zend_execute_data execute_data;
zend_fcall_info_cache fci_cache_local;
zval tmp;
@ -800,9 +797,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
/* Initialize execute_data */
if (EG(current_execute_data)) {
execute_data = *EG(current_execute_data);
EX(object) = Z_OBJ(EG(This));
EX(scope) = EG(scope);
EX(called_scope) = EG(called_scope);
EX(op_array) = NULL;
EX(opline) = NULL;
EX(object) = NULL;
} else {
/* This only happens when we're called outside any execute()'s
* It shouldn't be strictly necessary to NULL execute_data out,
@ -842,7 +841,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EX(function_state).function = fci_cache->function_handler;
calling_scope = fci_cache->calling_scope;
called_scope = fci_cache->called_scope;
EX(object) = fci->object = fci_cache->object;
fci->object = fci_cache->object;
if (fci->object &&
(!EG(objects_store).object_buckets ||
!IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
@ -916,18 +915,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
ZVAL_LONG(&tmp, fci->param_count);
zend_vm_stack_push(&tmp TSRMLS_CC);
current_scope = EG(scope);
EG(scope) = calling_scope;
current_this = Z_OBJ(EG(This));
current_called_scope = EG(called_scope);
if (called_scope) {
EG(called_scope) = called_scope;
} else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
EG(called_scope) = NULL;
}
EG(called_scope) = called_scope;
if (!fci->object ||
(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
Z_OBJ(EG(This)) = NULL;
@ -1016,9 +1005,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
if (Z_OBJ(EG(This))) {
zval_ptr_dtor(&EG(This));
}
EG(called_scope) = current_called_scope;
EG(scope) = current_scope;
Z_OBJ(EG(This)) = current_this;
Z_OBJ(EG(This)) = EX(object);
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
EG(current_execute_data) = EX(prev_execute_data);
if (EG(exception)) {
@ -1711,12 +1701,6 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
}
ex->symbol_table = EG(active_symbol_table);
if (ex->op_array->this_var != -1 &&
Z_TYPE_P(EX_VAR_2(ex, ex->op_array->this_var)) == IS_UNDEF &&
Z_OBJ(EG(This))) {
ZVAL_COPY_VALUE(EX_VAR_2(ex, ex->op_array->this_var), &EG(This));
}
for (i = 0; i < ex->op_array->last_var; i++) {
zval zv;

17
Zend/zend_generators.c

@ -118,8 +118,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
}
if (execute_data->current_this) {
OBJ_RELEASE(execute_data->current_this);
if (execute_data->object) {
OBJ_RELEASE(execute_data->object);
}
/* A fatal error / die occurred during the generator execution. Trying to clean
@ -298,13 +298,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
Z_ADDREF(EG(This));
}
/* Back up executor globals. */
execute_data->current_scope = EG(scope);
execute_data->current_called_scope = EG(called_scope);
execute_data->symbol_table = EG(active_symbol_table);
execute_data->current_this = Z_OBJ(EG(This));
/* 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->execute_data = execute_data;
generator->stack = EG(argument_stack);
@ -355,9 +350,9 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
EG(opline_ptr) = &generator->execute_data->opline;
EG(active_op_array) = generator->execute_data->op_array;
EG(active_symbol_table) = generator->execute_data->symbol_table;
Z_OBJ(EG(This)) = generator->execute_data->current_this;
EG(scope) = generator->execute_data->current_scope;
EG(called_scope) = generator->execute_data->current_called_scope;
Z_OBJ(EG(This)) = generator->execute_data->object;
EG(scope) = generator->execute_data->scope;
EG(called_scope) = generator->execute_data->called_scope;
EG(argument_stack) = generator->stack;
/* We want the backtrace to look as if the generator function was

131
Zend/zend_vm_def.h

@ -1805,11 +1805,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
}
zval_ptr_dtor(&EG(This));
if (!Z_DELREF(EG(This))) {
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
}
}
Z_OBJ(EG(This)) = EX(current_this);
EG(scope) = EX(current_scope);
EG(called_scope) = EX(current_called_scope);
Z_OBJ(EG(This)) = EX(object);
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
EX(call)--;
@ -1878,12 +1882,12 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
{
USE_OPLINE
zend_bool should_change_scope = 0;
zend_function *fbc = EX(function_state).function;
zend_object *object;
zend_uint num_args;
SAVE_OPLINE();
EX(object) = EX(call)->object;
object = EX(call)->object;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@ -1900,7 +1904,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
if (fbc->common.scope &&
!(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
!object) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
@ -1915,17 +1919,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
}
if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
should_change_scope = 1;
EX(current_this) = Z_OBJ(EG(This));
EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
Z_OBJ(EG(This)) = EX(object);
//??? EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
}
if (UNEXPECTED(EX(call)->num_additional_args != 0)) {
num_args = opline->extended_value + EX(call)->num_additional_args;
EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
@ -1940,6 +1933,17 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
int should_change_scope = 0;
zval *ret;
if (fbc->common.scope) {
should_change_scope = 1;
Z_OBJ(EG(This)) = object;
//??? EG(scope) = (object) ? NULL : fbc->common.scope;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
}
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
zend_uint i;
zval *p = EX(function_state).arguments - num_args;
@ -1947,30 +1951,44 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
for (i = 0; i < num_args; ++i, ++p) {
zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
}
if (UNEXPECTED(EG(exception) != NULL)) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_UNDEF(EX_VAR(opline->result.var));
}
if (UNEXPECTED(should_change_scope)) {
ZEND_VM_C_GOTO(fcall_end_change_scope);
} else {
ZEND_VM_C_GOTO(fcall_end);
}
}
}
if (EXPECTED(EG(exception) == NULL)) {
zval *ret = EX_VAR(opline->result.var);
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(num_args, ret TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL TSRMLS_CC);
}
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(num_args, ret TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(ret);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(ret);
}
} else if (RETURN_VALUE_USED(opline)) {
ZVAL_UNDEF(EX_VAR(opline->result.var));
if (UNEXPECTED(should_change_scope)) {
ZEND_VM_C_GOTO(fcall_end_change_scope);
} else {
ZEND_VM_C_GOTO(fcall_end);
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
zval *return_value = NULL;
Z_OBJ(EG(This)) = object;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
EG(active_symbol_table) = NULL;
EG(active_op_array) = &fbc->op_array;
if (RETURN_VALUE_USED(opline)) {
@ -2000,11 +2018,16 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
Z_OBJ(EG(This)) = object;
//??? EG(scope) = NULL;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
ZVAL_NULL(EX_VAR(opline->result.var));
/* Not sure what should be done here if it's a static method */
if (EXPECTED(EX(object) != NULL)) {
EX(object)->handlers->call_method(fbc->common.function_name, EX(object), num_args, EX_VAR(opline->result.var) TSRMLS_CC);
if (EXPECTED(object != NULL)) {
object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
@ -2023,26 +2046,31 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
}
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
if (should_change_scope) {
if (Z_OBJ(EG(This))) {
if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
if (EX(call)->is_ctor_result_used) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
ZEND_VM_C_LABEL(fcall_end_change_scope):
if (Z_OBJ(EG(This))) {
if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
if (EX(call)->is_ctor_result_used) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
zval_ptr_dtor(&EG(This));
}
Z_OBJ(EG(This)) = EX(current_this);
EG(scope) = EX(current_scope);
EG(called_scope) = EX(current_called_scope);
if (!Z_DELREF(EG(This))) {
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
}
}
Z_OBJ(EG(This)) = EX(object);
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
ZEND_VM_C_LABEL(fcall_end):
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
EX(call)--;
zend_vm_stack_clear_multiple(1 TSRMLS_CC);
@ -3923,7 +3951,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
}
EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);

134
Zend/zend_vm_execute.h

@ -414,11 +414,15 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
}
zval_ptr_dtor(&EG(This));
if (!Z_DELREF(EG(This))) {
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
}
}
Z_OBJ(EG(This)) = EX(current_this);
EG(scope) = EX(current_scope);
EG(called_scope) = EX(current_called_scope);
Z_OBJ(EG(This)) = EX(object);
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
EX(call)--;
@ -487,12 +491,12 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_bool should_change_scope = 0;
zend_function *fbc = EX(function_state).function;
zend_object *object;
zend_uint num_args;
SAVE_OPLINE();
EX(object) = EX(call)->object;
object = EX(call)->object;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@ -509,7 +513,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
if (fbc->common.scope &&
!(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
!object) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
@ -524,17 +528,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
}
if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
should_change_scope = 1;
EX(current_this) = Z_OBJ(EG(This));
EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
Z_OBJ(EG(This)) = EX(object);
//??? EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
}
if (UNEXPECTED(EX(call)->num_additional_args != 0)) {
num_args = opline->extended_value + EX(call)->num_additional_args;
EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
@ -549,6 +542,17 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
int should_change_scope = 0;
zval *ret;
if (fbc->common.scope) {
should_change_scope = 1;
Z_OBJ(EG(This)) = object;
//??? EG(scope) = (object) ? NULL : fbc->common.scope;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
}
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
zend_uint i;
zval *p = EX(function_state).arguments - num_args;
@ -556,30 +560,44 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
for (i = 0; i < num_args; ++i, ++p) {
zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
}
if (UNEXPECTED(EG(exception) != NULL)) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_UNDEF(EX_VAR(opline->result.var));
}
if (UNEXPECTED(should_change_scope)) {
goto fcall_end_change_scope;
} else {
goto fcall_end;
}
}
}
if (EXPECTED(EG(exception) == NULL)) {
zval *ret = EX_VAR(opline->result.var);
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(num_args, ret TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL TSRMLS_CC);
}
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(num_args, ret TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(ret);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(ret);
}
} else if (RETURN_VALUE_USED(opline)) {
ZVAL_UNDEF(EX_VAR(opline->result.var));
if (UNEXPECTED(should_change_scope)) {
goto fcall_end_change_scope;
} else {
goto fcall_end;
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
zval *return_value = NULL;
Z_OBJ(EG(This)) = object;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
EG(active_symbol_table) = NULL;
EG(active_op_array) = &fbc->op_array;
if (RETURN_VALUE_USED(opline)) {
@ -609,11 +627,16 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
Z_OBJ(EG(This)) = object;
//??? EG(scope) = NULL;
EG(scope) = fbc->common.scope;
EG(called_scope) = EX(call)->called_scope;
ZVAL_NULL(EX_VAR(opline->result.var));
/* Not sure what should be done here if it's a static method */
if (EXPECTED(EX(object) != NULL)) {
EX(object)->handlers->call_method(fbc->common.function_name, EX(object), num_args, EX_VAR(opline->result.var) TSRMLS_CC);
if (EXPECTED(object != NULL)) {
object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
@ -632,26 +655,31 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
}
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
if (should_change_scope) {
if (Z_OBJ(EG(This))) {
if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
if (EX(call)->is_ctor_result_used) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
fcall_end_change_scope:
if (Z_OBJ(EG(This))) {
if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
if (EX(call)->is_ctor_result_used) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
}
zval_ptr_dtor(&EG(This));
}
Z_OBJ(EG(This)) = EX(current_this);
EG(scope) = EX(current_scope);
EG(called_scope) = EX(current_called_scope);
if (!Z_DELREF(EG(This))) {
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
}
}
Z_OBJ(EG(This)) = EX(object);
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
fcall_end:
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
EX(call)--;
zend_vm_stack_clear_multiple(1 TSRMLS_CC);
@ -2916,7 +2944,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
}
EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
@ -7953,7 +7980,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
}
EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
@ -13058,7 +13084,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
}
EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
@ -29866,7 +29891,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
}
EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);

1
sapi/phpdbg/phpdbg.c

@ -613,7 +613,6 @@ const char phpdbg_ini_hardcoded[] =
/* overwriteable ini defaults must be set in phpdbg_ini_defaults() */
#define INI_DEFAULT(name, value) \
Z_SET_REFCOUNT(tmp, 0); \
ZVAL_STRINGL(&tmp, value, sizeof(value) - 1); \
zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp);

12
sapi/phpdbg/phpdbg_frame.c

@ -40,9 +40,9 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */
EG(opline_ptr) = &PHPDBG_EX(opline);
EG(active_op_array) = PHPDBG_EX(op_array);
EG(active_symbol_table) = PHPDBG_EX(symbol_table);
Z_OBJ(EG(This)) = PHPDBG_EX(current_this);
EG(scope) = PHPDBG_EX(current_scope);
EG(called_scope) = PHPDBG_EX(current_called_scope);
Z_OBJ(EG(This)) = PHPDBG_EX(object);
EG(scope) = PHPDBG_EX(scope);
EG(called_scope) = PHPDBG_EX(called_scope);
} /* }}} */
void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
@ -82,9 +82,9 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
EG(opline_ptr) = &PHPDBG_EX(opline);
EG(active_op_array) = PHPDBG_EX(op_array);
EG(active_symbol_table) = PHPDBG_EX(symbol_table);
Z_OBJ(EG(This)) = PHPDBG_EX(current_this);
EG(scope) = PHPDBG_EX(current_scope);
EG(called_scope) = PHPDBG_EX(current_called_scope);
Z_OBJ(EG(This)) = PHPDBG_EX(object);
EG(scope) = PHPDBG_EX(scope);
EG(called_scope) = PHPDBG_EX(called_scope);
}
phpdbg_notice("Switched to frame #%d", frame);

Loading…
Cancel
Save