summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-04-18 13:46:36 +0400
committerDmitry Stogov <dmitry@zend.com>2014-04-18 13:46:36 +0400
commitea2e1bb1eb7dd0ca1ce6d731190b2a6b2046a645 (patch)
tree55bd78ce8067146ef4a89f03d631de7b0dc611b8
parent8a14276701d946f0ade280e67f748cf028273b90 (diff)
downloadphp-git-ea2e1bb1eb7dd0ca1ce6d731190b2a6b2046a645.tar.gz
Optimized zend_leave_helper()
-rw-r--r--Zend/zend_API.h4
-rw-r--r--Zend/zend_compile.h9
-rw-r--r--Zend/zend_execute.c12
-rw-r--r--Zend/zend_execute.h2
-rw-r--r--Zend/zend_execute_API.c14
-rw-r--r--Zend/zend_generators.c2
-rw-r--r--Zend/zend_vm_def.h157
-rw-r--r--Zend/zend_vm_execute.h161
-rw-r--r--Zend/zend_vm_execute.skl2
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c4
10 files changed, 193 insertions, 174 deletions
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 6295d8a890..43c205c659 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -520,8 +520,8 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_lengt
ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC);
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
-ZEND_API void zend_attach_symbol_table(TSRMLS_D);
-ZEND_API void zend_detach_symbol_table(TSRMLS_D);
+ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data);
+ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data);
ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS_DC);
ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int force TSRMLS_DC);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 0c3f20f354..6681455992 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -366,6 +366,13 @@ typedef struct _call_slot {
zend_bool is_ctor_result_used;
} call_slot;
+typedef enum _vm_frame_kind {
+ VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
+ VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
+ VM_FRAME_TOP_FUNCTION, /* direct VM call to function from external C code */
+ VM_FRAME_TOP_CODE /* direct VM call to "main" code from external C code */
+} vm_frame_kind;
+
struct _zend_execute_data {
struct _zend_op *opline;
void **run_time_cache;
@@ -375,7 +382,7 @@ struct _zend_execute_data {
zend_array *symbol_table;
struct _zend_execute_data *prev_execute_data;
zval old_error_reporting;
- zend_bool nested;
+ vm_frame_kind frame_kind;
zval *return_value;
// TODO: simplify call sequence and remove current_* and call_* ???
zend_class_entry *current_scope;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 7302aeec34..b6a4031221 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1560,7 +1560,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
* +----------------------------------------+
*/
-static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
zend_execute_data *execute_data;
@@ -1650,7 +1650,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
EX(symbol_table) = EG(active_symbol_table);
EX(call) = NULL;
EG(current_execute_data) = execute_data;
- EX(nested) = nested;
+ EX(frame_kind) = frame_kind;
EX(delayed_exception) = NULL;
EX(return_value) = return_value;
@@ -1659,8 +1659,8 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
}
EX(run_time_cache) = op_array->run_time_cache;
- if (EG(active_symbol_table)) {
- zend_attach_symbol_table(TSRMLS_C);
+ if (EX(symbol_table)) {
+ zend_attach_symbol_table(execute_data);
}
if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
@@ -1677,9 +1677,9 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
}
/* }}} */
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
- return i_create_execute_data_from_op_array(op_array, return_value, nested TSRMLS_CC);
+ return i_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
}
/* }}} */
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 417f3acbd9..d632a97840 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -35,7 +35,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
void init_executor(TSRMLS_D);
void shutdown_executor(TSRMLS_D);
void shutdown_destructors(TSRMLS_D);
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 0c6861c14d..8d5b55c84d 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -935,12 +935,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_execute(EG(active_op_array), fci->retval TSRMLS_CC);
}
+ EG(active_op_array) = original_op_array;
+ EG(opline_ptr) = original_opline_ptr;
if (!fci->symbol_table && EG(active_symbol_table)) {
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = calling_symbol_table;
- EG(active_op_array) = original_op_array;
- EG(opline_ptr) = original_opline_ptr;
} 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;
ZVAL_NULL(fci->retval);
@@ -1695,12 +1695,11 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */
+ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
{
int i;
- zend_execute_data *execute_data = EG(current_execute_data);
zend_op_array *op_array = execute_data->op_array;
- HashTable *ht = &EG(active_symbol_table)->ht;
+ HashTable *ht = &execute_data->symbol_table->ht;
/* copy real values from symbol table into CV slots and create
INDIRECT references to CV in symbol table */
@@ -1727,12 +1726,11 @@ ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API void zend_detach_symbol_table(TSRMLS_D) /* {{{ */
+ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
{
int i;
- zend_execute_data *execute_data = EG(current_execute_data);
zend_op_array *op_array = execute_data->op_array;
- HashTable *ht = &EG(active_symbol_table)->ht;
+ HashTable *ht = &execute_data->symbol_table->ht;
/* copy real values from CV slots into symbol table */
for (i = 0; i < op_array->last_var; i++) {
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 29941c12e3..74df4cdb7b 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -287,7 +287,7 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
opline_ptr = EG(opline_ptr);
current_symbol_table = EG(active_symbol_table);
EG(active_symbol_table) = NULL;
- execute_data = zend_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC);
+ execute_data = zend_create_execute_data_from_op_array(op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
EG(active_symbol_table) = current_symbol_table;
EG(current_execute_data) = current_execute_data;
EG(opline_ptr) = opline_ptr;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index aa8b2a5e83..d6723fbd5a 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1748,96 +1748,103 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
{
- zend_bool nested = EX(nested);
- zend_op_array *op_array = EX(op_array);
+ vm_frame_kind frame_kind = EX(frame_kind);
- if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
- EG(active_symbol_table) == &EG(symbol_table)) {
- zend_detach_symbol_table(TSRMLS_C);
- }
-
EG(current_execute_data) = EX(prev_execute_data);
- EG(opline_ptr) = NULL;
-
- if (EG(active_symbol_table) != &EG(symbol_table)) {
- i_free_compiled_variables(execute_data TSRMLS_CC);
- }
-
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
- if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
- zval_ptr_dtor((zval*)op_array->prototype);
- }
+ if (frame_kind == VM_FRAME_NESTED_FUNCTION) {
+ i_free_compiled_variables(execute_data TSRMLS_CC);
+ if (UNEXPECTED(EX(symbol_table) != NULL)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
+ }
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
+ zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ }
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
- if (nested) {
execute_data = EG(current_execute_data);
- }
- if (nested) {
- USE_OPLINE
-
- LOAD_REGS();
- LOAD_OPLINE();
- if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-
- zend_attach_symbol_table(TSRMLS_C);
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ EG(active_symbol_table) = EX(symbol_table);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- HANDLE_EXCEPTION_LEAVE();
+ 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);
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
- } else {
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- if (EG(active_symbol_table)) {
- zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
- }
- EG(active_symbol_table) = EX(symbol_table);
+ EX(call)--;
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
+ zend_vm_stack_clear_multiple(1 TSRMLS_CC);
- 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));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_op *opline = EX(opline);
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
}
- Z_OBJ(EG(This)) = EX(current_this);
- EG(scope) = EX(current_scope);
- EG(called_scope) = EX(current_called_scope);
+ HANDLE_EXCEPTION_LEAVE();
+ }
- EX(call)--;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else if (frame_kind == VM_FRAME_NESTED_CODE) {
+ zend_detach_symbol_table(execute_data);
+ destroy_op_array(EX(op_array) TSRMLS_CC);
+ efree(EX(op_array));
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+ execute_data = EG(current_execute_data);
+ zend_attach_symbol_table(execute_data);
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION_LEAVE();
+ }
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(EX_VAR(opline->result.var));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else {
+ if (frame_kind == VM_FRAME_TOP_FUNCTION) {
+ i_free_compiled_variables(execute_data TSRMLS_CC);
+ } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
+ zend_array *symbol_table = EX(symbol_table);
+ zend_execute_data *old_execute_data;
+
+ zend_detach_symbol_table(execute_data);
+ old_execute_data = EX(prev_execute_data);
+ while (old_execute_data) {
+ if (old_execute_data->op_array) {
+ if (old_execute_data->symbol_table == symbol_table) {
+ zend_attach_symbol_table(old_execute_data);
+ }
+ break;
}
- HANDLE_EXCEPTION_LEAVE();
+ old_execute_data = old_execute_data->prev_execute_data;
}
-
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
}
- }
- ZEND_VM_RETURN();
+ if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
+ zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ }
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ EG(opline_ptr) = NULL;
+ ZEND_VM_RETURN();
+ }
}
ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
@@ -1951,7 +1958,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
} else if (EXPECTED(zend_execute_ex == execute_ex)) {
if (EXPECTED(EG(exception) == NULL)) {
- i_create_execute_data_from_op_array(EG(active_op_array), return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
ZEND_VM_ENTER();
}
} else {
@@ -1960,7 +1967,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
- if (EG(active_symbol_table)) {
+ if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = EX(symbol_table);
@@ -3894,7 +3901,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
}
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array, return_value TSRMLS_CC);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 24e6ef1658..9217e1113b 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -378,101 +378,108 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC
if (EG(exception) != NULL) {
return;
}
- zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC) TSRMLS_CC);
+ zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
}
static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_bool nested = EX(nested);
- zend_op_array *op_array = EX(op_array);
-
- if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
- EG(active_symbol_table) == &EG(symbol_table)) {
- zend_detach_symbol_table(TSRMLS_C);
- }
+ vm_frame_kind frame_kind = EX(frame_kind);
EG(current_execute_data) = EX(prev_execute_data);
- EG(opline_ptr) = NULL;
- if (EG(active_symbol_table) != &EG(symbol_table)) {
+ if (frame_kind == VM_FRAME_NESTED_FUNCTION) {
i_free_compiled_variables(execute_data TSRMLS_CC);
- }
-
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
-
- if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
- zval_ptr_dtor((zval*)op_array->prototype);
- }
+ if (UNEXPECTED(EX(symbol_table) != NULL)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
+ }
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
+ zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ }
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
- if (nested) {
execute_data = EG(current_execute_data);
- }
- if (nested) {
- USE_OPLINE
-
- LOAD_REGS();
- LOAD_OPLINE();
- if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-
- zend_attach_symbol_table(TSRMLS_C);
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ EG(active_symbol_table) = EX(symbol_table);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- HANDLE_EXCEPTION_LEAVE();
+ 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);
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
- } else {
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- if (EG(active_symbol_table)) {
- zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
- }
- EG(active_symbol_table) = EX(symbol_table);
+ EX(call)--;
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
+ zend_vm_stack_clear_multiple(1 TSRMLS_CC);
- 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));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_op *opline = EX(opline);
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
}
- Z_OBJ(EG(This)) = EX(current_this);
- EG(scope) = EX(current_scope);
- EG(called_scope) = EX(current_called_scope);
+ HANDLE_EXCEPTION_LEAVE();
+ }
- EX(call)--;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else if (frame_kind == VM_FRAME_NESTED_CODE) {
+ zend_detach_symbol_table(execute_data);
+ destroy_op_array(EX(op_array) TSRMLS_CC);
+ efree(EX(op_array));
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+ execute_data = EG(current_execute_data);
+ zend_attach_symbol_table(execute_data);
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION_LEAVE();
+ }
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(EX_VAR(opline->result.var));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else {
+ if (frame_kind == VM_FRAME_TOP_FUNCTION) {
+ i_free_compiled_variables(execute_data TSRMLS_CC);
+ } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
+ zend_array *symbol_table = EX(symbol_table);
+ zend_execute_data *old_execute_data;
+
+ zend_detach_symbol_table(execute_data);
+ old_execute_data = EX(prev_execute_data);
+ while (old_execute_data) {
+ if (old_execute_data->op_array) {
+ if (old_execute_data->symbol_table == symbol_table) {
+ zend_attach_symbol_table(old_execute_data);
+ }
+ break;
}
- HANDLE_EXCEPTION_LEAVE();
+ old_execute_data = old_execute_data->prev_execute_data;
}
-
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
}
+ if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
+ zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ }
+ zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ EG(opline_ptr) = NULL;
+ ZEND_VM_RETURN();
}
- ZEND_VM_RETURN();
}
static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
@@ -586,7 +593,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
} else if (EXPECTED(zend_execute_ex == execute_ex)) {
if (EXPECTED(EG(exception) == NULL)) {
- i_create_execute_data_from_op_array(EG(active_op_array), return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
ZEND_VM_ENTER();
}
} else {
@@ -595,7 +602,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
- if (EG(active_symbol_table)) {
+ if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = EX(symbol_table);
@@ -2924,7 +2931,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
}
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -7872,7 +7879,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
}
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -12862,7 +12869,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
}
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -29382,7 +29389,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
}
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+ i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array, return_value TSRMLS_CC);
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index e017abbce6..fa976cb678 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -36,7 +36,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value
if (EG(exception) != NULL) {
return;
}
- zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC) TSRMLS_CC);
+ zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
}
{%EXTERNAL_EXECUTOR%}
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index f4abb97a90..7aea80afdd 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -1079,10 +1079,10 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */
}
} /* }}} */
-static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
#if PHP_VERSION_ID >= 50500
- return zend_create_execute_data_from_op_array(op_array, return_value, nested TSRMLS_CC);
+ return zend_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
#else
#undef EX