ntext. They are set during zend_execute_data initialization and never changed.
ZEND_FUNCTION(debug_print_backtrace)
{
zend_execute_data *ptr, *skip;
+ zend_object *object;
int lineno, frameno = 0;
const char *function_name;
const char *filename;
ptr = EG(current_execute_data);
/* skip debug_backtrace() */
+ object = ptr->object;
ptr = ptr->prev_execute_data;
while (ptr && (limit == 0 || frameno < limit)) {
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 ?
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 = "->";
}
}
include_filename = filename;
+ object = skip->object;
ptr = skip->prev_execute_data;
++indent;
}
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;
/* 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;
}
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 ?
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, "->");
include_filename = filename;
+ object = skip->object;
ptr = skip->prev_execute_data;
}
}
} 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;
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;
}
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;
/* 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,
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]))) {
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;
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)) {
/*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;
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
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);
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
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)--;
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);
}
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 */
}
}
- 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);
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;
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)) {
}
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");
}
}
}
- 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);
}
EX(function_state).function = (zend_function *) new_op_array;
- EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
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)--;
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);
}
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 */
}
}
- 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);
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;
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)) {
}
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");
}
}
}
- 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);
}
EX(function_state).function = (zend_function *) new_op_array;
- EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
EX(function_state).function = (zend_function *) new_op_array;
- EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
EX(function_state).function = (zend_function *) new_op_array;
- EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
EX(function_state).function = (zend_function *) new_op_array;
- EX(object) = NULL;
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
/* 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);
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) /* {{{ */
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);