diff options
44 files changed, 782 insertions, 798 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index a1ffb5f0c9..52d574e047 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -559,7 +559,6 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS EG(lambda_count) = 0; ZVAL_UNDEF(&EG(user_error_handler)); ZVAL_UNDEF(&EG(user_exception_handler)); - EG(in_execution) = 0; EG(in_autoload) = NULL; EG(current_execute_data) = NULL; EG(current_module) = NULL; @@ -880,7 +879,7 @@ ZEND_API void _zend_bailout(char *filename, uint lineno) /* {{{ */ } CG(unclean_shutdown) = 1; CG(active_class_entry) = NULL; - CG(in_compilation) = EG(in_execution) = 0; + CG(in_compilation) = 0; EG(current_execute_data) = NULL; LONGJMP(*EG(bailout), FAILURE); } @@ -938,8 +937,7 @@ void zend_call_destructors(TSRMLS_D) /* {{{ */ ZEND_API void zend_deactivate(TSRMLS_D) /* {{{ */ { /* we're no longer executing anything */ - EG(opline_ptr) = NULL; - EG(active_symbol_table) = NULL; + EG(current_execute_data) = NULL; zend_try { shutdown_scanner(TSRMLS_C); @@ -1038,10 +1036,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ zend_stack declare_stack; zend_stack list_stack; zend_stack context_stack; + zend_array *symbol_table; TSRMLS_FETCH(); /* Report about uncaught exception in case of fatal errors */ if (EG(exception)) { + zend_execute_data *ex; + zend_op *opline; + switch (type) { case E_CORE_ERROR: case E_ERROR: @@ -1049,13 +1051,19 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ case E_PARSE: case E_COMPILE_ERROR: case E_USER_ERROR: - if (zend_is_executing(TSRMLS_C)) { - error_lineno = zend_get_executed_lineno(TSRMLS_C); + ex = EG(current_execute_data); + opline = NULL; + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + if (ex && ex->opline->opcode == ZEND_HANDLE_EXCEPTION && + EG(opline_before_exception)) { + opline = EG(opline_before_exception); } zend_exception_error(EG(exception), E_WARNING TSRMLS_CC); EG(exception) = NULL; - if (zend_is_executing(TSRMLS_C) && EG(opline_ptr)) { - active_opline->lineno = error_lineno; + if (opline) { + ex->opline = opline; } break; default: @@ -1088,7 +1096,12 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ error_lineno = zend_get_compiled_lineno(TSRMLS_C); } else if (zend_is_executing(TSRMLS_C)) { error_filename = zend_get_executed_filename(TSRMLS_C); - error_lineno = zend_get_executed_lineno(TSRMLS_C); + if (error_filename[0] == '[') { /* [no active file] */ + error_filename = NULL; + error_lineno = 0; + } else { + error_lineno = zend_get_executed_lineno(TSRMLS_C); + } } else { error_filename = NULL; error_lineno = 0; @@ -1162,16 +1175,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ ZVAL_LONG(¶ms[3], error_lineno); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + symbol_table = zend_rebuild_symbol_table(TSRMLS_C); /* during shutdown the symbol table table can be still null */ - if (!EG(active_symbol_table)) { + if (!symbol_table) { ZVAL_NULL(¶ms[4]); } else { ZVAL_NEW_ARR(¶ms[4]); - zend_array_dup(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht); + zend_array_dup(Z_ARRVAL(params[4]), &symbol_table->ht); } ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); @@ -1242,7 +1253,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ if (type == E_PARSE) { /* eval() errors do not affect exit_status */ if (!(EG(current_execute_data) && - EG(current_execute_data)->opline && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->type) && EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL && EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) { EG(exit_status) = 255; @@ -1287,7 +1299,7 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou va_list files; int i; zend_file_handle *file_handle; - zend_op_array *orig_op_array = EG(active_op_array); + zend_op_array *op_array; long orig_interactive = CG(interactive); va_start(files, file_count); @@ -1305,13 +1317,13 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou } } - EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC); + op_array = zend_compile_file(file_handle, type TSRMLS_CC); if (file_handle->opened_path) { zend_hash_str_add_empty_element(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path)); } zend_destroy_file_handle(file_handle TSRMLS_CC); - if (EG(active_op_array)) { - zend_execute(EG(active_op_array), retval TSRMLS_CC); + if (op_array) { + zend_execute(op_array, retval TSRMLS_CC); zend_exception_restore(TSRMLS_C); if (EG(exception)) { if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { @@ -1338,17 +1350,15 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } } - destroy_op_array(EG(active_op_array) TSRMLS_CC); - efree(EG(active_op_array)); + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); } else if (type==ZEND_REQUIRE) { va_end(files); - EG(active_op_array) = orig_op_array; CG(interactive) = orig_interactive; return FAILURE; } } va_end(files); - EG(active_op_array) = orig_op_array; CG(interactive) = orig_interactive; return SUCCESS; diff --git a/Zend/zend.h b/Zend/zend.h index f21ba92d61..3827f15b54 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -290,8 +290,9 @@ typedef enum { #define USED_RET() \ (!EG(current_execute_data) || \ - !EG(current_execute_data)->opline || \ - !(EG(current_execute_data)->opline->result_type & EXT_TYPE_UNUSED)) + !EG(current_execute_data)->prev_execute_data || \ + !ZEND_USER_CODE(EG(current_execute_data)->prev_execute_data->func->common.type) || \ + !(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED)) #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__) void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn)); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 6b469c2b0a..faf18252e4 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -49,8 +49,8 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */ zval **param, *param_ptr; TSRMLS_FETCH(); - param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1); - arg_count = EG(current_execute_data)->call->num_args; + param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); + arg_count = EG(current_execute_data)->num_args; if (param_count>arg_count) { return FAILURE; @@ -85,8 +85,8 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */ zval **param, *param_ptr; TSRMLS_FETCH(); - param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1); - arg_count = EG(current_execute_data)->call->num_args; + param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); + arg_count = EG(current_execute_data)->num_args; if (param_count>arg_count) { return FAILURE; @@ -109,8 +109,8 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array zval *param_ptr; int arg_count; - param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1); - arg_count = EG(current_execute_data)->call->num_args; + param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); + arg_count = EG(current_execute_data)->num_args; if (param_count>arg_count) { return FAILURE; @@ -131,8 +131,8 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS zval *param_ptr; int arg_count; - param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1); - arg_count = EG(current_execute_data)->call->num_args; + param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); + arg_count = EG(current_execute_data)->num_args; if (param_count>arg_count) { return FAILURE; @@ -803,7 +803,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, case '+': if (have_varargs) { if (!quiet) { - zend_function *active_function = EG(current_execute_data)->call->func; + zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted", class_name, @@ -823,7 +823,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, default: if (!quiet) { - zend_function *active_function = EG(current_execute_data)->call->func; + zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", class_name, @@ -846,7 +846,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) { if (!quiet) { - zend_function *active_function = EG(current_execute_data)->call->func; + zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given", class_name, @@ -860,7 +860,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, return FAILURE; } - arg_count = EG(current_execute_data)->call->num_args; + arg_count = EG(current_execute_data)->num_args; if (num_args > arg_count) { zend_error(E_WARNING, "%s(): could not obtain parameters for parsing", @@ -884,7 +884,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (num_varargs > 0) { *n_varargs = num_varargs; - *varargs = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1); + *varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1); /* adjust how many args we have left and restart loop */ num_args += 1 - num_varargs; i += num_varargs; @@ -895,7 +895,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, } } - arg = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1); + arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1); if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) { /* clean up varargs array if it was used */ @@ -966,7 +966,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL. * In that case EG(This) would still be the $this from the calling code and we'd take the * wrong branch here. */ - zend_bool is_method = EG(current_execute_data)->call->func->common.scope != NULL; + zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL; if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) { RETURN_IF_ZERO_ARGS(num_args, p, 0); @@ -1072,7 +1072,7 @@ static int zval_update_class_constant(zval *pp, int is_static, int offset TSRMLS { ZVAL_DEREF(pp); if (Z_CONSTANT_P(pp)) { - zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry); if ((*scope)->parent) { zend_class_entry *ce = *scope; @@ -1136,7 +1136,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC } if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0) { - zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry); zend_class_entry *old_scope = *scope; zval *val; @@ -2494,7 +2494,7 @@ static int module_registry_cleanup(zval *zv TSRMLS_DC) /* {{{ */ ZEND_API void zend_deactivate_modules(TSRMLS_D) /* {{{ */ { - EG(opline_ptr) = NULL; /* we're no longer executing anything */ + EG(current_execute_data) = NULL; /* we're no longer executing anything */ zend_try { if (EG(full_tables_cleanup)) { @@ -2770,7 +2770,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache if (!EG(scope)) { if (error) *error = estrdup("cannot access self:: when no class scope is active"); } else { - fcc->called_scope = EG(called_scope); + fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL; fcc->calling_scope = EG(scope); if (!fcc->object && Z_OBJ(EG(This))) { fcc->object = Z_OBJ(EG(This)); @@ -2784,7 +2784,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } else if (!EG(scope)->parent) { if (error) *error = estrdup("cannot access parent:: when current class scope has no parent"); } else { - fcc->called_scope = EG(called_scope); + fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL; fcc->calling_scope = EG(scope)->parent; if (!fcc->object && Z_OBJ(EG(This))) { fcc->object = Z_OBJ(EG(This)); @@ -2794,11 +2794,11 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } } else if (name_len == sizeof("static") - 1 && !memcmp(lcname->val, "static", sizeof("static") - 1)) { - if (!EG(called_scope)) { + if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) { if (error) *error = estrdup("cannot access static:: when no class scope is active"); } else { - fcc->called_scope = EG(called_scope); - fcc->calling_scope = EG(called_scope); + fcc->called_scope = EG(current_execute_data)->called_scope; + fcc->calling_scope = EG(current_execute_data)->called_scope; if (!fcc->object && Z_OBJ(EG(This))) { fcc->object = Z_OBJ(EG(This)); } @@ -2806,8 +2806,13 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache ret = 1; } } else if ((ce = zend_lookup_class_ex(name, NULL, 1 TSRMLS_CC)) != NULL) { - zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; + zend_class_entry *scope; + zend_execute_data *ex = EG(current_execute_data); + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + scope = ex ? ex->func->common.scope : NULL; fcc->calling_scope = ce; if (scope && !fcc->object && Z_OBJ(EG(This)) && instanceof_function(Z_OBJCE(EG(This)), scope TSRMLS_CC) && diff --git a/Zend/zend_API.h b/Zend/zend_API.h index eafdf64b4b..b702bd4138 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -521,7 +521,7 @@ 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 zend_array *zend_rebuild_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); diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 3e94ae0bd6..bb3e66c989 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -1761,9 +1761,19 @@ static void zend_mm_safe_error(zend_mm_heap *heap, zend_string *str = zend_get_compiled_filename(TSRMLS_C); error_filename = str ? str->val : NULL; error_lineno = zend_get_compiled_lineno(TSRMLS_C); - } else if (EG(in_execution)) { - error_filename = EG(active_op_array)?EG(active_op_array)->filename->val:NULL; - error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0; + } else if (EG(current_execute_data)) { + zend_execute_data *ex = EG(current_execute_data); + + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + if (ex) { + error_filename = ex->func->op_array.filename->val; + error_lineno = ex->opline->lineno; + } else { + error_filename = NULL; + error_lineno = 0; + } } else { error_filename = NULL; error_lineno = 0; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index df81c5d666..96b339cd67 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -394,7 +394,7 @@ ZEND_FUNCTION(gc_disable) Get the number of arguments that were passed to the function */ ZEND_FUNCTION(func_num_args) { - zend_execute_data *ex = EG(current_execute_data); + zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) { RETURN_LONG(ex->num_args); @@ -423,7 +423,7 @@ ZEND_FUNCTION(func_get_arg) RETURN_FALSE; } - ex = EG(current_execute_data); + ex = EG(current_execute_data)->prev_execute_data; if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) { zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context"); RETURN_FALSE; @@ -456,7 +456,7 @@ ZEND_FUNCTION(func_get_args) zval *p; int arg_count, first_extra_arg; int i; - zend_execute_data *ex = EG(current_execute_data); + zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) { zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context"); @@ -809,8 +809,8 @@ ZEND_FUNCTION(get_called_class) return; } - if (EG(called_scope)) { - RETURN_STR(STR_COPY(EG(called_scope)->name)); + if (EG(current_execute_data)->called_scope) { + RETURN_STR(STR_COPY(EG(current_execute_data)->called_scope->name)); } else if (!EG(scope)) { zend_error(E_WARNING, "get_called_class() called from outside a class"); } @@ -1749,12 +1749,10 @@ ZEND_FUNCTION(get_defined_functions) Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */ ZEND_FUNCTION(get_defined_vars) { - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); ZVAL_NEW_ARR(return_value); - zend_array_dup(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht); + zend_array_dup(Z_ARRVAL_P(return_value), &symbol_table->ht); } /* }}} */ @@ -2035,7 +2033,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) /* {{{ proto void debug_print_backtrace([int options[, int limit]]) */ ZEND_FUNCTION(debug_print_backtrace) { - zend_execute_data *ptr, *skip; + zend_execute_data *call, *ptr, *skip; zend_object *object; int lineno, frameno = 0; zend_function *func; @@ -2054,10 +2052,10 @@ ZEND_FUNCTION(debug_print_backtrace) } ZVAL_UNDEF(&arg_array); - ptr = EG(current_execute_data); + ptr = EG(current_execute_data)->prev_execute_data; /* skip debug_backtrace() */ - object = ptr->object; + call = ptr; ptr = ptr->prev_execute_data; while (ptr && (limit == 0 || frameno < limit)) { @@ -2070,7 +2068,8 @@ ZEND_FUNCTION(debug_print_backtrace) /* skip internal handler */ if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) && skip->prev_execute_data && - skip->prev_execute_data->opline && + skip->prev_execute_data->func && + ZEND_USER_CODE(skip->prev_execute_data->func->common.type) && skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { skip = skip->prev_execute_data; @@ -2078,22 +2077,31 @@ ZEND_FUNCTION(debug_print_backtrace) if (skip->func && ZEND_USER_CODE(skip->func->common.type)) { filename = skip->func->op_array.filename->val; - lineno = skip->opline->lineno; + if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) { + if (EG(opline_before_exception)) { + lineno = EG(opline_before_exception)->lineno; + } else { + lineno = skip->func->op_array.line_end; + } + } else { + lineno = skip->opline->lineno; + } } else { filename = NULL; lineno = 0; } /* $this may be passed into regular internal functions */ + object = call->object; if (object && - ptr->call && - ptr->call->func->type == ZEND_INTERNAL_FUNCTION && - !ptr->call->func->common.scope) { + call && + call->func->type == ZEND_INTERNAL_FUNCTION && + !call->func->common.scope) { object = NULL; } - if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) { - func = ptr->call->func; + if (call->func) { + func = call->func; function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( @@ -2103,9 +2111,8 @@ ZEND_FUNCTION(debug_print_backtrace) (func->common.function_name ? func->common.function_name->val : NULL); } else { - func = ptr->func; - function_name = func && func->common.function_name ? - func->common.function_name->val : NULL; + func = NULL; + function_name = NULL; } if (function_name) { @@ -2126,14 +2133,14 @@ ZEND_FUNCTION(debug_print_backtrace) } if (func->type != ZEND_EVAL_CODE) { if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) { - debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC); + debug_backtrace_get_args(call, &arg_array TSRMLS_CC); } } } else { /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; - if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { /* can happen when calling eval from a custom sapi */ function_name = "unknown"; build_filename_arg = 0; @@ -2182,12 +2189,13 @@ ZEND_FUNCTION(debug_print_backtrace) if (filename) { zend_printf(") called at [%s:%d]\n", filename, lineno); } else { + zend_execute_data *prev_call = skip; zend_execute_data *prev = skip->prev_execute_data; while (prev) { - if (prev->call && - prev->call->func && - !ZEND_USER_CODE(prev->call->func->common.type)) { + if (prev_call && + prev_call->func && + !ZEND_USER_CODE(prev_call->func->common.type)) { prev = NULL; break; } @@ -2195,6 +2203,7 @@ ZEND_FUNCTION(debug_print_backtrace) zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno); break; } + prev_call = prev; prev = prev->prev_execute_data; } if (!prev) { @@ -2202,7 +2211,7 @@ ZEND_FUNCTION(debug_print_backtrace) } } include_filename = filename; - object = skip->object; + call = skip; ptr = skip->prev_execute_data; ++indent; } @@ -2212,8 +2221,8 @@ 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)); + zend_execute_data *call, *ptr, *skip; + zend_object *object; int lineno, frameno = 0; zend_function *func; const char *function_name; @@ -2222,18 +2231,28 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int const char *include_filename = NULL; zval stack_frame; + call = NULL; ptr = EG(current_execute_data); - - /* skip "new Exception()" */ - if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) { - object = ptr->object; + if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) { + call = ptr; ptr = ptr->prev_execute_data; } - /* skip debug_backtrace() */ - if (skip_last-- && ptr) { - object = ptr->object; - ptr = ptr->prev_execute_data; + if (ptr) { + if (skip_last) { + /* skip debug_backtrace() */ + call = ptr; + ptr = ptr->prev_execute_data; + } else { + /* skip "new Exception()" */ + if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) { + call = ptr; + ptr = ptr->prev_execute_data; + } + } + } + if (!call) { + call = ptr; } array_init(return_value); @@ -2246,7 +2265,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int /* skip internal handler */ if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) && skip->prev_execute_data && - skip->prev_execute_data->opline && + skip->prev_execute_data->func && + ZEND_USER_CODE(skip->prev_execute_data->func->common.type) && skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { skip = skip->prev_execute_data; @@ -2254,7 +2274,15 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int if (skip->func && ZEND_USER_CODE(skip->func->common.type)) { filename = skip->func->op_array.filename->val; - lineno = skip->opline->lineno; + if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) { + if (EG(opline_before_exception)) { + lineno = EG(opline_before_exception)->lineno; + } else { + lineno = skip->func->op_array.line_end; + } + } else { + lineno = skip->opline->lineno; + } add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename); add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno); @@ -2262,14 +2290,15 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int * and debug_baktrace() might have been called by the error_handler. in this case we don't * want to pop anything of the argument-stack */ } else { + zend_execute_data *prev_call = skip; zend_execute_data *prev = skip->prev_execute_data; while (prev) { - if (prev->call && - prev->call->func && - !ZEND_USER_CODE(prev->call->func->common.type) && - !(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION && - (prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) { + if (prev_call && + prev_call->func && + !ZEND_USER_CODE(prev_call->func->common.type) && + !(prev_call->func->common.type == ZEND_INTERNAL_FUNCTION && + (prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) { break; } if (prev->func && ZEND_USER_CODE(prev->func->common.type)) { @@ -2278,21 +2307,22 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno); break; } + prev_call = prev; prev = prev->prev_execute_data; } filename = NULL; } /* $this may be passed into regular internal functions */ + object = call ? call->object : NULL; if (object && - ptr->call && - ptr->call->func->type == ZEND_INTERNAL_FUNCTION && - !ptr->call->func->common.scope) { + call->func->type == ZEND_INTERNAL_FUNCTION && + !call->func->common.scope) { object = NULL; } - if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) { - func = ptr->call->func; + if (call && call->func) { + func = call->func; function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( @@ -2302,9 +2332,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int (func->common.function_name ? func->common.function_name->val : NULL); } else { - func = ptr->func; - function_name = func && func->common.function_name ? - func->common.function_name->val : NULL; + func = NULL; + function_name = NULL; } if (function_name) { @@ -2333,17 +2362,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && func->type != ZEND_EVAL_CODE) { - if (ptr->call) { - zval args; - debug_backtrace_get_args(ptr->call, &args TSRMLS_CC); - add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args); - } + zval args; + + debug_backtrace_get_args(call, &args TSRMLS_CC); + add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args); } } else { /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; - if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { /* can happen when calling eval from a custom sapi */ function_name = "unknown"; build_filename_arg = 0; @@ -2393,7 +2421,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int include_filename = filename; - object = skip->object; + call = skip; ptr = skip->prev_execute_data; } } diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 053a5eb199..29c1328f2c 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers; ZEND_METHOD(Closure, __invoke) /* {{{ */ { - zend_function *func = EG(current_execute_data)->call->func; + zend_function *func = EG(current_execute_data)->func; zval *arguments; arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS()); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1c5d5dd4f6..0f077517f5 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -380,7 +380,6 @@ struct _zend_execute_data { #define ZEND_CALL_CTOR (1 << 0) #define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1) -#define ZEND_CALL_DONE (1 << 2) #define ZEND_CALL_FRAME_SLOT \ ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))) diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 4930d1fdd4..650a566159 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -231,7 +231,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len zend_constant *c; static char haltoff[] = "__COMPILER_HALT_OFFSET__"; - if (!EG(in_execution)) { + if (!EG(current_execute_data)) { return NULL; } else if (name_len == sizeof("__CLASS__")-1 && !memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) { @@ -354,7 +354,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, lcname = do_alloca(class_name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, class_name_len); if (!scope) { - if (EG(in_execution)) { + if (EG(current_execute_data)) { scope = EG(scope); } else { scope = CG(active_class_entry); @@ -379,8 +379,8 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, } } else if (class_name_len == sizeof("static")-1 && !memcmp(lcname, "static", sizeof("static")-1)) { - if (EG(called_scope)) { - ce = EG(called_scope); + if (EG(current_execute_data) && EG(current_execute_data)->called_scope) { + ce = EG(current_execute_data)->called_scope; } else { zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } diff --git a/Zend/zend_dtrace.c b/Zend/zend_dtrace.c index 8d854f1ef8..2c1deadec0 100644 --- a/Zend/zend_dtrace.c +++ b/Zend/zend_dtrace.c @@ -81,7 +81,7 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC) } } -ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC) +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC) { int lineno; const char *filename; @@ -94,7 +94,7 @@ ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_ DTRACE_EXECUTE_ENTRY((char *)filename, lineno); } - execute_internal(execute_data_ptr, fci TSRMLS_CC); + execute_internal(execute_data, return_value TSRMLS_CC); if (DTRACE_EXECUTE_RETURN_ENABLED()) { DTRACE_EXECUTE_RETURN((char *)filename, lineno); diff --git a/Zend/zend_dtrace.h b/Zend/zend_dtrace.h index 26008afb6b..6b1c8413e0 100644 --- a/Zend/zend_dtrace.h +++ b/Zend/zend_dtrace.h @@ -32,11 +32,11 @@ extern "C" { #ifdef HAVE_DTRACE ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC); -ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); +ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC); -ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); #include <zend_dtrace_gen.h> #endif /* HAVE_DTRACE */ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 0f59e254d7..90487bf762 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -119,7 +119,8 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ zend_throw_exception_hook(exception TSRMLS_CC); } - if (EG(current_execute_data)->opline == NULL || + if (!EG(current_execute_data)->func || + !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) || (EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) { /* no need to rethrow the exception */ return; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5318bbe2d3..fcc932095d 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -116,7 +116,8 @@ static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *sho /* End of zend_execute_locks.h */ -#define CV_DEF_OF(i) (EG(active_op_array)->vars[i]) +// TODO: avoid global variable usage ??? +#define CV_DEF_OF(i) (EG(current_execute_data)->func->op_array.vars[i]) #define CTOR_CALL_BIT 0x1 #define CTOR_USED_BIT 0x2 @@ -546,7 +547,7 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen ZVAL_UNDEF(arg); } - if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { + if (zf->common.type == ZEND_USER_FUNCTION && ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno); } else { zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind); @@ -982,7 +983,7 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze } -static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type TSRMLS_DC) +static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type TSRMLS_DC) { HashTable *ht; @@ -990,14 +991,14 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) { ht = &EG(symbol_table).ht; } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) { - ZEND_ASSERT(EG(active_op_array)->static_variables != NULL); - ht = EG(active_op_array)->static_variables; + ZEND_ASSERT(EX(func)->op_array.static_variables != NULL); + ht = EX(func)->op_array.static_variables; } else { ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL); - if (!EG(active_symbol_table)) { + if (!EX(symbol_table)) { zend_rebuild_symbol_table(TSRMLS_C); } - ht = &EG(active_symbol_table)->ht; + ht = &EX(symbol_table)->ht; } return ht; } @@ -1443,8 +1444,8 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of #define CHECK_SYMBOL_TABLES() \ zend_hash_apply(&EG(symbol_table), zend_check_symbol TSRMLS_CC); \ - if (&EG(symbol_table)!=EG(active_symbol_table)) { \ - zend_hash_apply(EG(active_symbol_table), zend_check_symbol TSRMLS_CC); \ + if (&EG(symbol_table)!=EX(symbol_table)) { \ + zend_hash_apply(EX(symbol_table), zend_check_symbol TSRMLS_CC); \ } static int zend_check_symbol(zval *pz TSRMLS_DC) @@ -1475,18 +1476,9 @@ static int zend_check_symbol(zval *pz TSRMLS_DC) ZEND_API opcode_handler_t *zend_opcode_handlers; -ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC) +ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC) { - if (fci != NULL) { - execute_data_ptr->call->func->internal_function.handler( - fci->param_count, fci->retval TSRMLS_CC - ); - } else { - zval *return_value = EX_VAR_2(execute_data_ptr, execute_data_ptr->opline->result.var); - execute_data_ptr->call->func->internal_function.handler( - execute_data_ptr->call->num_args, return_value TSRMLS_CC - ); - } + execute_data->func->internal_function.handler(execute_data->num_args, return_value TSRMLS_CC); } void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */ @@ -1542,11 +1534,97 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* * +----------------------------------------+ */ +static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +{ + zend_uint first_extra_arg; + ZEND_ASSERT(EX(func) == (zend_function*)op_array); + ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); + + EX(return_value) = return_value; + EX(frame_kind) = frame_kind; + ZVAL_UNDEF(&EX(old_error_reporting)); + EX(delayed_exception) = NULL; + EX(call) = NULL; + + EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; + EX(scope) = EG(scope); + + first_extra_arg = op_array->num_args; + + if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) { + first_extra_arg--; + } + if (UNEXPECTED(EX(num_args) > first_extra_arg)) { + /* move extra args into separate array after all CV and TMP vars */ + zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T); + + memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg)); + } + + do { + /* Initialize CV variables (skip arguments) */ + int num_args = MIN(op_array->num_args, EX(num_args)); + + if (EXPECTED(num_args < op_array->last_var)) { + zval *var = EX_VAR_NUM(num_args); + zval *end = EX_VAR_NUM(op_array->last_var); + + do { + ZVAL_UNDEF(var); + var++; + } while (var != end); + } + } while (0); + + 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)); + } + + if (!op_array->run_time_cache && op_array->last_cache_slot) { + if (op_array->function_name) { + op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*)); + } else { + op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + } + } + EX(run_time_cache) = op_array->run_time_cache; + + EG(current_execute_data) = execute_data; +} + +static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +{ + ZEND_ASSERT(EX(func) == (zend_function*)op_array); + ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); + + EX(return_value) = return_value; + EX(frame_kind) = frame_kind; + ZVAL_UNDEF(&EX(old_error_reporting)); + EX(delayed_exception) = NULL; + EX(call) = NULL; + + EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; + EX(scope) = EG(scope); + + zend_attach_symbol_table(execute_data); + + if (!op_array->run_time_cache && op_array->last_cache_slot) { + if (op_array->function_name) { + op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*)); + } else { + op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + } + } + EX(run_time_cache) = op_array->run_time_cache; + + EG(current_execute_data) = execute_data; +} + static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ { ZEND_ASSERT(EX(func) == (zend_function*)op_array); ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); - ZEND_ASSERT(EX(called_scope) == EG(called_scope)); EX(return_value) = return_value; EX(frame_kind) = frame_kind; @@ -1554,10 +1632,8 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da EX(delayed_exception) = NULL; 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(scope) = EG(scope); - EX(symbol_table) = EG(active_symbol_table); if (UNEXPECTED(EX(symbol_table) != NULL)) { zend_attach_symbol_table(execute_data); @@ -1608,7 +1684,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da } /* }}} */ -ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ +ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { /* * Normally the execute_data is allocated on the VM stack (because it does @@ -1620,7 +1696,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op * restore it simply by replacing a pointer. */ zend_execute_data *execute_data; - zend_uint num_args = EG(current_execute_data)->call->num_args; + zend_uint num_args = call->num_args; EG(argument_stack) = zend_vm_stack_new_page( MAX(ZEND_VM_STACK_PAGE_SIZE, @@ -1630,15 +1706,15 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op execute_data = zend_vm_stack_push_call_frame( (zend_function*)op_array, num_args, - EG(current_execute_data)->call->flags, - EG(current_execute_data)->call->called_scope, - EG(current_execute_data)->call->object, + call->flags, + call->called_scope, + call->object, NULL TSRMLS_CC); - execute_data->num_args = num_args; + EX(num_args) = num_args; /* copy arguments */ if (num_args > 0) { - zval *arg_src = ZEND_CALL_ARG(EG(current_execute_data)->call, 1); + zval *arg_src = ZEND_CALL_ARG(call, 1); zval *arg_dst = ZEND_CALL_ARG(execute_data, 1); int i; @@ -1653,15 +1729,10 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op } /* }}} */ -ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ { - zend_execute_data *execute_data; - - execute_data = EG(current_execute_data)->call; EX(prev_execute_data) = EG(current_execute_data); i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC); - - return execute_data; } /* }}} */ diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 40f42ae2dd..4fc56d9864 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -30,16 +30,16 @@ BEGIN_EXTERN_C() struct _zend_fcall_info; ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC); -ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC); +ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); void shutdown_destructors(TSRMLS_D); -ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC); -ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC); +ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC); +ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value 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); +ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); ZEND_API int zend_is_true(zval *op TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC); @@ -250,8 +250,8 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call T zend_uint num_args = call->num_args; if (num_args > 0) { - zval *p = ZEND_CALL_ARG(call, num_args + 1); - zval *end = p - num_args;; + zval *end = ZEND_CALL_ARG(call, 1); + zval *p = end + num_args; do { p--; @@ -272,35 +272,6 @@ static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data * } } -static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex) -{ - return ex->call->num_args; -} - -static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg) -{ - int arg_count = ex->call->num_args; - - if (UNEXPECTED(requested_arg > arg_count)) { - return NULL; - } - return ZEND_CALL_ARG(ex->call, requested_arg); -} - -static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D) -{ - if (EG(current_execute_data)->prev_execute_data) { - return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data); - } else { - return 0; - } -} - -static zend_always_inline zval* zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) -{ - return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg); -} - void execute_new_code(TSRMLS_D); @@ -325,8 +296,6 @@ void zend_shutdown_timeout_thread(void); #define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2) #endif -#define active_opline (*EG(opline_ptr)) - /* The following tries to resolve the classname of a zval of type object. * Since it is slow it should be only used in error messages. */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 2ba582942a..69f7cfad5b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -39,7 +39,7 @@ #endif ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC); -ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC); +ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); /* true globals */ ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0},0}, NULL, NULL, 0, NULL, NULL, 0 }; @@ -150,7 +150,6 @@ void init_executor(TSRMLS_D) /* {{{ */ EG(function_table) = CG(function_table); EG(class_table) = CG(class_table); - EG(in_execution) = 0; EG(in_autoload) = NULL; EG(autoload_func) = NULL; EG(error_handling) = EH_NORMAL; @@ -160,10 +159,9 @@ void init_executor(TSRMLS_D) /* {{{ */ zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0); GC_REFCOUNT(&EG(symbol_table)) = 1; GC_TYPE_INFO(&EG(symbol_table)) = IS_ARRAY; - EG(active_symbol_table) = &EG(symbol_table); + EG(valid_symbol_table) = 1; zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC); - EG(opline_ptr) = NULL; zend_hash_init(&EG(included_files), 8, NULL, NULL, 0); @@ -188,12 +186,9 @@ void init_executor(TSRMLS_D) /* {{{ */ EG(prev_exception) = NULL; EG(scope) = NULL; - EG(called_scope) = NULL; ZVAL_OBJ(&EG(This), NULL); - EG(active_op_array) = NULL; - EG(active) = 1; EG(start_op) = NULL; } @@ -271,6 +266,7 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ } zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht); } zend_end_try(); + EG(valid_symbol_table) = 0; zend_try { zval *zeh; @@ -401,11 +397,7 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ return ""; } - if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) { - func = EG(current_execute_data)->call->func; - } else { - func = EG(current_execute_data)->func; - } + func = EG(current_execute_data)->func; switch (func->type) { case ZEND_USER_FUNCTION: case ZEND_INTERNAL_FUNCTION: @@ -433,11 +425,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */ if (!zend_is_executing(TSRMLS_C)) { return NULL; } - if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) { - func = EG(current_execute_data)->call->func; - } else { - func = EG(current_execute_data)->func; - } + func = EG(current_execute_data)->func; switch (func->type) { case ZEND_USER_FUNCTION: { zend_string *function_name = func->common.function_name; @@ -460,8 +448,13 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */ ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */ { - if (EG(active_op_array)) { - return EG(active_op_array)->filename->val; + zend_execute_data *ex = EG(current_execute_data); + + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + if (ex) { + return ex->func->op_array.filename->val; } else { return "[no active file]"; } @@ -470,12 +463,17 @@ ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */ ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */ { - if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION && - active_opline->lineno == 0 && EG(opline_before_exception)) { - return EG(opline_before_exception)->lineno; + zend_execute_data *ex = EG(current_execute_data); + + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; } - if (EG(opline_ptr)) { - return active_opline->lineno; + if (ex) { + if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION && + ex->opline->lineno == 0 && EG(opline_before_exception)) { + return EG(opline_before_exception)->lineno; + } + return ex->opline->lineno; } else { return 0; } @@ -484,7 +482,7 @@ ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */ ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */ { - return EG(in_execution); + return EG(current_execute_data) != 0; } /* }}} */ @@ -662,14 +660,12 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */ { zend_uint i; - zend_array *calling_symbol_table; - zend_op_array *original_op_array; - zend_op **original_opline_ptr; zend_class_entry *calling_scope = NULL; - zend_class_entry *called_scope = NULL; - zend_execute_data execute_data; + zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local; zend_function *func; + zend_object *orig_object; + zend_class_entry *orig_scope; zval tmp; ZVAL_UNDEF(fci->retval); @@ -690,20 +686,28 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS break; } + orig_object = Z_OBJ(EG(This)); + orig_scope = EG(scope); + /* 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(func) = NULL; - EX(opline) = NULL; - } else { + if (!EG(current_execute_data)) { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, * but it may make bugs easier to spot */ - memset(&execute_data, 0, sizeof(zend_execute_data)); + memset(&dummy_execute_data, 0, sizeof(zend_execute_data)); + EG(current_execute_data) = &dummy_execute_data; + } else if (EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type) && + EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL) { + /* Insert fake frame in case of include or magic calls */ + dummy_execute_data = *EG(current_execute_data); + dummy_execute_data.prev_execute_data = EG(current_execute_data); + dummy_execute_data.call = NULL; + dummy_execute_data.prev_nested_call = NULL; + dummy_execute_data.opline = NULL; + dummy_execute_data.func = NULL; + EG(current_execute_data) = &dummy_execute_data; } if (!fci_cache || !fci_cache->initialized) { @@ -722,6 +726,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (callable_name) { STR_RELEASE(callable_name); } + if (EG(current_execute_data) == &dummy_execute_data) { + EG(current_execute_data) = dummy_execute_data.prev_execute_data; + } return FAILURE; } else if (error) { /* Capitalize the first latter of the error message */ @@ -735,13 +742,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } func = fci_cache->function_handler; - EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(func, fci->param_count, 0, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC); calling_scope = fci_cache->calling_scope; - called_scope = fci_cache->called_scope; fci->object = fci_cache->object; if (fci->object && (!EG(objects_store).object_buckets || !IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) { + if (EG(current_execute_data) == &dummy_execute_data) { + EG(current_execute_data) = dummy_execute_data.prev_execute_data; + } return FAILURE; } @@ -783,16 +792,19 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) { if (i) { /* hack to clean up the stack */ - EX(call)->num_args = i; - zend_vm_stack_free_args(EX(call) TSRMLS_CC); + call->num_args = i; + zend_vm_stack_free_args(call TSRMLS_CC); } - zend_vm_stack_free_call_frame(EX(call) TSRMLS_CC); + zend_vm_stack_free_call_frame(call TSRMLS_CC); zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", i+1, func->common.scope ? func->common.scope->name->val : "", func->common.scope ? "::" : "", func->common.function_name->val); + if (EG(current_execute_data) == &dummy_execute_data) { + EG(current_execute_data) = dummy_execute_data.prev_execute_data; + } return FAILURE; } @@ -808,73 +820,56 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else if (Z_REFCOUNTED(fci->params[i])) { Z_ADDREF(fci->params[i]); } - param = ZEND_CALL_ARG(EX(call), i+1); + param = ZEND_CALL_ARG(call, i+1); ZVAL_COPY_VALUE(param, &fci->params[i]); } else if (Z_ISREF(fci->params[i]) && /* don't separate references for __call */ (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) { param = &tmp; - param = ZEND_CALL_ARG(EX(call), i+1); + param = ZEND_CALL_ARG(call, i+1); ZVAL_DUP(param, Z_REFVAL(fci->params[i])); } else { - param = ZEND_CALL_ARG(EX(call), i+1); + param = ZEND_CALL_ARG(call, i+1); ZVAL_COPY(param, &fci->params[i]); } } - EX(call)->num_args = fci->param_count; + call->num_args = fci->param_count; EG(scope) = calling_scope; - EG(called_scope) = called_scope; if (!fci->object || (func->common.fn_flags & ZEND_ACC_STATIC)) { - Z_OBJ(EG(This)) = EX(call)->object = NULL; + Z_OBJ(EG(This)) = call->object = NULL; } else { Z_OBJ(EG(This)) = fci->object; Z_ADDREF(EG(This)); } - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = &execute_data; - if (func->type == ZEND_USER_FUNCTION) { - calling_symbol_table = EG(active_symbol_table); EG(scope) = func->common.scope; - if (fci->symbol_table) { - EG(active_symbol_table) = fci->symbol_table; + call->symbol_table = fci->symbol_table; + if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { + zend_init_execute_data(call, &func->op_array, fci->retval, call->symbol_table ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC); + zend_execute_ex(call TSRMLS_CC); } else { - EG(active_symbol_table) = NULL; - } - - original_op_array = EG(active_op_array); - EG(active_op_array) = (zend_op_array *) func; - original_opline_ptr = EG(opline_ptr); - - if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) { - zend_execute(EG(active_op_array), fci->retval TSRMLS_CC); - } else { - zend_generator_create_zval(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); + zend_generator_create_zval(call, &func->op_array, fci->retval TSRMLS_CC); } - EG(active_symbol_table) = calling_symbol_table; } else if (func->type == ZEND_INTERNAL_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; ZVAL_NULL(fci->retval); if (func->common.scope) { EG(scope) = func->common.scope; } + call->prev_execute_data = EG(current_execute_data); + EG(current_execute_data) = call; if (EXPECTED(zend_execute_internal == NULL)) { /* saves one function call if zend_execute_internal is not used */ func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC); } else { - zend_execute_internal(&execute_data, fci TSRMLS_CC); + zend_execute_internal(call, fci->retval TSRMLS_CC); } - zend_vm_stack_free_args(EX(call) TSRMLS_CC); - zend_vm_stack_free_call_frame(EX(call) TSRMLS_CC); + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call TSRMLS_CC); + zend_vm_stack_free_call_frame(call TSRMLS_CC); /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) @@ -896,11 +891,17 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS /* Not sure what should be done here if it's a static method */ if (fci->object) { + call->prev_execute_data = EG(current_execute_data); + EG(current_execute_data) = call; fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC); + EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } + zend_vm_stack_free_args(call TSRMLS_CC); + zend_vm_stack_free_call_frame(call TSRMLS_CC); + if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { STR_RELEASE(func->common.function_name); } @@ -916,10 +917,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zval_ptr_dtor(&EG(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); + Z_OBJ(EG(This)) = orig_object; + EG(scope) = orig_scope; + if (EG(current_execute_data) == &dummy_execute_data) { + EG(current_execute_data) = dummy_execute_data.prev_execute_data; + } if (EG(exception)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -1060,7 +1062,6 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s { zval pv; zend_op_array *new_op_array; - zend_op_array *original_active_op_array = EG(active_op_array); zend_uint original_compiler_options; int retval; @@ -1083,22 +1084,13 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s if (new_op_array) { zval local_retval; - zend_op **original_opline_ptr = EG(opline_ptr); int orig_interactive = CG(interactive); - EG(active_op_array) = new_op_array; - EG(no_extensions)=1; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + EG(no_extensions)=1; CG(interactive) = 0; zend_try { ZVAL_UNDEF(&local_retval); - if (EG(current_execute_data)) { - EG(current_execute_data)->call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC); - } zend_execute(new_op_array, &local_retval TSRMLS_CC); } zend_catch { destroy_op_array(new_op_array TSRMLS_CC); @@ -1120,8 +1112,6 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s } EG(no_extensions)=0; - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); retval = SUCCESS; @@ -1222,7 +1212,6 @@ void execute_new_code(TSRMLS_D) /* {{{ */ zend_release_labels(1 TSRMLS_CC); - EG(active_op_array) = CG(active_op_array); orig_interactive = CG(interactive); CG(interactive) = 0; zend_execute(CG(active_op_array), NULL TSRMLS_CC); @@ -1474,10 +1463,10 @@ check_fetch_type: } return EG(scope)->parent; case ZEND_FETCH_CLASS_STATIC: - if (!EG(called_scope)) { + if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) { zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } - return EG(called_scope); + return EG(current_execute_data)->called_scope; case ZEND_FETCH_CLASS_AUTO: { fetch_type = zend_get_class_fetch_type(class_name->val, class_name->len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { @@ -1593,45 +1582,42 @@ ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC) /* {{{ */ } /* }}} */ -ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ +ZEND_API zend_array *zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ { zend_uint i; zend_execute_data *ex; + zend_array *symbol_table; - if (!EG(active_symbol_table)) { - - /* Search for last called user function */ - ex = EG(current_execute_data); - while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) { - ex = ex->prev_execute_data; - } - if (!ex) { - return; - } - if (ex->symbol_table) { - EG(active_symbol_table) = ex->symbol_table; - return; - } + /* Search for last called user function */ + ex = EG(current_execute_data); + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) { + ex = ex->prev_execute_data; + } + if (!ex) { + return NULL; + } + if (ex->symbol_table) { + return ex->symbol_table; + } - if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { - /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ - EG(active_symbol_table) = *(EG(symtable_cache_ptr)--); - } else { - EG(active_symbol_table) = emalloc(sizeof(zend_array)); - GC_REFCOUNT(EG(active_symbol_table)) = 0; - GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY; - zend_hash_init(&EG(active_symbol_table)->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0); - /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ - } - ex->symbol_table = EG(active_symbol_table); - for (i = 0; i < ex->func->op_array.last_var; i++) { - zval zv; + if (EG(symtable_cache_ptr) >= EG(symtable_cache)) { + /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ + symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--); + } else { + symbol_table = ex->symbol_table = emalloc(sizeof(zend_array)); + GC_REFCOUNT(symbol_table) = 0; + GC_TYPE_INFO(symbol_table) = IS_ARRAY; + zend_hash_init(&symbol_table->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0); + /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ + } + for (i = 0; i < ex->func->op_array.last_var; i++) { + zval zv; - ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i)); - zend_hash_add_new(&EG(active_symbol_table)->ht, - ex->func->op_array.vars[i], &zv); - } + ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i)); + zend_hash_add_new(&symbol_table->ht, + ex->func->op_array.vars[i], &zv); } + return symbol_table; } /* }}} */ @@ -1686,13 +1672,18 @@ 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) /* {{{ */ { - if (!EG(active_symbol_table)) { - int i; - zend_execute_data *execute_data = EG(current_execute_data); - zend_op_array *op_array = &execute_data->func->op_array; - zend_ulong h = STR_HASH_VAL(name); + zend_execute_data *execute_data = EG(current_execute_data); + + while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) { + execute_data = execute_data->prev_execute_data; + } + + if (execute_data) { + if (!execute_data->symbol_table) { + zend_ulong h = STR_HASH_VAL(name); + zend_op_array *op_array = &execute_data->func->op_array; + int i; - if (op_array) { for (i = 0; i < op_array->last_var; i++) { if (op_array->vars[i]->h == h && op_array->vars[i]->len == name->len && @@ -1701,31 +1692,34 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS return SUCCESS; } } - } - if (force) { - zend_rebuild_symbol_table(TSRMLS_C); - if (EG(active_symbol_table)) { - zend_hash_update(&EG(active_symbol_table)->ht, name, value); + if (force) { + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + if (symbol_table) { + return zend_hash_update(&symbol_table->ht, name, value) ? SUCCESS : FAILURE;; + } } } else { - return FAILURE; + return (zend_hash_update_ind(&execute_data->symbol_table->ht, name, value) != NULL) ? SUCCESS : FAILURE; } - } else { - return (zend_hash_update_ind(&EG(active_symbol_table)->ht, name, value) != NULL) ? SUCCESS : FAILURE; } - return SUCCESS; + return FAILURE; } /* }}} */ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int force TSRMLS_DC) /* {{{ */ { - if (!EG(active_symbol_table)) { - int i; - zend_execute_data *execute_data = EG(current_execute_data); - zend_op_array *op_array = &execute_data->func->op_array; - zend_ulong h = zend_hash_func(name, len); + zend_execute_data *execute_data = EG(current_execute_data); + + while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) { + execute_data = execute_data->prev_execute_data; + } + + if (execute_data) { + if (!execute_data->symbol_table) { + zend_ulong h = zend_hash_func(name, len); + zend_op_array *op_array = &execute_data->func->op_array; + int i; - if (op_array) { for (i = 0; i < op_array->last_var; i++) { if (op_array->vars[i]->h == h && op_array->vars[i]->len == len && @@ -1734,19 +1728,18 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int return SUCCESS; } } - } - if (force) { - zend_rebuild_symbol_table(TSRMLS_C); - if (EG(active_symbol_table)) { - zend_hash_str_update(&EG(active_symbol_table)->ht, name, len, value); + + if (force) { + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + if (symbol_table) { + return zend_hash_str_update(&symbol_table->ht, name, len, value) ? SUCCESS : FAILURE;; + } } } else { - return FAILURE; + return (zend_hash_str_update_ind(&execute_data->symbol_table->ht, name, len, value) != NULL) ? SUCCESS : FAILURE; } - } else { - return (zend_hash_str_update_ind(&EG(active_symbol_table)->ht, name, len, value) != NULL) ? SUCCESS : FAILURE; } - return SUCCESS; + return FAILURE; } /* }}} */ diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index f4847b0839..698b2d8cf3 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -132,10 +132,6 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished efree(op_array); } - if (generator->execute_data->prev_execute_data) { - generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call; - } - efree(generator->stack); generator->execute_data = NULL; } @@ -224,14 +220,11 @@ static int copy_closure_static_var(zval *var TSRMLS_DC, int num_args, va_list ar } /* }}} */ -/* Requires globals EG(scope), EG(current_scope), EG(This), - * EG(active_symbol_table) and EG(current_execute_data). */ -ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ +/* Requires globals EG(scope), EG(This) and EG(current_execute_data). */ +ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { zend_generator *generator; zend_execute_data *current_execute_data; - zend_op **opline_ptr; - zend_array *current_symbol_table; zend_execute_data *execute_data; zend_vm_stack current_stack = EG(argument_stack); @@ -260,16 +253,10 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v } /* Create new execution context. We have to back up and restore - * EG(current_execute_data), EG(opline_ptr) and EG(active_symbol_table) - * here because the function modifies or uses them */ + * EG(current_execute_data) here. */ current_execute_data = EG(current_execute_data); - opline_ptr = EG(opline_ptr); - current_symbol_table = EG(active_symbol_table); - EG(active_symbol_table) = NULL; - execute_data = zend_create_generator_execute_data(op_array, return_value TSRMLS_CC); - EG(active_symbol_table) = current_symbol_table; + execute_data = zend_create_generator_execute_data(call, op_array, return_value TSRMLS_CC); EG(current_execute_data) = current_execute_data; - EG(opline_ptr) = opline_ptr; object_init_ex(return_value, zend_ce_generator); @@ -314,43 +301,23 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ { /* Backup executor globals */ zend_execute_data *original_execute_data = EG(current_execute_data); - zend_op **original_opline_ptr = EG(opline_ptr); - zend_op_array *original_active_op_array = EG(active_op_array); - zend_array *original_active_symbol_table = EG(active_symbol_table); zend_object *original_This; zend_class_entry *original_scope = EG(scope); - zend_class_entry *original_called_scope = EG(called_scope); zend_vm_stack original_stack = EG(argument_stack); - zend_execute_data *prev_execute_data; original_This = Z_OBJ(EG(This)); /* Set executor globals */ EG(current_execute_data) = generator->execute_data; - EG(opline_ptr) = &generator->execute_data->opline; - EG(active_op_array) = &generator->execute_data->func->op_array; - EG(active_symbol_table) = generator->execute_data->symbol_table; 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 * called from whatever method we are current running (e.g. next()). * So we have to link generator call frame with caller call frames */ - prev_execute_data = original_execute_data; - if (prev_execute_data && - prev_execute_data->call && - (prev_execute_data->call->flags & ZEND_CALL_DONE)) { - prev_execute_data->call->prev_execute_data = prev_execute_data; - prev_execute_data = prev_execute_data->call; - } - generator->execute_data->prev_execute_data = prev_execute_data; - if (prev_execute_data) { - generator->execute_data->prev_nested_call = prev_execute_data->call; - prev_execute_data->call = generator->execute_data; - } + generator->execute_data->prev_execute_data = original_execute_data; /* Resume execution */ generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; @@ -358,19 +325,14 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING; /* Unlink generator call_frame from the caller */ - if (generator->execute_data && generator->execute_data->prev_execute_data) { - generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call; + if (generator->execute_data) { generator->execute_data->prev_execute_data = NULL; } /* Restore executor globals */ EG(current_execute_data) = original_execute_data; - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; - EG(active_symbol_table) = original_active_symbol_table; Z_OBJ(EG(This)) = original_This; EG(scope) = original_scope; - EG(called_scope) = original_called_scope; EG(argument_stack) = original_stack; /* If an exception was thrown in the generator we have to internally diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 999ead4b6e..5d1264cc4f 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -54,7 +54,7 @@ static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2; static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4; void zend_register_generator_ce(TSRMLS_D); -ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_value TSRMLS_DC); +ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC); ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC); ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 7a43e6e02f..082e733844 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -170,9 +170,6 @@ struct _zend_executor_globals { zend_array **symtable_cache_limit; zend_array **symtable_cache_ptr; - zend_op **opline_ptr; - - zend_array *active_symbol_table; zend_array symbol_table; /* main symbol table */ HashTable included_files; /* files already included */ @@ -183,14 +180,11 @@ struct _zend_executor_globals { int orig_error_reporting; int exit_status; - zend_op_array *active_op_array; - HashTable *function_table; /* function symbol table */ HashTable *class_table; /* class table */ HashTable *zend_constants; /* constants table */ zend_class_entry *scope; - zend_class_entry *called_scope; /* Scope of the calling class */ zval This; @@ -198,7 +192,6 @@ struct _zend_executor_globals { int ticks_count; - zend_bool in_execution; HashTable *in_autoload; zend_function *autoload_func; zend_bool full_tables_cleanup; @@ -246,7 +239,8 @@ struct _zend_executor_globals { zend_property_info std_property_info; - zend_bool active; + zend_bool active; + zend_bool valid_symbol_table; zend_op *start_op; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index ded81e2918..d5420dae76 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -90,11 +90,12 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun if (object) { fcic.called_scope = Z_OBJCE_P(object); } else if (obj_ce && - !(EG(called_scope) && - instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) { + !(EG(current_execute_data) && + EG(current_execute_data)->called_scope && + instanceof_function(EG(current_execute_data)->called_scope, obj_ce TSRMLS_CC))) { fcic.called_scope = obj_ce; } else { - fcic.called_scope = EG(called_scope); + fcic.called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL; } fcic.object = object ? Z_OBJ_P(object) : NULL; result = zend_call_function(&fci, &fcic TSRMLS_CC); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index e38fbfc640..cd6b0b4ad0 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -299,8 +299,8 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui zend_property_info *scope_property_info; zend_bool denied_access = 0; - if (cache_slot != -1 && EXPECTED(ce == CACHED_PTR_EX(EG(active_op_array), cache_slot))) { - property_info = CACHED_PTR_EX(EG(active_op_array), cache_slot + 1); + if (cache_slot != -1 && EXPECTED(ce == CACHED_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot))) { + property_info = CACHED_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot + 1); if (UNEXPECTED(!property_info)) { EG(std_property_info).flags = ZEND_ACC_PUBLIC; EG(std_property_info).name = member; @@ -339,7 +339,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name->val, member->val); } if (cache_slot != -1) { - CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info); + CACHE_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce, property_info); } return property_info; } @@ -355,7 +355,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui && (scope_property_info = zend_hash_find_ptr(&EG(scope)->properties_info, member)) != NULL && scope_property_info->flags & ZEND_ACC_PRIVATE) { if (cache_slot != -1) { - CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, scope_property_info); + CACHE_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce, scope_property_info); } return scope_property_info; } else if (property_info) { @@ -368,12 +368,12 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui } else { /* fall through, return property_info... */ if (cache_slot != -1) { - CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info); + CACHE_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce, property_info); } } } else { if (cache_slot != -1) { - CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, NULL); + CACHE_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce, NULL); } EG(std_property_info).flags = ZEND_ACC_PUBLIC; EG(std_property_info).name = member; @@ -905,7 +905,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { - zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func; + zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func; zval method_name, method_args; zval method_result; zend_class_entry *ce = Z_OBJCE_P(getThis()); @@ -1123,7 +1123,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { - zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func; + zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func; zval method_name, method_args; zval method_result; zend_class_entry *ce = EG(scope); @@ -1276,7 +1276,7 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p zend_property_info *property_info; if (UNEXPECTED(cache_slot == -1) || - (property_info = CACHED_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce)) == NULL) { + (property_info = CACHED_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce)) == NULL) { if (UNEXPECTED((property_info = zend_hash_find_ptr(&ce->properties_info, property_name)) == NULL)) { if (!silent) { @@ -1302,7 +1302,7 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p zend_update_class_constants(ce TSRMLS_CC); if (EXPECTED(cache_slot != -1)) { - CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info); + CACHE_POLYMORPHIC_PTR_EX(&EG(current_execute_data)->func->op_array, cache_slot, ce, property_info); } } diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 1ef0e1d7e7..af0070c5fb 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -77,11 +77,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC) if (object->ce != EG(scope)) { zend_class_entry *ce = object->ce; - zend_error(EG(in_execution) ? E_ERROR : E_WARNING, + zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING, "Call to private %s::__destruct() from context '%s'%s", ce->name->val, EG(scope) ? EG(scope)->name->val : "", - EG(in_execution) ? "" : " during shutdown ignored"); + EG(current_execute_data) ? "" : " during shutdown ignored"); return; } } else { @@ -90,11 +90,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC) if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) { zend_class_entry *ce = object->ce; - zend_error(EG(in_execution) ? E_ERROR : E_WARNING, + zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING, "Call to protected %s::__destruct() from context '%s'%s", ce->name->val, EG(scope) ? EG(scope)->name->val : "", - EG(in_execution) ? "" : " during shutdown ignored"); + EG(current_execute_data) ? "" : " during shutdown ignored"); return; } } diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 2031b017eb..b512c45672 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -305,6 +305,7 @@ ZEND_API void _zval_internal_ptr_dtor_wrapper(zval *zval_ptr) ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */ { + zend_array *symbol_table; HashTable *target = va_arg(args, HashTable*); zend_bool is_ref; zval tmp; @@ -312,16 +313,14 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, if (Z_CONST_FLAGS_P(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) { is_ref = Z_CONST_FLAGS_P(p) & IS_LEXICAL_REF; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - p = zend_hash_find(&EG(active_symbol_table)->ht, key->key); + symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + p = zend_hash_find(&symbol_table->ht, key->key); if (!p) { p = &tmp; ZVAL_NULL(&tmp); if (is_ref) { ZVAL_NEW_REF(&tmp, &tmp); - zend_hash_add_new(&EG(active_symbol_table)->ht, key->key, &tmp); + zend_hash_add_new(&symbol_table->ht, key->key, &tmp); Z_ADDREF_P(p); } else { zend_error(E_NOTICE,"Undefined variable: %s", key->key->val); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 50f0e53e14..89668bd3b5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1145,7 +1145,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST| retval = zend_std_get_static_property(ce, name, 0, ((OP1_TYPE == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); FREE_OP1(); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -1772,9 +1772,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) { vm_frame_kind frame_kind = EX(frame_kind); - zend_execute_data *prev_nested_call; - - EG(current_execute_data) = EX(prev_execute_data); if (frame_kind == VM_FRAME_NESTED_FUNCTION) { i_free_compiled_variables(execute_data TSRMLS_CC); @@ -1784,15 +1781,11 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) { zval_ptr_dtor((zval*)EX(func)->op_array.prototype); } - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_extra_args(execute_data TSRMLS_CC); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - EX(call) = prev_nested_call; - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; - EG(active_symbol_table) = EX(symbol_table); if (Z_OBJ(EG(This))) { if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { @@ -1811,7 +1804,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); - EG(called_scope) = EX(called_scope); if (UNEXPECTED(EG(exception) != NULL)) { zend_op *opline = EX(opline); @@ -1829,14 +1821,11 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) zend_detach_symbol_table(execute_data); destroy_op_array(&EX(func)->op_array TSRMLS_CC); efree(EX(func)); - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - EX(call) = prev_nested_call; zend_attach_symbol_table(execute_data); - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION_LEAVE(); @@ -1848,6 +1837,9 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } else { if (frame_kind == VM_FRAME_TOP_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); + } zend_vm_stack_free_extra_args(execute_data TSRMLS_CC); } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -1868,13 +1860,9 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) { zval_ptr_dtor((zval*)EX(func)->op_array.prototype); } - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); - if (EG(current_execute_data)) { - EG(current_execute_data)->call = prev_nested_call; - } - EG(opline_ptr) = NULL; ZEND_VM_RETURN(); } } @@ -2369,7 +2357,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS if (OP1_TYPE != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -2576,7 +2564,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zend_function *fbc = call->func; SAVE_OPLINE(); - call->flags = ZEND_CALL_DONE; + EX(call) = call->prev_nested_call; 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); @@ -2624,9 +2612,13 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) #else EG(scope) = fbc->common.scope; #endif - EG(called_scope) = call->called_scope; + } else { + call->called_scope = EX(called_scope); } + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { zend_uint i; zval *p = ZEND_CALL_ARG(call, 1); @@ -2636,6 +2628,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) p++; } if (UNEXPECTED(EG(exception) != NULL)) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call TSRMLS_CC); + zend_vm_stack_free_call_frame(call TSRMLS_CC); if (RETURN_VALUE_USED(opline)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } @@ -2655,12 +2650,10 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call->num_args, ret TSRMLS_CC); } else { - zend_execute_internal(execute_data, NULL TSRMLS_CC); + zend_execute_internal(call, ret TSRMLS_CC); } - + EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call TSRMLS_CC); - - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); if (!RETURN_VALUE_USED(opline)) { @@ -2677,9 +2670,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) Z_OBJ(EG(This)) = call->object; EG(scope) = fbc->common.scope; - EG(called_scope) = call->called_scope; - EG(active_symbol_table) = NULL; - EG(active_op_array) = &fbc->op_array; + call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); @@ -2689,16 +2680,15 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (RETURN_VALUE_USED(opline)) { - zend_generator_create_zval(&fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); + zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); } else { zend_vm_stack_free_args(call TSRMLS_CC); } - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); } else { - call->prev_execute_data = EG(current_execute_data); - i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_func_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); @@ -2706,31 +2696,25 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) execute_ex(call TSRMLS_CC); } } - - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; - 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); } else { /* ZEND_OVERLOADED_FUNCTION */ Z_OBJ(EG(This)) = call->object; //??? EG(scope) = NULL; EG(scope) = fbc->common.scope; - EG(called_scope) = 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(call->object != NULL)) { + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC); + EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } zend_vm_stack_free_args(call TSRMLS_CC); - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { @@ -2765,7 +2749,6 @@ ZEND_VM_C_LABEL(fcall_end_change_scope): } Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); - EG(called_scope) = EX(called_scope); ZEND_VM_C_LABEL(fcall_end): if (UNEXPECTED(EG(exception) != NULL)) { @@ -3538,14 +3521,14 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -3976,29 +3959,29 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { zval *return_value = NULL; + zend_execute_data *call; - EG(active_op_array) = new_op_array; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); } - EX(call) = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC); + call = zend_vm_stack_push_call_frame( + (zend_function*)new_op_array, 0, 0, EX(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } - EX(call)->prev_execute_data = EG(current_execute_data); - i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { - execute_ex(EG(current_execute_data) TSRMLS_CC); + execute_ex(call TSRMLS_CC); } - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); if (UNEXPECTED(EG(exception) != NULL)) { @@ -4070,7 +4053,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) } zend_std_unset_static_property(ce, Z_STR_P(varname), ((OP1_TYPE == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -4588,7 +4571,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -4829,7 +4812,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val); + zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(scope)->name->val, EX(func)->op_array.function_name->val); ZEND_VM_NEXT_OPCODE(); /* Never reached */ } @@ -5343,11 +5326,11 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) } closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; - closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC; + closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; if (closure_is_static || closure_is_being_defined_inside_static_context) { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); } CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 31f1b9d4ae..dcaa1657c6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -337,13 +337,9 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE - zend_bool original_in_execution; - original_in_execution = EG(in_execution); - EG(in_execution) = 1; - LOAD_REGS(); LOAD_OPLINE(); @@ -358,7 +354,6 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) { switch (ret) { case 1: - EG(in_execution) = original_in_execution; return; case 2: case 3: @@ -381,23 +376,21 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC return; } - if (EG(current_execute_data) && EG(current_execute_data)->call) { - execute_data = EG(current_execute_data)->call; + execute_data = zend_vm_stack_push_call_frame( + (zend_function*)op_array, 0, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, Z_OBJ(EG(This)), NULL TSRMLS_CC); + if (EG(current_execute_data)) { + execute_data->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } else { - execute_data = zend_vm_stack_push_call_frame( - (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); + execute_data->symbol_table = &EG(symbol_table); } EX(prev_execute_data) = EG(current_execute_data); - i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC); + i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_CODE TSRMLS_CC); zend_execute_ex(execute_data TSRMLS_CC); } static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { vm_frame_kind frame_kind = EX(frame_kind); - zend_execute_data *prev_nested_call; - - EG(current_execute_data) = EX(prev_execute_data); if (frame_kind == VM_FRAME_NESTED_FUNCTION) { i_free_compiled_variables(execute_data TSRMLS_CC); @@ -407,15 +400,11 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) { zval_ptr_dtor((zval*)EX(func)->op_array.prototype); } - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_extra_args(execute_data TSRMLS_CC); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - EX(call) = prev_nested_call; - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; - EG(active_symbol_table) = EX(symbol_table); if (Z_OBJ(EG(This))) { if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { @@ -434,7 +423,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); - EG(called_scope) = EX(called_scope); if (UNEXPECTED(EG(exception) != NULL)) { zend_op *opline = EX(opline); @@ -452,14 +440,11 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) zend_detach_symbol_table(execute_data); destroy_op_array(&EX(func)->op_array TSRMLS_CC); efree(EX(func)); - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - EX(call) = prev_nested_call; zend_attach_symbol_table(execute_data); - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION_LEAVE(); @@ -471,6 +456,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } else { if (frame_kind == VM_FRAME_TOP_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); + } zend_vm_stack_free_extra_args(execute_data TSRMLS_CC); } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -491,13 +479,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) { zval_ptr_dtor((zval*)EX(func)->op_array.prototype); } - prev_nested_call = EX(prev_nested_call); + EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); - if (EG(current_execute_data)) { - EG(current_execute_data)->call = prev_nested_call; - } - EG(opline_ptr) = NULL; ZEND_VM_RETURN(); } } @@ -528,7 +512,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_function *fbc = call->func; SAVE_OPLINE(); - call->flags = ZEND_CALL_DONE; + EX(call) = call->prev_nested_call; 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); @@ -576,9 +560,13 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) #else EG(scope) = fbc->common.scope; #endif - EG(called_scope) = call->called_scope; + } else { + call->called_scope = EX(called_scope); } + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { zend_uint i; zval *p = ZEND_CALL_ARG(call, 1); @@ -588,6 +576,9 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) p++; } if (UNEXPECTED(EG(exception) != NULL)) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call TSRMLS_CC); + zend_vm_stack_free_call_frame(call TSRMLS_CC); if (RETURN_VALUE_USED(opline)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } @@ -607,12 +598,10 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call->num_args, ret TSRMLS_CC); } else { - zend_execute_internal(execute_data, NULL TSRMLS_CC); + zend_execute_internal(call, ret TSRMLS_CC); } - + EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call TSRMLS_CC); - - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); if (!RETURN_VALUE_USED(opline)) { @@ -629,9 +618,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_OBJ(EG(This)) = call->object; EG(scope) = fbc->common.scope; - EG(called_scope) = call->called_scope; - EG(active_symbol_table) = NULL; - EG(active_op_array) = &fbc->op_array; + call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); @@ -641,16 +628,15 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (RETURN_VALUE_USED(opline)) { - zend_generator_create_zval(&fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); + zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); } else { zend_vm_stack_free_args(call TSRMLS_CC); } - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); } else { - call->prev_execute_data = EG(current_execute_data); - i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_func_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); @@ -658,31 +644,25 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) execute_ex(call TSRMLS_CC); } } - - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; - 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); } else { /* ZEND_OVERLOADED_FUNCTION */ Z_OBJ(EG(This)) = call->object; //??? EG(scope) = NULL; EG(scope) = fbc->common.scope; - EG(called_scope) = 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(call->object != NULL)) { + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC); + EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } zend_vm_stack_free_args(call TSRMLS_CC); - EX(call) = call->prev_nested_call; zend_vm_stack_free_call_frame(call TSRMLS_CC); if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { @@ -717,7 +697,6 @@ fcall_end_change_scope: } Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); - EG(called_scope) = EX(called_scope); fcall_end: if (UNEXPECTED(EG(exception) != NULL)) { @@ -1058,7 +1037,7 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR static int ZEND_FASTCALL ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val); + zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(scope)->name->val, EX(func)->op_array.function_name->val); ZEND_VM_NEXT_OPCODE(); /* Never reached */ } @@ -2698,14 +2677,14 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -2916,29 +2895,29 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { zval *return_value = NULL; + zend_execute_data *call; - EG(active_op_array) = new_op_array; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); } - EX(call) = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC); + call = zend_vm_stack_push_call_frame( + (zend_function*)new_op_array, 0, 0, EX(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } - EX(call)->prev_execute_data = EG(current_execute_data); - i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { - execute_ex(EG(current_execute_data) TSRMLS_CC); + execute_ex(call TSRMLS_CC); } - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); if (UNEXPECTED(EG(exception) != NULL)) { @@ -3563,7 +3542,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -3808,7 +3787,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (IS_CONST != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -4110,7 +4089,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -4173,7 +4152,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -4774,7 +4753,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (IS_CONST != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -5385,7 +5364,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -5608,7 +5587,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (IS_CONST != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -5812,7 +5791,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -5875,7 +5854,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -6095,7 +6074,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -6301,7 +6280,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (IS_CONST != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -6489,7 +6468,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -6552,7 +6531,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_ isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -6596,11 +6575,11 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER } closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; - closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC; + closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; if (closure_is_static || closure_is_being_defined_inside_static_context) { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); } CHECK_EXCEPTION(); @@ -7130,7 +7109,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (IS_CONST != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -7891,14 +7870,14 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -8110,29 +8089,29 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { zval *return_value = NULL; + zend_execute_data *call; - EG(active_op_array) = new_op_array; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); } - EX(call) = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC); + call = zend_vm_stack_push_call_frame( + (zend_function*)new_op_array, 0, 0, EX(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } - EX(call)->prev_execute_data = EG(current_execute_data); - i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { - execute_ex(EG(current_execute_data) TSRMLS_CC); + execute_ex(call TSRMLS_CC); } - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); if (UNEXPECTED(EG(exception) != NULL)) { @@ -8806,7 +8785,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_dtor(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -9250,7 +9229,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -9313,7 +9292,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -10495,7 +10474,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_dtor(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -10925,7 +10904,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -10988,7 +10967,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -11208,7 +11187,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_dtor(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -11490,7 +11469,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -11553,7 +11532,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -13151,14 +13130,14 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -13371,29 +13350,29 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { zval *return_value = NULL; + zend_execute_data *call; - EG(active_op_array) = new_op_array; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); } - EX(call) = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC); + call = zend_vm_stack_push_call_frame( + (zend_function*)new_op_array, 0, 0, EX(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } - EX(call)->prev_execute_data = EG(current_execute_data); - i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { - execute_ex(EG(current_execute_data) TSRMLS_CC); + execute_ex(call TSRMLS_CC); } - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); if (UNEXPECTED(EG(exception) != NULL)) { @@ -14718,7 +14697,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -15425,7 +15404,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (IS_VAR != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -15727,7 +15706,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -15918,7 +15897,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -17653,7 +17632,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (IS_VAR != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -19073,7 +19052,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -19848,7 +19827,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (IS_VAR != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -20052,7 +20031,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -20243,7 +20222,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -20963,7 +20942,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -21312,7 +21291,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (IS_VAR != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -21500,7 +21479,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -21563,7 +21542,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -23215,7 +23194,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (IS_VAR != IS_CONST) { /* previous opcode is ZEND_FETCH_CLASS */ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EG(called_scope); + ce = EX(called_scope); } } @@ -23815,14 +23794,14 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -30286,14 +30265,14 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(ce != EX(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EX(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EX(scope) ? EX(scope)->name->val : ""); } } } @@ -30504,29 +30483,29 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { zval *return_value = NULL; + zend_execute_data *call; - EG(active_op_array) = new_op_array; if (RETURN_VALUE_USED(opline)) { return_value = EX_VAR(opline->result.var); } - EX(call) = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC); + call = zend_vm_stack_push_call_frame( + (zend_function*)new_op_array, 0, 0, EX(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } - EX(call)->prev_execute_data = EG(current_execute_data); - i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { - execute_ex(EG(current_execute_data) TSRMLS_CC); + execute_ex(call TSRMLS_CC); } - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = &EX(func)->op_array; destroy_op_array(new_op_array TSRMLS_CC); efree(new_op_array); if (UNEXPECTED(EG(exception) != NULL)) { @@ -31700,7 +31679,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -32497,7 +32476,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -32688,7 +32667,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -35756,7 +35735,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -36621,7 +36600,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -36812,7 +36791,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -37530,7 +37509,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); if (retval == NULL) { switch (type) { @@ -37955,7 +37934,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND } zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(varname) : -1) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } @@ -38018,7 +37997,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC isset = 0; } } else { - target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 41a834de95..4825e02b53 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -3,15 +3,11 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE - zend_bool original_in_execution; {%HELPER_VARS%} {%INTERNAL_LABELS%} - original_in_execution = EG(in_execution); - EG(in_execution) = 1; - LOAD_REGS(); LOAD_OPLINE(); @@ -39,14 +35,15 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value return; } - if (EG(current_execute_data) && EG(current_execute_data)->call) { - execute_data = EG(current_execute_data)->call; + execute_data = zend_vm_stack_push_call_frame( + (zend_function*)op_array, 0, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, Z_OBJ(EG(This)), NULL TSRMLS_CC); + if (EG(current_execute_data)) { + execute_data->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } else { - execute_data = zend_vm_stack_push_call_frame( - (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC); + execute_data->symbol_table = &EG(symbol_table); } EX(prev_execute_data) = EG(current_execute_data); - i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC); + i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_CODE TSRMLS_CC); zend_{%EXECUTOR_NAME%}_ex(execute_data TSRMLS_CC); } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index bdc6cc79b8..b0a642084d 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -941,7 +941,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); - out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); + out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); @@ -973,7 +973,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, } out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); - out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); + out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); @@ -1043,7 +1043,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, // Executor is defined as a set of functions out($f, $m[1]."switch (ret) {\n" . $m[1]."\tcase 1:\n" . - $m[1]."\t\tEG(in_execution) = original_in_execution;\n". $m[1]."\t\treturn;\n". $m[1]."\tcase 2:\n" . $m[1]."\tcase 3:\n" . diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index ebea66323c..df264e02af 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2084,10 +2084,9 @@ PHP_FUNCTION(mb_parse_str) detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC); } else { zval tmp; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - ZVAL_ARR(&tmp, EG(active_symbol_table)); + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + + ZVAL_ARR(&tmp, symbol_table); detected = _php_mb_encoding_handler_ex(&info, &tmp, encstr TSRMLS_CC); } diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index de97f64db8..91b78ec6f0 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -219,12 +219,13 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) { /* substitute __COMPILER_HALT_OFFSET__ constant */ - zend_bool orig_in_execution = EG(in_execution); - zend_op_array *orig_op_array = EG(active_op_array); + zend_execute_data *orig_execute_data = EG(current_execute_data); + zend_execute_data fake_execute_data; zval *offset; - EG(in_execution) = 1; - EG(active_op_array) = op_array; + memset(&fake_execute_data, 0, sizeof(zend_execute_data)); + fake_execute_data.func = (zend_function*)op_array; + EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1 TSRMLS_CC)) != NULL) { zend_uint tv = ZEND_RESULT(opline).var; @@ -232,8 +233,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { MAKE_NOP(opline); replace_tmp_by_const(op_array, opline, tv, offset TSRMLS_CC); } - EG(active_op_array) = orig_op_array; - EG(in_execution) = orig_in_execution; + EG(current_execute_data) = orig_execute_data; break; } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 426156fa5b..c1775b8538 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -733,7 +733,7 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle #endif if (sapi_module.get_stat && - !EG(opline_ptr) && + !EG(current_execute_data) && file_handle->filename == SG(request_info).path_translated) { struct stat *tmpbuf = sapi_module.get_stat(TSRMLS_C); @@ -995,7 +995,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt since fopen_wrappers from version 4.0.7 use current script's path in include path too. */ - if (EG(in_execution) && + if (EG(current_execute_data) && (parent_script = zend_get_executed_filename(TSRMLS_C)) != NULL && parent_script[0] != '[') { @@ -1518,16 +1518,18 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T /* In case this callback is called from include_once, require_once or it's * a main FastCGI request, the key must be already calculated, and cached * persistent script already found */ - if ((EG(opline_ptr) == NULL && + if ((EG(current_execute_data) == NULL && ZCG(cache_opline) == NULL && file_handle->filename == SG(request_info).path_translated && ZCG(cache_persistent_script)) || - (EG(opline_ptr) && *EG(opline_ptr) && - *EG(opline_ptr) == ZCG(cache_opline) && - (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && + (EG(current_execute_data) && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type) && + EG(current_execute_data)->opline == ZCG(cache_opline) && + EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL && #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || - (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { + (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE || + EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) { #else ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { @@ -1682,11 +1684,13 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T /* see bug #15471 (old BTS) */ if (persistent_script->full_path) { - if (!EG(opline_ptr) || !*EG(opline_ptr) || - (*EG(opline_ptr))->opcode != ZEND_INCLUDE_OR_EVAL || + if (!EG(current_execute_data) || !EG(current_execute_data)->opline || + !EG(current_execute_data)->func || + !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) || + EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL || #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - ((*EG(opline_ptr))->extended_value != ZEND_INCLUDE_ONCE && - (*EG(opline_ptr))->extended_value != ZEND_REQUIRE_ONCE)) { + (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE && + EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) { #else ((*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_INCLUDE_ONCE && (*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_REQUIRE_ONCE)) { @@ -1843,8 +1847,10 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl !CG(interactive) && !ZCSG(restart_in_progress)) { - if (EG(opline_ptr) && *EG(opline_ptr)) { - zend_op *opline = *EG(opline_ptr); + if (EG(current_execute_data) && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { + zend_op *opline = EG(current_execute_data)->opline; if (opline->opcode == ZEND_INCLUDE_OR_EVAL && (opline->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || @@ -1940,14 +1946,15 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl !ZCSG(restart_in_progress)) { /* check if callback is called from include_once or it's a main request */ - if ((!EG(opline_ptr) && + if ((!EG(current_execute_data) && filename == SG(request_info).path_translated) || - (EG(opline_ptr) && - *EG(opline_ptr) && - (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && + (EG(current_execute_data) && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type) && + EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL && #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || - (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { + (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE || + EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) { #else ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { @@ -1960,11 +1967,11 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl handle->free_filename = 0; /* check if cached script was already found by resolve_path() */ - if ((EG(opline_ptr) == NULL && + if ((EG(current_execute_data) == NULL && ZCG(cache_opline) == NULL && ZCG(cache_persistent_script) != NULL) || - (EG(opline_ptr) && - (ZCG(cache_opline) == *EG(opline_ptr)))) { + (EG(current_execute_data) && + (ZCG(cache_opline) == EG(current_execute_data)->opline))) { persistent_script = ZCG(cache_persistent_script); handle->opened_path = estrndup(persistent_script->full_path->val, persistent_script->full_path->len); handle->type = ZEND_HANDLE_FILENAME; @@ -1983,8 +1990,8 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl handle->type = ZEND_HANDLE_FILENAME; memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1); ZCG(key_len) = persistent_script->full_path_len; - ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; - ZCG(cache_persistent_script) = EG(opline_ptr) ? persistent_script : NULL; + ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL; + ZCG(cache_persistent_script) = EG(current_execute_data) ? persistent_script : NULL; return SUCCESS; } #endif @@ -2005,14 +2012,15 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len !ZCSG(restart_in_progress)) { /* check if callback is called from include_once or it's a main request */ - if ((!EG(opline_ptr) && + if ((!EG(current_execute_data) && filename == SG(request_info).path_translated) || - (EG(opline_ptr) && - *EG(opline_ptr) && - (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && + (EG(current_execute_data) && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type) && + EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL && #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || - (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { + (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE || + EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) { #else ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { @@ -2034,7 +2042,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len if (persistent_script && !persistent_script->corrupted) { memcpy(ZCG(key), persistent_script->full_path->val, persistent_script->full_path->len + 1); ZCG(key_len) = persistent_script->full_path->len; - ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; + ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL; ZCG(cache_persistent_script) = persistent_script; return estrndup(persistent_script->full_path->val, persistent_script->full_path->len); } @@ -2051,7 +2059,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len !persistent_script->corrupted) { /* we have persistent script */ - ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; + ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL; ZCG(cache_persistent_script) = persistent_script; return estrndup(persistent_script->full_path->val, persistent_script->full_path->len); } @@ -2073,7 +2081,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len zend_shared_alloc_unlock(TSRMLS_C); SHM_PROTECT(); } - ZCG(cache_opline) = (EG(opline_ptr) && key) ? *EG(opline_ptr): NULL; + ZCG(cache_opline) = (EG(current_execute_data) && key) ? EG(current_execute_data)->opline : NULL; ZCG(cache_persistent_script) = key ? persistent_script : NULL; return resolved_path; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 1f76f7ca03..e47cfda894 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -297,20 +297,20 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc op_array->refcount = NULL; if (main_persistent_script) { - zend_bool orig_in_execution = EG(in_execution); - zend_op_array *orig_op_array = EG(active_op_array); + zend_execute_data *orig_execute_data = EG(current_execute_data); + zend_execute_data fake_execute_data; zval *offset; #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO main_persistent_script->early_binding = -1; #endif - EG(in_execution) = 1; - EG(active_op_array) = op_array; + memset(&fake_execute_data, 0, sizeof(fake_execute_data)); + fake_execute_data.func = (zend_function*)op_array; + EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1 TSRMLS_CC)) != NULL) { main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset); } - EG(active_op_array) = orig_op_array; - EG(in_execution) = orig_in_execution; + EG(current_execute_data) = orig_execute_data; } if (op_array->static_variables) { diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 048362d3ec..e2acb53724 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -283,13 +283,8 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char #endif if (new_op_array) { ZVAL_UNDEF(&result); - EG(active_op_array) = new_op_array; zend_try { - if (EG(current_execute_data)) { - EG(current_execute_data)->call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC); - } zend_execute(new_op_array, &result TSRMLS_CC); if (PHAR_G(cwd)) { efree(PHAR_G(cwd)); diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c index c94c245071..84d27ca046 100644 --- a/ext/readline/readline_cli.c +++ b/ext/readline/readline_cli.c @@ -432,8 +432,9 @@ static char *cli_completion_generator_ht(const char *text, int textlen, int *sta static char *cli_completion_generator_var(const char *text, int textlen, int *state TSRMLS_DC) /* {{{ */ { char *retval, *tmp; + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); - tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, EG(active_symbol_table) ? &EG(active_symbol_table)->ht : NULL, NULL TSRMLS_CC); + tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, symbol_table ? &symbol_table->ht : NULL, NULL TSRMLS_CC); if (retval) { retval = malloc(strlen(tmp) + 2); retval[0] = '$'; diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 0ec71d7625..a2596be3c6 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1232,7 +1232,7 @@ static void unset_zval_property(zval* object, char* name TSRMLS_DC) ZVAL_STRING(&member, name); old_scope = EG(scope); EG(scope) = Z_OBJCE_P(object); - Z_OBJ_HT_P(object)->unset_property(object, &member, 0 TSRMLS_CC); + Z_OBJ_HT_P(object)->unset_property(object, &member, -1 TSRMLS_CC); EG(scope) = old_scope; zval_ptr_dtor(&member); } else if (Z_TYPE_P(object) == IS_ARRAY) { diff --git a/ext/soap/soap.c b/ext/soap/soap.c index fe97793afe..d98d1fc494 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -92,7 +92,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const zend_object* _old_error_object = Z_OBJ(SOAP_GLOBAL(error_object));\ int _old_soap_version = SOAP_GLOBAL(soap_version);\ zend_bool _old_in_compilation = CG(in_compilation); \ - zend_bool _old_in_execution = EG(in_execution); \ zend_execute_data *_old_current_execute_data = EG(current_execute_data); \ zval *_old_stack_top = EG(argument_stack)->top; \ int _bailout = 0;\ @@ -104,7 +103,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const #define SOAP_CLIENT_END_CODE() \ } zend_catch {\ CG(in_compilation) = _old_in_compilation; \ - EG(in_execution) = _old_in_execution; \ EG(current_execute_data) = _old_current_execute_data; \ if (EG(exception) == NULL || \ !instanceof_function(zend_get_class_entry(EG(exception) TSRMLS_CC), soap_fault_class_entry TSRMLS_CC)) {\ @@ -2131,14 +2129,13 @@ static void soap_server_fault(char* code, char* string, char *actor, zval* detai static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) { - zend_bool _old_in_compilation, _old_in_execution; + zend_bool _old_in_compilation; zend_execute_data *_old_current_execute_data; int _old_http_response_code; char *_old_http_status_line; TSRMLS_FETCH(); _old_in_compilation = CG(in_compilation); - _old_in_execution = EG(in_execution); _old_current_execute_data = EG(current_execute_data); _old_http_response_code = SG(sapi_headers).http_response_code; _old_http_status_line = SG(sapi_headers).http_status_line; @@ -2204,7 +2201,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const call_old_error_handler(error_num, error_filename, error_lineno, format, args); } zend_catch { CG(in_compilation) = _old_in_compilation; - EG(in_execution) = _old_in_execution; EG(current_execute_data) = _old_current_execute_data; if (SG(sapi_headers).http_status_line) { efree(SG(sapi_headers).http_status_line); @@ -2287,7 +2283,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const call_old_error_handler(error_num, error_filename, error_lineno, format, args); } zend_catch { CG(in_compilation) = _old_in_compilation; - EG(in_execution) = _old_in_execution; EG(current_execute_data) = _old_current_execute_data; if (SG(sapi_headers).http_status_line) { efree(SG(sapi_headers).http_status_line); diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 5ec20cd563..cd0a050b98 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -286,16 +286,7 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha } STR_RELEASE(opened_path); if (new_op_array) { - EG(active_op_array) = new_op_array; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - ZVAL_UNDEF(&result); - if (EG(current_execute_data)) { - EG(current_execute_data)->call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC); - } zend_execute(new_op_array, &result TSRMLS_CC); destroy_op_array(new_op_array TSRMLS_CC); @@ -319,8 +310,6 @@ PHP_FUNCTION(spl_autoload) int found = 0, pos_len, pos1_len; char *pos, *pos1; zend_string *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions); - zend_op **original_opline_ptr = EG(opline_ptr); - zend_op_array *original_active_op_array = EG(active_op_array); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|S", &class_name, &file_exts) == FAILURE) { RETURN_FALSE; @@ -337,8 +326,6 @@ PHP_FUNCTION(spl_autoload) lc_name = STR_ALLOC(class_name->len, 0); zend_str_tolower_copy(lc_name->val, class_name->val, class_name->len); while (pos && *pos && !EG(exception)) { - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; pos1 = strchr(pos, ','); if (pos1) { pos1_len = pos1 - pos; @@ -354,15 +341,17 @@ PHP_FUNCTION(spl_autoload) } STR_FREE(lc_name); - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; - if (!found && !SPL_G(autoload_running)) { /* For internal errors, we generate E_ERROR, for direct calls an exception is thrown. * The "scope" is determined by an opcode, if it is ZEND_FETCH_CLASS we know function was called indirectly by * the Zend engine. */ - if (active_opline->opcode != ZEND_FETCH_CLASS) { + zend_execute_data *ex = EG(current_execute_data); + + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + if (ex && ex->opline->opcode != ZEND_FETCH_CLASS) { zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Class %s could not be loaded", class_name->val); } else { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be loaded", class_name->val); diff --git a/ext/standard/array.c b/ext/standard/array.c index e1113a8ed5..06f04aed2c 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1294,6 +1294,7 @@ PHP_FUNCTION(extract) ulong num_key; int var_exists, count = 0; int extract_refs = 0; + zend_array *symbol_table; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|lz/", &var_array, &extract_type, &prefix) == FAILURE) { return; @@ -1320,9 +1321,7 @@ PHP_FUNCTION(extract) } } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + symbol_table = zend_rebuild_symbol_table(TSRMLS_C); ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(var_array), num_key, var_name, entry) { zval final_name; @@ -1331,7 +1330,7 @@ PHP_FUNCTION(extract) var_exists = 0; if (var_name) { - var_exists = zend_hash_exists_ind(&EG(active_symbol_table)->ht, var_name); + var_exists = zend_hash_exists_ind(&symbol_table->ht, var_name); } else if (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID) { zval num; @@ -1401,14 +1400,14 @@ PHP_FUNCTION(extract) ZVAL_MAKE_REF(entry); Z_ADDREF_P(entry); - if ((orig_var = zend_hash_find(&EG(active_symbol_table)->ht, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(&symbol_table->ht, Z_STR(final_name))) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); ZVAL_COPY_VALUE(orig_var, entry); } else { - zend_hash_update(&EG(active_symbol_table)->ht, Z_STR(final_name), entry); + zend_hash_update(&symbol_table->ht, Z_STR(final_name), entry); } } else { if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry); @@ -1458,14 +1457,13 @@ PHP_FUNCTION(compact) { zval *args = NULL; /* function arguments array */ int num_args, i; + zend_array *symbol_table; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) { return; } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + symbol_table = zend_rebuild_symbol_table(TSRMLS_C); /* compact() is probably most used with a single array of var_names or multiple string names, rather than a combination of both. @@ -1477,7 +1475,7 @@ PHP_FUNCTION(compact) } for (i=0; i<ZEND_NUM_ARGS(); i++) { - php_compact_var(&EG(active_symbol_table)->ht, return_value, &args[i] TSRMLS_CC); + php_compact_var(&symbol_table->ht, return_value, &args[i] TSRMLS_CC); } } /* }}} */ diff --git a/ext/standard/assert.c b/ext/standard/assert.c index 3ec7361197..e64e2e1ecb 100644 --- a/ext/standard/assert.c +++ b/ext/standard/assert.c @@ -53,7 +53,7 @@ enum { static PHP_INI_MH(OnChangeCallback) /* {{{ */ { - if (EG(in_execution)) { + if (EG(current_execute_data)) { if (Z_TYPE(ASSERTG(callback)) != IS_UNDEF) { zval_ptr_dtor(&ASSERTG(callback)); ZVAL_UNDEF(&ASSERTG(callback)); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index c8b3f96bc5..644e364f21 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -4759,15 +4759,15 @@ PHP_FUNCTION(forward_static_call) return; } - if (!EG(active_op_array)->scope) { + if (!EG(current_execute_data)->prev_execute_data->func->common.scope) { zend_error(E_ERROR, "Cannot call forward_static_call() when no class scope is active"); } fci.retval = &retval; - if (EG(called_scope) && - instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) { - fci_cache.called_scope = EG(called_scope); + if (EG(current_execute_data)->called_scope && + instanceof_function(EG(current_execute_data)->called_scope, fci_cache.calling_scope TSRMLS_CC)) { + fci_cache.called_scope = EG(current_execute_data)->called_scope; } if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { @@ -4791,9 +4791,9 @@ PHP_FUNCTION(forward_static_call_array) zend_fcall_info_args(&fci, params TSRMLS_CC); fci.retval = &retval; - if (EG(called_scope) && - instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) { - fci_cache.called_scope = EG(called_scope); + if (EG(current_execute_data)->called_scope && + instanceof_function(EG(current_execute_data)->called_scope, fci_cache.calling_scope TSRMLS_CC)) { + fci_cache.called_scope = EG(current_execute_data)->called_scope; } if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 2b10370710..f7d6fc4500 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -141,6 +141,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, int follow_location = 1; php_stream_filter *transfer_encoding = NULL; int response_code; + zend_array *symbol_table; tmp_line[0] = '\0'; @@ -634,9 +635,7 @@ finish: location[0] = '\0'; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + symbol_table = zend_rebuild_symbol_table(TSRMLS_C); if (header_init) { zval ztmp; @@ -644,7 +643,7 @@ finish: zend_set_local_var_str("http_response_header", sizeof("http_response_header")-1, &ztmp, 0 TSRMLS_CC); } - response_header = zend_hash_str_find_ind(&EG(active_symbol_table)->ht, "http_response_header", sizeof("http_response_header")-1); + response_header = zend_hash_str_find_ind(&symbol_table->ht, "http_response_header", sizeof("http_response_header")-1); if (!php_stream_eof(stream)) { size_t tmp_line_len; diff --git a/ext/standard/string.c b/ext/standard/string.c index 3250241bc6..ceebf77a70 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4221,11 +4221,9 @@ PHP_FUNCTION(parse_str) if (arrayArg == NULL) { zval tmp; + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - ZVAL_ARR(&tmp, EG(active_symbol_table)); + ZVAL_ARR(&tmp, symbol_table); sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC); } else { zval ret; diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index a87f97fdcf..0b853f34f2 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -668,10 +668,8 @@ static void php_wddx_add_var(wddx_packet *packet, zval *name_var) TSRMLS_FETCH(); if (Z_TYPE_P(name_var) == IS_STRING) { - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - if ((val = zend_hash_find(&EG(active_symbol_table)->ht, Z_STR_P(name_var))) != NULL) { + zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + if ((val = zend_hash_find(&symbol_table->ht, Z_STR_P(name_var))) != NULL) { if (Z_TYPE_P(val) == IS_INDIRECT) { val = Z_INDIRECT_P(val); } diff --git a/main/SAPI.c b/main/SAPI.c index e587f7aaf7..229396dd79 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -947,7 +947,7 @@ SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries TSRMLS_DC) SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC) { - if (SG(sapi_started) && EG(in_execution)) { + if (SG(sapi_started) && EG(current_execute_data)) { return FAILURE; } return zend_hash_str_add_mem(&SG(known_post_content_types), @@ -957,7 +957,7 @@ SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC) SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC) { - if (SG(sapi_started) && EG(in_execution)) { + if (SG(sapi_started) && EG(current_execute_data)) { return; } zend_hash_str_del(&SG(known_post_content_types), post_entry->content_type, @@ -967,7 +967,7 @@ SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC) SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D) TSRMLS_DC) { - if (SG(sapi_started) && EG(in_execution)) { + if (SG(sapi_started) && EG(current_execute_data)) { return FAILURE; } sapi_module.default_post_reader = default_post_reader; @@ -977,7 +977,7 @@ SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRML SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC) TSRMLS_DC) { - if (SG(sapi_started) && EG(in_execution)) { + if (SG(sapi_started) && EG(current_execute_data)) { return FAILURE; } sapi_module.treat_data = treat_data; @@ -986,7 +986,7 @@ SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zva SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D) TSRMLS_DC) { - if (SG(sapi_started) && EG(in_execution)) { + if (SG(sapi_started) && EG(current_execute_data)) { return FAILURE; } sapi_module.input_filter = input_filter; diff --git a/main/main.c b/main/main.c index 0e17be81f9..f4f88d5360 100644 --- a/main/main.c +++ b/main/main.c @@ -770,6 +770,8 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c } else if (php_during_module_shutdown()) { function = "PHP Shutdown"; } else if (EG(current_execute_data) && + EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->common.type) && EG(current_execute_data)->opline && EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL ) { @@ -897,12 +899,16 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c efree(docref_buf); } - if (PG(track_errors) && module_initialized && + if (PG(track_errors) && module_initialized && EG(valid_symbol_table) && (Z_TYPE(EG(user_error_handler)) == IS_UNDEF || !(EG(user_error_handler_error_reporting) & type))) { zval tmp; ZVAL_STRINGL(&tmp, buffer, buffer_len); - if (zend_set_local_var_str("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) { - zval_ptr_dtor(&tmp); + if (EG(current_execute_data)) { + if (zend_set_local_var_str("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) { + zval_ptr_dtor(&tmp); + } + } else { + zend_hash_str_update_ind(&EG(symbol_table).ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp); } } if (replace_buffer) { @@ -1227,16 +1233,16 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ return; } - if (PG(track_errors) && module_initialized) { - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - if (EG(active_symbol_table)) { - zval tmp; - ZVAL_STRINGL(&tmp, buffer, buffer_len); + if (PG(track_errors) && module_initialized && EG(valid_symbol_table)) { + zval tmp; + + ZVAL_STRINGL(&tmp, buffer, buffer_len); + if (EG(current_execute_data)) { if (zend_set_local_var_str("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) { zval_ptr_dtor(&tmp); } + } else { + zend_hash_str_update_ind(&EG(symbol_table).ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp); } } @@ -1776,11 +1782,10 @@ void php_request_shutdown(void *dummy) report_memleaks = PG(report_memleaks); - /* EG(opline_ptr) points into nirvana and therefore cannot be safely accessed + /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed * inside zend_executor callback functions. */ - EG(opline_ptr) = NULL; - EG(active_op_array) = NULL; + EG(current_execute_data) = NULL; php_deactivate_ticks(TSRMLS_C); @@ -2126,7 +2131,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod #endif EG(bailout) = NULL; EG(error_reporting) = E_ALL & ~E_NOTICE; - EG(active_symbol_table) = NULL; PG(header_is_being_sent) = 0; SG(request_info).headers_only = 0; SG(request_info).argv0 = NULL; diff --git a/main/php_variables.c b/main/php_variables.c index fbd91dc286..3bb6d65aa5 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -110,8 +110,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars } /* GLOBALS hijack attempt, reject parameter */ - if (symtable1 && EG(active_symbol_table) && - symtable1 == &EG(active_symbol_table)->ht && + if (symtable1 == &EG(symbol_table).ht && var_len == sizeof("GLOBALS")-1 && !memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) { zval_dtor(val); |
