summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_builtin_functions.c45
-rw-r--r--Zend/zend_compile.h25
-rw-r--r--Zend/zend_execute.c68
-rw-r--r--Zend/zend_execute_API.c34
-rw-r--r--Zend/zend_generators.c17
-rw-r--r--Zend/zend_vm_def.h131
-rw-r--r--Zend/zend_vm_execute.h134
-rw-r--r--sapi/phpdbg/phpdbg.c1
-rw-r--r--sapi/phpdbg/phpdbg_frame.c12
9 files changed, 257 insertions, 210 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 22076104f0..1d066deb41 100644
--- a/Zend/zend_builtin_functions.c
+++ b/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;
}
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 35559a21d4..24f06c426f 100644
--- a/Zend/zend_compile.h
+++ b/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;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 2866f841d6..2dc3c22414 100644
--- a/Zend/zend_execute.c
+++ b/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;
}
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 0091fea00d..d2fefa7f71 100644
--- a/Zend/zend_execute_API.c
+++ b/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;
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 74df4cdb7b..0f19e84041 100644
--- a/Zend/zend_generators.c
+++ b/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
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 7808b441fd..2d4771c004 100644
--- a/Zend/zend_vm_def.h
+++ b/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);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index c0ff942e20..1ec6d97343 100644
--- a/Zend/zend_vm_execute.h
+++ b/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);
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c
index 64babced64..f20ad3f222 100644
--- a/sapi/phpdbg/phpdbg.c
+++ b/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);
diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c
index 965e9bc2e2..2c2d9e6177 100644
--- a/sapi/phpdbg/phpdbg_frame.c
+++ b/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);