Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:34855 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 81262 invoked by uid 1010); 21 Jan 2008 19:47:47 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 81247 invoked from network); 21 Jan 2008 19:47:46 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Jan 2008 19:47:46 -0000 Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 212.25.124.162 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 212.25.124.162 mail.zend.com Linux 2.5 (sometimes 2.4) (4) Received: from [212.25.124.162] ([212.25.124.162:31299] helo=mail.zend.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 85/C5-42899-0E6F4974 for ; Mon, 21 Jan 2008 14:47:46 -0500 Received: (qmail 25969 invoked from network); 21 Jan 2008 19:47:41 -0000 Received: from mail.zend.net (HELO ?127.0.0.1?) (10.1.1.1) by cvs.zend.com with SMTP; 21 Jan 2008 19:47:41 -0000 Message-ID: <4794F6DA.8010400@zend.com> Date: Mon, 21 Jan 2008 22:47:38 +0300 User-Agent: Thunderbird 2.0.0.9 (Windows/20071031) MIME-Version: 1.0 To: PHP Internals List Content-Type: multipart/mixed; boundary="------------000306080100090102040203" Subject: Segmented argument_stack From: dmitry@zend.com (Dmitry Stogov) --------------000306080100090102040203 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi, The attached patch (for PHP_5_3) implements the segmented argument_stack that has the following advantages: 1) It fixes #43426 and other crashes which occur because of stack reallocation. 2) The whole stack is never reallocated. So we don't have penalties because of the while stack copying (it may be 1MB and more). 3) CPU stack usage reduced, because execute_data, Ts and CVs now are stored in the same argument_stack. As result the probability of CPU stack overflow is reduced. 4) func_num_args(), func_get_agr(), func_get_args(), debug_print_backtrace() and exception's backtrace now always able to get arguments. They didn't work before in case of incomplete "arguments frame". For example: "foo(1, func_num_args());". 5) bench.php got about 1% speedup I'm going to commit the patch into HEAD and PHP_5_3 on Thursday. Any objections? Thanks. Dmitry. --------------000306080100090102040203 Content-Type: text/plain; name="stack-2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="stack-2.diff" Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.34.2.15 diff -u -p -d -r1.296.2.27.2.34.2.15 zend_API.c --- Zend/zend_API.c 31 Dec 2007 07:17:04 -0000 1.296.2.27.2.34.2.15 +++ Zend/zend_API.c 18 Jan 2008 14:04:43 -0000 @@ -43,7 +43,7 @@ ZEND_API int zend_get_parameters(int ht, zval **param, *param_ptr; TSRMLS_FETCH(); - p = EG(argument_stack).top_element-2; + p = zend_vm_stack_top(TSRMLS_C) - 1; arg_count = (int)(zend_uintptr_t) *p; if (param_count>arg_count) { @@ -81,7 +81,7 @@ ZEND_API int _zend_get_parameters_array( int arg_count; zval *param_ptr; - p = EG(argument_stack).top_element-2; + p = zend_vm_stack_top(TSRMLS_C) - 1; arg_count = (int)(zend_uintptr_t) *p; if (param_count>arg_count) { @@ -119,7 +119,7 @@ ZEND_API int zend_get_parameters_ex(int zval ***param; TSRMLS_FETCH(); - p = EG(argument_stack).top_element-2; + p = zend_vm_stack_top(TSRMLS_C) - 1; arg_count = (int)(zend_uintptr_t) *p; if (param_count>arg_count) { @@ -142,7 +142,7 @@ ZEND_API int _zend_get_parameters_array_ void **p; int arg_count; - p = EG(argument_stack).top_element-2; + p = zend_vm_stack_top(TSRMLS_C) - 1; arg_count = (int)(zend_uintptr_t) *p; if (param_count>arg_count) { @@ -187,7 +187,7 @@ ZEND_API int zend_copy_parameters_array( void **p; int arg_count; - p = EG(argument_stack).top_element-2; + p = zend_vm_stack_top(TSRMLS_C) - 1; arg_count = (int)(zend_uintptr_t) *p; if (param_count>arg_count) { @@ -746,7 +746,7 @@ static int zend_parse_va_args(int num_ar return FAILURE; } - arg_count = (int)(zend_uintptr_t) *(EG(argument_stack).top_element-2); + arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1); if (num_args > arg_count) { zend_error(E_WARNING, "%s(): could not obtain parameters for parsing", @@ -770,7 +770,7 @@ static int zend_parse_va_args(int num_ar if (num_varargs > 0) { int iv = 0; - zval **p = (zval **) (EG(argument_stack).top_element - 2 - (arg_count - i)); + zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i)); *n_varargs = num_varargs; @@ -790,7 +790,7 @@ static int zend_parse_va_args(int num_ar } } - arg = (zval **) (EG(argument_stack).top_element - 2 - (arg_count-i)); + arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i)); if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) { /* clean up varargs array if it was used */ Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.277.2.12.2.25.2.7 diff -u -p -d -r1.277.2.12.2.25.2.7 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 31 Dec 2007 07:17:04 -0000 1.277.2.12.2.25.2.7 +++ Zend/zend_builtin_functions.c 18 Jan 2008 14:04:43 -0000 @@ -171,18 +171,10 @@ ZEND_FUNCTION(zend_version) Get the number of arguments that were passed to the function */ ZEND_FUNCTION(func_num_args) { - void **p; - int arg_count; + zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; - p = EG(argument_stack).top_element-1-1; - arg_count = (int)(zend_uintptr_t) *p; /* this is the amount of arguments passed to func_num_args(); */ - p -= 1+arg_count; - if (*p) { - zend_error(E_ERROR, "func_num_args(): Can't be used as a function parameter"); - } - --p; - if (p>=EG(argument_stack).elements) { - RETURN_LONG((long)(zend_uintptr_t) *p); + if (ex && ex->function_state.arguments) { + RETURN_LONG((long)(zend_uintptr_t)*(ex->function_state.arguments)); } else { zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context"); RETURN_LONG(-1); @@ -200,6 +192,7 @@ ZEND_FUNCTION(func_get_arg) zval **z_requested_offset; zval *arg; long requested_offset; + zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &z_requested_offset)==FAILURE) { RETURN_FALSE; @@ -212,20 +205,15 @@ ZEND_FUNCTION(func_get_arg) RETURN_FALSE; } - p = EG(argument_stack).top_element-1-1; - arg_count = (int)(zend_uintptr_t) *p; /* this is the amount of arguments passed to func_get_arg(); */ - p -= 1+arg_count; - if (*p) { - zend_error(E_ERROR, "func_get_arg(): Can't be used as a function parameter"); - } - --p; - if (pfunction_state.arguments) { zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context"); RETURN_FALSE; } - arg_count = (int)(zend_uintptr_t) *p; - if (requested_offset>=arg_count) { + p = ex->function_state.arguments; + arg_count = (int)(zend_uintptr_t) *p; /* this is the amount of arguments passed to func_get_arg(); */ + + if (requested_offset >= arg_count) { zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset); RETURN_FALSE; } @@ -245,21 +233,15 @@ ZEND_FUNCTION(func_get_args) void **p; int arg_count; int i; + zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; - p = EG(argument_stack).top_element-1-1; - arg_count = (int)(zend_uintptr_t) *p; /* this is the amount of arguments passed to func_get_args(); */ - p -= 1+arg_count; - if (*p) { - zend_error(E_ERROR, "func_get_args(): Can't be used as a function parameter"); - } - --p; - - if (pfunction_state.arguments) { zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context"); RETURN_FALSE; } - arg_count = (int)(zend_uintptr_t) *p; + p = ex->function_state.arguments; + arg_count = (int)(zend_uintptr_t) *p; /* this is the amount of arguments passed to func_get_args(); */ array_init(return_value); for (i=0; i EG(argument_stack).elements) && *((*curpos)-1)) { - (*curpos)--; - } - return arg_array; } @@ -1744,47 +1719,16 @@ ZEND_FUNCTION(debug_print_backtrace) char *call_type; char *include_filename = NULL; zval *arg_array = NULL; - void **cur_arg_pos = EG(argument_stack).top_element; - void **args = cur_arg_pos; - int arg_stack_consistent = 0; - int frames_on_stack = 0; int indent = 0; if (ZEND_NUM_ARGS()) { ZEND_WRONG_PARAM_COUNT(); } - while (--args > EG(argument_stack).elements) { - if (*args--) { - break; - } - args -= *(ulong*)args; - frames_on_stack++; - - /* skip args from incomplete frames */ - while (((args-1) > EG(argument_stack).elements) && *(args-1)) { - args--; - } - - if ((args-1) == EG(argument_stack).elements) { - arg_stack_consistent = 1; - break; - } - } - ptr = EG(current_execute_data); /* skip debug_backtrace() */ ptr = ptr->prev_execute_data; - cur_arg_pos -= 2; - frames_on_stack--; - - if (arg_stack_consistent) { - /* skip args from incomplete frames */ - while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { - cur_arg_pos--; - } - } while (ptr) { char *free_class_name = NULL; @@ -1800,7 +1744,7 @@ ZEND_FUNCTION(debug_print_backtrace) skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { - skip = skip->prev_execute_data; + skip = skip->prev_execute_data; } if (skip->op_array) { @@ -1836,9 +1780,8 @@ ZEND_FUNCTION(debug_print_backtrace) call_type = NULL; } if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { - if (arg_stack_consistent && (frames_on_stack > 0)) { - arg_array = debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC); - frames_on_stack--; + if (ptr->function_state.arguments) { + arg_array = debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC); } } } else { @@ -1933,28 +1876,6 @@ ZEND_API void zend_fetch_debug_backtrace char *class_name; char *include_filename = NULL; zval *stack_frame; - void **cur_arg_pos = EG(argument_stack).top_element; - void **args = cur_arg_pos; - int arg_stack_consistent = 0; - int frames_on_stack = 0; - - while (--args > EG(argument_stack).elements) { - if (*args--) { - break; - } - args -= *(ulong*)args; - frames_on_stack++; - - /* skip args from incomplete frames */ - while (((args-1) > EG(argument_stack).elements) && *(args-1)) { - args--; - } - - if ((args-1) == EG(argument_stack).elements) { - arg_stack_consistent = 1; - break; - } - } ptr = EG(current_execute_data); @@ -1965,17 +1886,7 @@ ZEND_API void zend_fetch_debug_backtrace /* skip debug_backtrace() */ if (skip_last-- && ptr) { - int arg_count = *((ulong*)(cur_arg_pos - 2)); - cur_arg_pos -= (arg_count + 2); - frames_on_stack--; ptr = ptr->prev_execute_data; - - if (arg_stack_consistent) { - /* skip args from incomplete frames */ - while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { - cur_arg_pos--; - } - } } array_init(return_value); @@ -2050,9 +1961,8 @@ ZEND_API void zend_fetch_debug_backtrace } if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { - if (arg_stack_consistent && (frames_on_stack > 0)) { - add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC)); - frames_on_stack--; + if (ptr->function_state.arguments) { + add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC)); } } } else { Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.316.2.8.2.12.2.12 diff -u -p -d -r1.316.2.8.2.12.2.12 zend_compile.h --- Zend/zend_compile.h 31 Dec 2007 07:17:04 -0000 1.316.2.8.2.12.2.12 +++ Zend/zend_compile.h 18 Jan 2008 14:04:43 -0000 @@ -271,6 +271,7 @@ typedef union _zend_function { typedef struct _zend_function_state { zend_function *function; + void **arguments; } zend_function_state; @@ -299,7 +300,6 @@ struct _zend_execute_data { union _temp_variable *Ts; zval ***CVs; zend_bool original_in_execution; - ALLOCA_FLAG(use_heap) HashTable *symbol_table; struct _zend_execute_data *prev_execute_data; zval *old_error_reporting; Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.716.2.12.2.24.2.14 diff -u -p -d -r1.716.2.12.2.24.2.14 zend_execute.c --- Zend/zend_execute.c 15 Jan 2008 11:52:44 -0000 1.716.2.12.2.24.2.14 +++ Zend/zend_execute.c 18 Jan 2008 14:04:44 -0000 @@ -1457,10 +1457,10 @@ ZEND_API void execute_internal(zend_exec } #define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ - free_alloca(EX(CVs), EX(use_heap)); \ EG(in_execution) = EX(original_in_execution); \ EG(current_execute_data) = EX(prev_execute_data); \ - EG(opline_ptr) = NULL; + EG(opline_ptr) = NULL; \ + zend_vm_stack_free(execute_data TSRMLS_CC); #define ZEND_VM_RETURN_FROM_EXECUTE_LOOP() \ ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ Index: Zend/zend_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_execute.h,v retrieving revision 1.84.2.4.2.8.2.2 diff -u -p -d -r1.84.2.4.2.8.2.2 zend_execute.h --- Zend/zend_execute.h 31 Dec 2007 07:17:04 -0000 1.84.2.4.2.8.2.2 +++ Zend/zend_execute.h 18 Jan 2008 14:04:44 -0000 @@ -143,30 +143,158 @@ ZEND_API int zval_update_constant(zval * ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC); /* dedicated Zend executor functions - do not use! */ -static inline void zend_ptr_stack_clear_multiple(TSRMLS_D) +#define ZEND_VM_STACK_PAGE_SIZE (64 * 1024) + +struct _zend_vm_stack { + void **top; + void **end; + zend_vm_stack prev; + void *elements[1]; +}; + +#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \ + do { \ + if (UNEXPECTED(count > \ + EG(argument_stack)->end - EG(argument_stack)->top)) { \ + zend_vm_stack_extend(count TSRMLS_CC); \ + } \ + } while (0) + +static inline zend_vm_stack zend_vm_stack_new_page(int count) { + zend_vm_stack page = emalloc(sizeof(*page)+sizeof(page->elements[0])*(count-1)); + + page->top = page->elements; + page->end = page->elements + count; + page->prev = NULL; + return page; +} + +static inline void zend_vm_stack_init(TSRMLS_D) { - void **p = EG(argument_stack).top_element-2; + EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE); +} + +static inline void zend_vm_stack_destroy(TSRMLS_D) +{ + zend_vm_stack stack = EG(argument_stack); + + while (stack != NULL) { + zend_vm_stack p = stack->prev; + efree(stack); + stack = p; + } +} + +static inline void zend_vm_stack_extend(int count TSRMLS_DC) +{ + zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE); + p->prev = EG(argument_stack); + EG(argument_stack) = p; +} + +static inline void **zend_vm_stack_top(TSRMLS_D) +{ + return EG(argument_stack)->top; +} + +static inline void zend_vm_stack_push(void *ptr TSRMLS_DC) +{ + ZEND_VM_STACK_GROW_IF_NEEDED(1); + *(EG(argument_stack)->top++) = ptr; +} + +static inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC) +{ + *(EG(argument_stack)->top++) = ptr; +} + +static inline void *zend_vm_stack_pop(TSRMLS_D) +{ + void *el = *(--EG(argument_stack)->top); + + if (UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->elements)) { + zend_vm_stack p = EG(argument_stack); + EG(argument_stack) = p->prev; + efree(p); + } + return el; +} + +static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC) +{ + void *ret; + + size = (size + (sizeof(void*) - 1)) / sizeof(void*); + + ZEND_VM_STACK_GROW_IF_NEEDED(size); + ret = EG(argument_stack)->top; + EG(argument_stack)->top += size; + return ret; +} + +static inline void zend_vm_stack_free(void *ptr TSRMLS_DC) +{ + if (UNEXPECTED(EG(argument_stack)->elements == ptr)) { + zend_vm_stack p = EG(argument_stack); + + EG(argument_stack) = p->prev; + efree(p); + } else { + EG(argument_stack)->top = ptr; + } +} + +static inline void** zend_vm_stack_push_args(int count TSRMLS_DC) +{ + + if (UNEXPECTED(EG(argument_stack)->top - EG(argument_stack)->elements < count) || + UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) { + zend_vm_stack p = EG(argument_stack); + + zend_vm_stack_extend(count + 1 TSRMLS_CC); + + EG(argument_stack)->top += count; + *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; + while (count-- > 0) { + void *data = *(--p->top); + + if (UNEXPECTED(p->top == p->elements)) { + zend_vm_stack r = p; + + EG(argument_stack)->prev = p->prev; + p = p->prev; + efree(r); + } + *(EG(argument_stack)->elements + count) = data; + } + return EG(argument_stack)->top++; + } + *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; + return EG(argument_stack)->top++; +} + +static inline void zend_vm_stack_clear_multiple(TSRMLS_D) +{ + void **p = EG(argument_stack)->top - 1; int delete_count = (int)(zend_uintptr_t) *p; - EG(argument_stack).top -= (delete_count+2); while (--delete_count>=0) { zval *q = *(zval **)(--p); *p = NULL; zval_ptr_dtor(&q); } - EG(argument_stack).top_element = p; + zend_vm_stack_free(p TSRMLS_CC); } -static inline int zend_ptr_stack_get_arg(int requested_arg, void **data TSRMLS_DC) +static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) { - void **p = EG(argument_stack).top_element-2; + void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments; int arg_count = (int)(zend_uintptr_t) *p; - if (requested_arg>arg_count) { - return FAILURE; + if (UNEXPECTED(requested_arg > arg_count)) { + return NULL; } - *data = (p-arg_count+requested_arg-1); - return SUCCESS; + return (zval**)p - arg_count + requested_arg - 1; } void execute_new_code(TSRMLS_D); Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.331.2.20.2.24.2.19 diff -u -p -d -r1.331.2.20.2.24.2.19 zend_execute_API.c --- Zend/zend_execute_API.c 15 Jan 2008 11:47:05 -0000 1.331.2.20.2.24.2.19 +++ Zend/zend_execute_API.c 18 Jan 2008 14:04:44 -0000 @@ -146,8 +146,8 @@ void init_executor(TSRMLS_D) /* {{{ */ EG(in_autoload) = NULL; EG(autoload_func) = NULL; - zend_ptr_stack_init(&EG(argument_stack)); - zend_ptr_stack_push(&EG(argument_stack), (void *) NULL); + zend_vm_stack_init(TSRMLS_C); + zend_vm_stack_push((void *) NULL TSRMLS_CC); zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0); { @@ -287,7 +287,7 @@ void shutdown_executor(TSRMLS_D) /* {{{ } zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC); - zend_ptr_stack_destroy(&EG(argument_stack)); + zend_vm_stack_destroy(TSRMLS_C); /* Destroy all op arrays */ if (EG(full_tables_cleanup)) { @@ -939,6 +939,12 @@ int zend_call_function(zend_fcall_info * } } + if (call_via_handler) { + ZEND_VM_STACK_GROW_IF_NEEDED(2 + 1); + } else { + ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1); + } + for (i=0; iparam_count; i++) { zval *param; @@ -951,8 +957,8 @@ int zend_call_function(zend_fcall_info * if (fci->no_separation) { if(i) { /* hack to clean up the stack */ - zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (zend_uintptr_t) i, NULL); - zend_ptr_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC); + zend_vm_stack_clear_multiple(TSRMLS_C); } if (call_via_handler) { @@ -988,17 +994,18 @@ int zend_call_function(zend_fcall_info * if (call_via_handler) { add_next_index_zval(params_array, param); } else { - zend_ptr_stack_push(&EG(argument_stack), param); + zend_vm_stack_push_nocheck(param TSRMLS_CC); } } if (call_via_handler) { - zend_ptr_stack_push(&EG(argument_stack), method_name); - zend_ptr_stack_push(&EG(argument_stack), params_array); + zend_vm_stack_push_nocheck(method_name TSRMLS_CC); + zend_vm_stack_push_nocheck(params_array TSRMLS_CC); fci->param_count = 2; } - zend_ptr_stack_2_push(&EG(argument_stack), (void *) (zend_uintptr_t) fci->param_count, NULL); + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push_nocheck((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC); current_scope = EG(scope); EG(scope) = calling_scope; @@ -1087,7 +1094,7 @@ int zend_call_function(zend_fcall_info * *fci->retval_ptr_ptr = NULL; } } - zend_ptr_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(TSRMLS_C); if (call_via_handler) { zval_ptr_dtor(&method_name); zval_ptr_dtor(¶ms_array); Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.141.2.3.2.7.2.5 diff -u -p -d -r1.141.2.3.2.7.2.5 zend_globals.h --- Zend/zend_globals.h 31 Dec 2007 07:17:04 -0000 1.141.2.3.2.7.2.5 +++ Zend/zend_globals.h 18 Jan 2008 14:04:44 -0000 @@ -64,6 +64,7 @@ typedef struct _zend_declarables { zval ticks; } zend_declarables; +typedef struct _zend_vm_stack *zend_vm_stack; struct _zend_compiler_globals { zend_stack bp_stack; @@ -213,7 +214,7 @@ struct _zend_executor_globals { HashTable regular_list; HashTable persistent_list; - zend_ptr_stack argument_stack; + zend_vm_stack argument_stack; int user_error_handler_error_reporting; zval *user_error_handler; Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.59.2.29.2.48.2.27 diff -u -p -d -r1.59.2.29.2.48.2.27 zend_vm_def.h --- Zend/zend_vm_def.h 11 Jan 2008 10:08:49 -0000 1.59.2.29.2.48.2.27 +++ Zend/zend_vm_def.h 18 Jan 2008 14:04:44 -0000 @@ -2028,7 +2028,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help } zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(called_scope), (void**)&ex_object, (void**)&EX(fbc)); - zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL); + EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -2038,11 +2038,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_help if (EX(function_state).function->common.arg_info) { zend_uint i=0; - zval **p; - ulong arg_count; - - p = (zval **) EG(argument_stack).top_element-2; - arg_count = (ulong)(zend_uintptr_t) *p; + zval **p = (zval**)EX(function_state).arguments; + ulong arg_count = opline->extended_value; while (arg_count>0) { zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC); @@ -2130,6 +2127,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help } EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; if (EG(This)) { if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) { @@ -2154,7 +2152,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help EG(called_scope) = current_called_scope; } - zend_ptr_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(TSRMLS_C); if (EG(exception)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -2346,7 +2344,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST if (!IS_OP1_TMP_FREE()) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); FREE_OP1_IF_VAR(); } ZEND_VM_NEXT_OPCODE(); @@ -2373,7 +2371,7 @@ ZEND_VM_HELPER(zend_send_by_var_helper, zval_copy_ctor(varptr); } Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); FREE_OP1(); /* for string offsets */ ZEND_VM_NEXT_OPCODE(); @@ -2409,7 +2407,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_RE (Z_REFCOUNT_P(varptr) == 1 && (OP1_TYPE == IS_CV || free_op1.var)))) { Z_SET_ISREF_P(varptr); Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); } else { zval *valptr; @@ -2419,7 +2417,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_RE if (!IS_OP1_TMP_FREE()) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); @@ -2440,7 +2438,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|C SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -2460,10 +2458,10 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|C ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) { zend_op *opline = EX(opline); - zval **param; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); + zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); - if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (param == NULL) { char *space; char *class_name = get_active_class_name(&space TSRMLS_CC); zend_execute_data *ptr = EX(prev_execute_data); @@ -2497,11 +2495,12 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) { zend_op *opline = EX(opline); - zval **param, *assignment_value, **var_ptr; + zval *assignment_value, **var_ptr; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); zend_free_op free_res; + zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); - if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (param == NULL) { if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; @@ -3943,15 +3942,16 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTI int i; zend_uint catch_op_num; int catched = 0; - zval **stack_zval_pp; zval restored_error_reporting; + + void **stack_frame = (void**)execute_data + + (sizeof(zend_execute_data) + + sizeof(zval**) * EX(op_array)->last_var + + sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); - stack_zval_pp = (zval **) EG(argument_stack).top_element - 1; - while (*stack_zval_pp != NULL) { - zval_ptr_dtor(stack_zval_pp); - EG(argument_stack).top_element--; - EG(argument_stack).top--; - stack_zval_pp--; + while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { + zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); + zval_ptr_dtor(&stack_zval_p); } for (i=0; ilast_try_catch; i++) { Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.62.2.30.2.49.2.28 diff -u -p -d -r1.62.2.30.2.49.2.28 zend_vm_execute.h --- Zend/zend_vm_execute.h 11 Jan 2008 10:08:49 -0000 1.62.2.30.2.49.2.28 +++ Zend/zend_vm_execute.h 18 Jan 2008 14:04:44 -0000 @@ -30,10 +30,13 @@ static opcode_handler_t zend_vm_get_opco #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC +#undef EX +#define EX(element) execute_data->element + ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) { - zend_execute_data execute_data; + zend_execute_data *execute_data; if (EG(exception)) { @@ -41,23 +44,23 @@ ZEND_API void execute(zend_op_array *op_ } /* Initialize execute_data */ + execute_data = (zend_execute_data *)zend_vm_stack_alloc( + sizeof(zend_execute_data) + + sizeof(zval**) * op_array->last_var + + sizeof(temp_variable) * op_array->T TSRMLS_CC); + + EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); + memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; - if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var < TEMP_VAR_STACK_LIMIT)) { - EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap)); - } else { - SET_ALLOCA_FLAG(EX(use_heap)); - EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable), op_array->T, sizeof(zval**) * op_array->last_var); - } - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); EX(symbol_table) = EG(active_symbol_table); EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = &execute_data; + EG(current_execute_data) = execute_data; EG(in_execution) = 1; if (op_array->start_op) { @@ -76,6 +79,7 @@ ZEND_API void execute(zend_op_array *op_ EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array; + EX(function_state).arguments = NULL; while (1) { #ifdef ZEND_WIN32 @@ -84,7 +88,7 @@ ZEND_API void execute(zend_op_array *op_ } #endif - if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) { + if (EX(opline)->handler(execute_data TSRMLS_CC) > 0) { return; } @@ -92,9 +96,6 @@ ZEND_API void execute(zend_op_array *op_ zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } -#undef EX -#define EX(element) execute_data->element - static int ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if DEBUG_ZEND>=2 @@ -165,7 +166,7 @@ static int zend_do_fcall_common_helper_S } zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(called_scope), (void**)&ex_object, (void**)&EX(fbc)); - zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL); + EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -175,11 +176,8 @@ static int zend_do_fcall_common_helper_S if (EX(function_state).function->common.arg_info) { zend_uint i=0; - zval **p; - ulong arg_count; - - p = (zval **) EG(argument_stack).top_element-2; - arg_count = (ulong)(zend_uintptr_t) *p; + zval **p = (zval**)EX(function_state).arguments; + ulong arg_count = opline->extended_value; while (arg_count>0) { zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC); @@ -267,6 +265,7 @@ static int zend_do_fcall_common_helper_S } EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; if (EG(This)) { if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) { @@ -291,7 +290,7 @@ static int zend_do_fcall_common_helper_S EG(called_scope) = current_called_scope; } - zend_ptr_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(TSRMLS_C); if (EG(exception)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -340,10 +339,10 @@ static int ZEND_CATCH_SPEC_HANDLER(ZEND_ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval **param; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); + zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); - if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (param == NULL) { char *space; char *class_name = get_active_class_name(&space TSRMLS_CC); zend_execute_data *ptr = EX(prev_execute_data); @@ -519,15 +518,16 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HA int i; zend_uint catch_op_num; int catched = 0; - zval **stack_zval_pp; zval restored_error_reporting; - stack_zval_pp = (zval **) EG(argument_stack).top_element - 1; - while (*stack_zval_pp != NULL) { - zval_ptr_dtor(stack_zval_pp); - EG(argument_stack).top_element--; - EG(argument_stack).top--; - stack_zval_pp--; + void **stack_frame = (void**)execute_data + + (sizeof(zend_execute_data) + + sizeof(zval**) * EX(op_array)->last_var + + sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); + + while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { + zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); + zval_ptr_dtor(&stack_zval_p); } for (i=0; ilast_try_catch; i++) { @@ -715,11 +715,12 @@ static int ZEND_INIT_NS_FCALL_BY_NAME_SP static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval **param, *assignment_value, **var_ptr; + zval *assignment_value, **var_ptr; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); zend_free_op free_res; + zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); - if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (param == NULL) { if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) { zval *default_value; @@ -1521,7 +1522,7 @@ static int ZEND_SEND_VAL_SPEC_CONST_HAND if (!0) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); @@ -4618,7 +4619,7 @@ static int ZEND_SEND_VAL_SPEC_TMP_HANDLE if (!1) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); @@ -7690,7 +7691,7 @@ static int ZEND_SEND_VAL_SPEC_VAR_HANDLE if (!0) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } ZEND_VM_NEXT_OPCODE(); @@ -7717,7 +7718,7 @@ static int zend_send_by_var_helper_SPEC_ zval_copy_ctor(varptr); } Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* for string offsets */ ZEND_VM_NEXT_OPCODE(); @@ -7753,7 +7754,7 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_VAR (Z_REFCOUNT_P(varptr) == 1 && (IS_VAR == IS_CV || free_op1.var)))) { Z_SET_ISREF_P(varptr); Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); } else { zval *valptr; @@ -7763,7 +7764,7 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_VAR if (!0) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -7784,7 +7785,7 @@ static int ZEND_SEND_REF_SPEC_VAR_HANDLE SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -20885,7 +20886,7 @@ static int ZEND_SEND_VAL_SPEC_CV_HANDLER if (!0) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); @@ -20912,7 +20913,7 @@ static int zend_send_by_var_helper_SPEC_ zval_copy_ctor(varptr); } Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); ; /* for string offsets */ ZEND_VM_NEXT_OPCODE(); @@ -20948,7 +20949,7 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_CV_ (Z_REFCOUNT_P(varptr) == 1 && (IS_CV == IS_CV || free_op1.var)))) { Z_SET_ISREF_P(varptr); Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); } else { zval *valptr; @@ -20958,7 +20959,7 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_CV_ if (!0) { zval_copy_ctor(valptr); } - zend_ptr_stack_push(&EG(argument_stack), valptr); + zend_vm_stack_push(valptr TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); @@ -20979,7 +20980,7 @@ static int ZEND_SEND_REF_SPEC_CV_HANDLER SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); - zend_ptr_stack_push(&EG(argument_stack), varptr); + zend_vm_stack_push(varptr TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } Index: Zend/zend_vm_execute.skl =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v retrieving revision 1.2.2.2.2.1.2.5 diff -u -p -d -r1.2.2.2.2.1.2.5 zend_vm_execute.skl --- Zend/zend_vm_execute.skl 23 Nov 2007 15:03:03 -0000 1.2.2.2.2.1.2.5 +++ Zend/zend_vm_execute.skl 18 Jan 2008 14:04:44 -0000 @@ -2,7 +2,7 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) { - zend_execute_data execute_data; + zend_execute_data *execute_data; {%HELPER_VARS%} {%INTERNAL_LABELS%} @@ -12,23 +12,23 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_ } /* Initialize execute_data */ + execute_data = (zend_execute_data *)zend_vm_stack_alloc( + sizeof(zend_execute_data) + + sizeof(zval**) * op_array->last_var + + sizeof(temp_variable) * op_array->T TSRMLS_CC); + + EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); + memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; - if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var < TEMP_VAR_STACK_LIMIT)) { - EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap)); - } else { - SET_ALLOCA_FLAG(EX(use_heap)); - EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable), op_array->T, sizeof(zval**) * op_array->last_var); - } - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); EX(symbol_table) = EG(active_symbol_table); EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = &execute_data; + EG(current_execute_data) = execute_data; EG(in_execution) = 1; if (op_array->start_op) { @@ -47,6 +47,7 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_ EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array; + EX(function_state).arguments = NULL; while (1) { {%ZEND_VM_CONTINUE_LABEL%} Index: Zend/zend_vm_gen.php =================================================================== RCS file: /repository/ZendEngine2/zend_vm_gen.php,v retrieving revision 1.12.2.5.2.4.2.1 diff -u -p -d -r1.12.2.5.2.4.2.1 zend_vm_gen.php --- Zend/zend_vm_gen.php 31 Dec 2007 07:24:44 -0000 1.12.2.5.2.4.2.1 +++ Zend/zend_vm_gen.php 18 Jan 2008 14:04:44 -0000 @@ -404,7 +404,7 @@ function gen_code($f, $spec, $kind, $cod "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/me", ), array( - "&execute_data", + "execute_data", "goto \\1".($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_LABEL", "'goto '.helper_name('\\1',$spec,'$op1','$op2')", "'\\2 = \\3; goto '.helper_name('\\1',$spec,'$op1','$op2').';'", @@ -420,7 +420,7 @@ function gen_code($f, $spec, $kind, $cod "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/me", ), array( - "&execute_data", + "execute_data", "goto \\1".($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER", "'goto '.helper_name('\\1',$spec,'$op1','$op2')", "'\\2 = \\3; goto '.helper_name('\\1',$spec,'$op1','$op2').';'", @@ -801,20 +801,26 @@ function gen_executor($f, $skl, $spec, $ out($f,"#define ZEND_VM_RETURN() return 1\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); + out($f,"#undef EX\n"); + out($f,"#define EX(element) execute_data->element\n\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL &execute_data TSRMLS_CC\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); + out($f,"#undef EX\n"); + out($f,"#define EX(element) execute_data->element\n\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(EX(opline)->handler)\n"); out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL &execute_data TSRMLS_CC\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); + out($f,"#undef EX\n"); + out($f,"#define EX(element) execute_data->element\n\n"); break; } break; @@ -862,7 +868,7 @@ function gen_executor($f, $skl, $spec, $ // Emit code that dispatches to opcode handler switch ($kind) { case ZEND_VM_KIND_CALL: - out($f, $m[1]."if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0)".$m[3]."\n"); + out($f, $m[1]."if (EX(opline)->handler(execute_data TSRMLS_CC) > 0)".$m[3]."\n"); break; case ZEND_VM_KIND_SWITCH: out($f, $m[1]."dispatch_handler = EX(opline)->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n"); @@ -886,9 +892,7 @@ function gen_executor($f, $skl, $spec, $ // Unspecialized executor with CALL threading is the same as the // old one, so we don't need to produce code twitch if (!$old || ZEND_VM_SPEC || (ZEND_VM_KIND != ZEND_VM_KIND_CALL)) { - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); - // Emit executor code + // Emit executor code gen_executor_code($f, $spec, $kind, $m[1]); } } Index: Zend/tests/bug41209.phpt =================================================================== RCS file: /repository/ZendEngine2/tests/bug41209.phpt,v retrieving revision 1.1.2.2 diff -u -p -d -r1.1.2.2 bug41209.phpt --- Zend/tests/bug41209.phpt 27 Apr 2007 08:12:24 -0000 1.1.2.2 +++ Zend/tests/bug41209.phpt 18 Jan 2008 14:04:44 -0000 @@ -41,6 +41,6 @@ echo "Done\n"; --EXPECTF-- Fatal error: Uncaught exception 'ErrorException' with message 'Undefined variable: id' in %s:%d Stack trace: -#0 %s(%d): env::errorHandler() +#0 %s(%d): env::errorHandler(8, '%s', '%s', 34, Array) #1 {main} thrown in %s on line %d --------------000306080100090102040203--