From: Dmitry Stogov Date: Fri, 18 Apr 2014 09:46:36 +0000 (+0400) Subject: Optimized zend_leave_helper() X-Git-Tag: POST_PHPNG_MERGE~412^2~82^2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea2e1bb1eb7dd0ca1ce6d731190b2a6b2046a645;p=php Optimized zend_leave_helper() --- 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