Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:38146 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 79437 invoked from network); 10 Jun 2008 17:53:17 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Jun 2008 17:53:16 -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 Windows 2000 SP4, XP SP1 Received: from [212.25.124.162] ([212.25.124.162:65473] helo=mx1.zend.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 4E/8E-15621-B8FBE484 for ; Tue, 10 Jun 2008 13:53:16 -0400 Received: from ws.home ([10.1.1.1]) by mx1.zend.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 10 Jun 2008 20:53:14 +0300 Message-ID: <484EBF85.10800@zend.com> Date: Tue, 10 Jun 2008 21:53:09 +0400 User-Agent: Thunderbird 2.0.0.14 (X11/20080501) MIME-Version: 1.0 To: Marcus Boerger CC: PHP Internals List , Andi Gutmans , Stanislav Malyshev References: <484E617D.6080508@zend.com> <341522076.20080610193850@marcus-boerger.de> In-Reply-To: <341522076.20080610193850@marcus-boerger.de> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 10 Jun 2008 17:53:15.0143 (UTC) FILETIME=[DB778970:01C8CB22] Subject: Re: [PHP-DEV] [PATCH] Executor improvements From: dmitry@zend.com (Dmitry Stogov) I will do it before commit. Didn't have time to check Windows version yet. Thanks. Dmitry. Marcus Boerger wrote: > Hello Dmitry, > > Tuesday, June 10, 2008, 1:11:57 PM, you wrote: > >> Index: Zend/zend.h >> =================================================================== >> RCS file: /repository/ZendEngine2/zend.h,v >> retrieving revision 1.293.2.11.2.9.2.20 >> diff -u -p -d -r1.293.2.11.2.9.2.20 zend.h >> --- Zend/zend.h 18 Mar 2008 21:14:27 -0000 1.293.2.11.2.9.2.20 >> +++ Zend/zend.h 10 Jun 2008 10:53:48 -0000 >> @@ -176,6 +176,12 @@ char *alloca (); >> # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) >> #endif >> >> +#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3400 && defined(__i386__) >> +# define ZEND_FASTCALL __attribute__((fastcall)) >> +#else >> +# define ZEND_FASTCALL >> +#endif > > Is this like __fastcall under windows? If so, please add it when _MSC_VER > is defined. > >> + >> #if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && >> !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && >> defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN) >> # define ZEND_ALLOCA_MAX_SIZE (32 * 1024) >> # define ALLOCA_FLAG(name) \ >> Index: Zend/zend_compile.h >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_compile.h,v >> retrieving revision 1.316.2.8.2.12.2.24 >> diff -u -p -d -r1.316.2.8.2.12.2.24 zend_compile.h >> --- Zend/zend_compile.h 12 May 2008 09:09:05 -0000 1.316.2.8.2.12.2.24 >> +++ Zend/zend_compile.h 10 Jun 2008 10:53:48 -0000 >> @@ -73,7 +73,8 @@ typedef struct _zend_execute_data zend_e >> #define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data TSRMLS_DC >> #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data TSRMLS_CC >> >> -typedef int (*opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); >> +typedef int (*user_opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); >> +typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); >> >> extern ZEND_API opcode_handler_t *zend_opcode_handlers; >> >> @@ -309,10 +310,16 @@ struct _zend_execute_data { >> zval *object; >> union _temp_variable *Ts; >> zval ***CVs; >> - zend_bool original_in_execution; >> HashTable *symbol_table; >> struct _zend_execute_data *prev_execute_data; >> zval *old_error_reporting; >> + zend_bool nested; >> + zval **original_return_value; >> + zend_class_entry *current_scope; >> + zend_class_entry *current_called_scope; >> + zval *current_this; >> + zval *current_object; >> + struct _zend_op *call_opline; >> }; >> >> #define EX(element) execute_data.element >> Index: Zend/zend_execute.c >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_execute.c,v >> retrieving revision 1.716.2.12.2.24.2.29 >> diff -u -p -d -r1.716.2.12.2.24.2.29 zend_execute.c >> --- Zend/zend_execute.c 9 May 2008 09:23:03 -0000 1.716.2.12.2.24.2.29 >> +++ Zend/zend_execute.c 10 Jun 2008 10:53:48 -0000 >> @@ -1314,29 +1314,9 @@ ZEND_API void execute_internal(zend_exec >> #define ZEND_VM_INC_OPCODE() \ >> EX(opline)++ >> >> -#define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() do { \ >> - EG(in_execution) = EX(original_in_execution); \ >> - EG(current_execute_data) = EX(prev_execute_data); \ >> - EG(opline_ptr) = NULL; \ >> - if (!EG(active_symbol_table)) { \ >> - int n = EX(op_array)->last_var; \ >> - while (n > 0) { \ >> - --n; \ >> - if (EX(CVs)[n]) { \ >> - zval_ptr_dtor(EX(CVs)[n]); \ >> - } \ >> - } \ >> - } \ >> - zend_vm_stack_free(execute_data TSRMLS_CC); \ >> - } while (0); >> - >> -#define ZEND_VM_RETURN_FROM_EXECUTE_LOOP() \ >> - ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ >> - ZEND_VM_RETURN() >> - >> #include "zend_vm_execute.h" >> >> -ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, opcode_handler_t handler) >> +ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler) >> { >> if (opcode != ZEND_USER_OPCODE) { >> zend_user_opcodes[opcode] = ZEND_USER_OPCODE; >> @@ -1346,7 +1326,7 @@ ZEND_API int zend_set_user_opcode_handle >> return FAILURE; >> } >> >> -ZEND_API opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) >> +ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) >> { >> return zend_user_opcode_handlers[opcode]; >> } >> Index: Zend/zend_execute.h >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_execute.h,v >> retrieving revision 1.84.2.4.2.8.2.9 >> diff -u -p -d -r1.84.2.4.2.8.2.9 zend_execute.h >> --- Zend/zend_execute.h 15 Apr 2008 15:52:36 -0000 1.84.2.4.2.8.2.9 >> +++ Zend/zend_execute.h 10 Jun 2008 10:53:48 -0000 >> @@ -331,8 +331,8 @@ ZEND_API zval** zend_get_compiled_variab >> >> #define ZEND_USER_OPCODE_DISPATCH_TO 0x100 /* call original handler of returned opcode */ >> >> -ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, opcode_handler_t handler); >> -ZEND_API opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode); >> +ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler); >> +ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode); >> >> /* former zend_execute_locks.h */ >> typedef struct _zend_free_op { >> Index: Zend/zend_vm_def.h >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_vm_def.h,v >> retrieving revision 1.59.2.29.2.48.2.57 >> diff -u -p -d -r1.59.2.29.2.48.2.57 zend_vm_def.h >> --- Zend/zend_vm_def.h 3 Jun 2008 18:11:11 -0000 1.59.2.29.2.48.2.57 >> +++ Zend/zend_vm_def.h 10 Jun 2008 10:53:49 -0000 >> @@ -2073,15 +2073,116 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_B >> ZEND_VM_NEXT_OPCODE(); >> } >> >> +ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) >> +{ >> + zend_bool nested; >> + zend_op_array *op_array = EX(op_array); >> + >> + EG(current_execute_data) = EX(prev_execute_data); >> + EG(opline_ptr) = NULL; >> + if (!EG(active_symbol_table)) { >> + zval ***cv = EX(CVs); >> + zval ***end = cv + EX(op_array)->last_var; >> + while (cv != end) { >> + if (*cv) { >> + zval_ptr_dtor(*cv); >> + } >> + cv++; >> + } >> + } >> + >> + nested = EX(nested); >> + >> + zend_vm_stack_free(execute_data TSRMLS_CC); >> + >> + if (nested) { >> + execute_data = EG(current_execute_data); >> + >> + if (EX(call_opline)->opcode == ZEND_INCLUDE_OR_EVAL) { >> + >> + EX(function_state).function = (zend_function *) EX(op_array); >> + EX(function_state).arguments = NULL; >> + EX(object) = EX(current_object); >> + >> + if (RETURN_VALUE_USED(EX(call_opline))) { >> + if >> (!EX_T(EX(call_opline)->result.u.var).var.ptr) { /* there was no return statement */ >> + >> ALLOC_ZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr); >> + >> INIT_PZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr); >> + >> Z_LVAL_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = 1; >> + >> Z_TYPE_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = IS_BOOL; >> + } >> + } >> + >> + EG(opline_ptr) = &EX(opline); >> + EG(active_op_array) = EX(op_array); >> + EG(return_value_ptr_ptr) = EX(original_return_value); >> + destroy_op_array(op_array TSRMLS_CC); >> + efree(op_array); >> + if (EG(exception)) { >> + zend_throw_exception_internal(NULL TSRMLS_CC); >> + } >> + >> + EX(opline)++; >> + ZEND_VM_LEAVE(); >> + } else { >> + >> + EG(opline_ptr) = &EX(opline); >> + EG(active_op_array) = EX(op_array); >> + EG(return_value_ptr_ptr) = EX(original_return_value); >> + if (EG(active_symbol_table)) { >> + if >> (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { >> + >> zend_hash_destroy(EG(active_symbol_table)); >> + >> FREE_HASHTABLE(EG(active_symbol_table)); >> + } else { >> + /* clean before putting into the cache, since clean >> + could call dtors, which could use cached hash */ >> + >> zend_hash_clean(EG(active_symbol_table)); >> + *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); >> + } >> + } >> + EG(active_symbol_table) = EX(symbol_table); >> + >> + 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))) { >> + if (IS_CTOR_USED(EX(called_scope))) { >> + Z_DELREF_P(EG(This)); >> + } >> + if (Z_REFCOUNT_P(EG(This)) == 1) { >> + >> zend_object_store_ctor_failed(EG(This) TSRMLS_CC); >> + } >> + } >> + zval_ptr_dtor(&EG(This)); >> + } >> + EG(This) = EX(current_this); >> + EG(scope) = EX(current_scope); >> + EG(called_scope) = EX(current_called_scope); >> + >> + EX(object) = EX(current_object); >> + EX(called_scope) = DECODE_CTOR(EX(called_scope)); >> + >> + zend_vm_stack_clear_multiple(TSRMLS_C); >> + >> + if (EG(exception)) { >> + zend_throw_exception_internal(NULL TSRMLS_CC); >> + if (RETURN_VALUE_USED(EX(call_opline)) >> && EX_T(EX(call_opline)->result.u.var).var.ptr) { >> + >> zval_ptr_dtor(&EX_T(EX(call_opline)->result.u.var).var.ptr); >> + } >> + } >> + >> + EX(opline)++; >> + ZEND_VM_LEAVE(); >> + } >> + } >> + ZEND_VM_RETURN(); >> +} >> >> ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) >> { >> zend_op *opline = EX(opline); >> - zend_class_entry *current_scope; >> - zend_class_entry *current_called_scope; >> - zval *current_this; >> - zend_bool should_change_scope; >> - zval *ex_object; >> + zend_bool should_change_scope = 0; >> >> if (EX(function_state).function->common.fn_flags & >> (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) { >> if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) { >> @@ -2112,17 +2213,15 @@ ZEND_VM_HELPER(zend_do_fcall_common_help >> if (EX(function_state).function->type == ZEND_USER_FUNCTION || >> EX(function_state).function->common.scope) { >> should_change_scope = 1; >> - current_this = EG(This); >> - current_scope = EG(scope); >> - current_called_scope = EG(called_scope); >> + EX(current_this) = EG(This); >> + EX(current_scope) = EG(scope); >> + EX(current_called_scope) = EG(called_scope); >> EG(This) = EX(object); >> EG(scope) = (EX(function_state).function->type == >> ZEND_USER_FUNCTION || !EX(object)) ? >> EX(function_state).function->common.scope : NULL; >> EG(called_scope) = EX(called_scope); >> - } else { >> - should_change_scope = 0; >> } >> >> - zend_ptr_stack_3_pop(&EG(arg_types_stack), >> (void*)&EX(called_scope), (void**)&ex_object, (void**)&EX(fbc)); >> + zend_ptr_stack_3_pop(&EG(arg_types_stack), >> (void*)&EX(called_scope), (void**)&EX(current_object), (void**)&EX(fbc)); >> EX(function_state).arguments = >> zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); >> >> if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { >> @@ -2151,8 +2250,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help >> zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); >> } >> } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) { >> - zval **original_return_value = EG(return_value_ptr_ptr); >> - >> + EX(original_return_value) = EG(return_value_ptr_ptr); >> EG(active_symbol_table) = NULL; >> EG(active_op_array) = >> &EX(function_state).function->op_array; >> EG(return_value_ptr_ptr) = NULL; >> @@ -2163,11 +2261,20 @@ ZEND_VM_HELPER(zend_do_fcall_common_help >> >> EX_T(opline->result.u.var).var.fcall_returned_reference = >> EX(function_state).function->common.return_reference; >> } >> >> +#ifndef ZEND_VM_EXPORT >> + if (zend_execute == execute && !EG(exception)) { >> + EX(call_opline) = opline; >> + ZEND_VM_ENTER(); >> + } else { >> + zend_execute(EG(active_op_array) TSRMLS_CC); >> + } >> +#else >> zend_execute(EG(active_op_array) TSRMLS_CC); >> +#endif >> >> EG(opline_ptr) = &EX(opline); >> EG(active_op_array) = EX(op_array); >> - EG(return_value_ptr_ptr)=original_return_value; >> + EG(return_value_ptr_ptr) = EX(original_return_value); >> if (EG(active_symbol_table)) { >> if >> (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { >> zend_hash_destroy(EG(active_symbol_table)); >> @@ -2220,12 +2327,12 @@ ZEND_VM_HELPER(zend_do_fcall_common_help >> } >> zval_ptr_dtor(&EG(This)); >> } >> - EG(This) = current_this; >> - EG(scope) = current_scope; >> - EG(called_scope) = current_called_scope; >> + EG(This) = EX(current_this); >> + EG(scope) = EX(current_scope); >> + EG(called_scope) = EX(current_called_scope); >> } >> >> - EX(object) = ex_object; >> + EX(object) = EX(current_object); >> EX(called_scope) = DECODE_CTOR(EX(called_scope)); >> >> zend_vm_stack_clear_multiple(TSRMLS_C); >> @@ -2335,7 +2442,7 @@ ZEND_VM_C_LABEL(return_by_value): >> } >> } >> FREE_OP1_IF_VAR(); >> - ZEND_VM_RETURN_FROM_EXECUTE_LOOP(); >> + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); >> } >> >> ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) >> @@ -3030,7 +3137,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL >> { >> zend_op *opline = EX(opline); >> zend_op_array *new_op_array=NULL; >> - zval **original_return_value = EG(return_value_ptr_ptr); >> int return_value_used; >> zend_free_op free_op1; >> zval *inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R); >> @@ -3102,17 +3208,15 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL >> if (inc_filename==&tmp_inc_filename) { >> zval_dtor(&tmp_inc_filename); >> } >> + FREE_OP1(); >> EX_T(opline->result.u.var).var.ptr_ptr = >> &EX_T(opline->result.u.var).var.ptr; >> - if (new_op_array) { >> - zval *saved_object; >> - zend_function *saved_function; >> - >> + if (new_op_array && !EG(exception)) { >> + EX(original_return_value) = EG(return_value_ptr_ptr); >> EG(return_value_ptr_ptr) = return_value_used ? >> EX_T(opline->result.u.var).var.ptr_ptr : NULL; >> EG(active_op_array) = new_op_array; >> EX_T(opline->result.u.var).var.ptr = NULL; >> >> - saved_object = EX(object); >> - saved_function = EX(function_state).function; >> + EX(current_object) = EX(object); >> >> EX(function_state).function = (zend_function *) new_op_array; >> EX(object) = NULL; >> @@ -3121,10 +3225,15 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL >> zend_rebuild_symbol_table(TSRMLS_C); >> } >> >> - zend_execute(new_op_array TSRMLS_CC); >> + if (zend_execute == execute) { >> + EX(call_opline) = opline; >> + ZEND_VM_ENTER(); >> + } else { >> + zend_execute(new_op_array TSRMLS_CC); >> + } >> >> - EX(function_state).function = saved_function; >> - EX(object) = saved_object; >> + EX(function_state).function = (zend_function *) EX(op_array); >> + EX(object) = EX(current_object); >> >> if (return_value_used) { >> if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */ >> @@ -3137,6 +3246,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL >> >> EG(opline_ptr) = &EX(opline); >> EG(active_op_array) = EX(op_array); >> + EG(return_value_ptr_ptr) = EX(original_return_value); >> destroy_op_array(new_op_array TSRMLS_CC); >> efree(new_op_array); >> if (EG(exception)) { >> @@ -3150,8 +3260,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL >> Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL; >> } >> } >> - FREE_OP1(); >> - EG(return_value_ptr_ptr) = original_return_value; >> ZEND_VM_NEXT_OPCODE(); >> } >> >> @@ -3885,7 +3993,6 @@ ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP >> FREE_OP1(); >> } >> #endif >> - ZEND_VM_EXIT_FROM_EXECUTE_LOOP(); >> zend_bailout(); >> ZEND_VM_NEXT_OPCODE(); >> } >> @@ -4156,7 +4263,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTI >> EX(old_error_reporting) = NULL; >> >> if (!catched) { >> - ZEND_VM_RETURN_FROM_EXECUTE_LOOP(); >> + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); >> } else { >> ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); >> ZEND_VM_CONTINUE(); >> @@ -4177,7 +4284,7 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, A >> case ZEND_USER_OPCODE_CONTINUE: >> ZEND_VM_CONTINUE(); >> case ZEND_USER_OPCODE_RETURN: >> - ZEND_VM_RETURN_FROM_EXECUTE_LOOP(); >> + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); >> case ZEND_USER_OPCODE_DISPATCH: >> ZEND_VM_DISPATCH(EX(opline)->opcode, EX(opline)); >> default: >> Index: Zend/zend_vm_execute.skl >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v >> retrieving revision 1.2.2.2.2.1.2.8 >> diff -u -p -d -r1.2.2.2.2.1.2.8 zend_vm_execute.skl >> --- Zend/zend_vm_execute.skl 7 May 2008 12:04:39 -0000 1.2.2.2.2.1.2.8 >> +++ Zend/zend_vm_execute.skl 10 Jun 2008 10:53:49 -0000 >> @@ -3,6 +3,8 @@ >> ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) >> { >> zend_execute_data *execute_data; >> + zend_bool nested = 0; >> + zend_bool original_in_execution = EG(in_execution); >> {%HELPER_VARS%} >> >> {%INTERNAL_LABELS%} >> @@ -11,6 +13,9 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_ >> return; >> } >> >> + EG(in_execution) = 1; >> + >> +zend_vm_enter: >> /* Initialize execute_data */ >> execute_data = (zend_execute_data *)zend_vm_stack_alloc( >> sizeof(zend_execute_data) + >> @@ -25,12 +30,12 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_ >> EX(object) = NULL; >> EX(old_error_reporting) = NULL; >> 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; >> + EX(nested) = nested; >> + nested = 1; >> >> - EG(in_execution) = 1; >> if (op_array->start_op) { >> ZEND_VM_SET_OPCODE(op_array->start_op); >> } else { >> Index: Zend/zend_vm_gen.php >> =================================================================== >> RCS file: /repository/ZendEngine2/zend_vm_gen.php,v >> retrieving revision 1.12.2.5.2.4.2.2 >> diff -u -p -d -r1.12.2.5.2.4.2.2 zend_vm_gen.php >> --- Zend/zend_vm_gen.php 24 Jan 2008 09:41:39 -0000 1.12.2.5.2.4.2.2 >> +++ Zend/zend_vm_gen.php 10 Jun 2008 10:53:49 -0000 >> @@ -304,7 +304,7 @@ function helper_name($name, $spec, $op1, >> } >> >> // Generates code for opcode handler or helper >> -function gen_code($f, $spec, $kind, $code, $op1, $op2) { >> +function gen_code($f, $spec, $kind, $export, $code, $op1, $op2) { >> global $op1_type, $op2_type, $op1_get_zval_ptr, $op2_get_zval_ptr, >> $op1_get_zval_ptr_ptr, $op2_get_zval_ptr_ptr, >> $op1_get_obj_zval_ptr, $op2_get_obj_zval_ptr, >> @@ -343,7 +343,9 @@ function gen_code($f, $spec, $kind, $cod >> "/ZEND_VM_C_LABEL\(\s*([A-Za-z_]*)\s*\)/m", >> "/ZEND_VM_C_GOTO\(\s*([A-Za-z_]*)\s*\)/m", >> "/^#if\s+1\s*\\|\\|.*[^\\\\]$/m", >> - "/^#if\s+0\s*&&.*[^\\\\]$/m" >> + "/^#if\s+0\s*&&.*[^\\\\]$/m", >> + "/^#ifdef\s+ZEND_VM_EXPORT\s*\n/m", >> + "/^#ifndef\s+ZEND_VM_EXPORT\s*\n/m" >> ), >> array( >> $op1_type[$op1], >> @@ -374,6 +376,8 @@ function gen_code($f, $spec, $kind, $cod >> "goto \\1".(($spec && $kind != >> ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2]):""), >> "#if 1", >> "#if 0", >> + $export?"#if 1\n":"#if 0\n", >> + $export?"#if 0\n":"#if 1\n" >> ), >> $code); >> >> @@ -481,7 +485,7 @@ function gen_handler($f, $spec, $kind, $ >> // Generate opcode handler's entry point according to selected threading model >> switch($kind) { >> case ZEND_VM_KIND_CALL: >> - out($f,"static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); >> + out($f,"ZEND_FASTCALL static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); >> break; >> case ZEND_VM_KIND_SWITCH: >> if ($spec) { >> @@ -502,7 +506,7 @@ function gen_handler($f, $spec, $kind, $ >> } >> >> // Generate opcode handler's code >> - gen_code($f, $spec, $kind, $code, $op1, $op2); >> + gen_code($f, $spec, $kind, 0, $code, $op1, $op2); >> } >> >> // Generates helper >> @@ -518,10 +522,10 @@ function gen_helper($f, $spec, $kind, $n >> case ZEND_VM_KIND_CALL: >> if ($param == null) { >> // Helper without parameters >> - out($f, "static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(ZEND_OPCODE_HANDLER_ARGS)\n"); >> + out($f, "ZEND_FASTCALL static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(ZEND_OPCODE_HANDLER_ARGS)\n"); >> } else { >> // Helper with parameter >> - out($f, "static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(".$param.", ZEND_OPCODE_HANDLER_ARGS)\n"); >> + out($f, "ZEND_FASTCALL static int >> ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(".$param.", ZEND_OPCODE_HANDLER_ARGS)\n"); >> } >> break; >> case ZEND_VM_KIND_SWITCH: >> @@ -533,7 +537,7 @@ function gen_helper($f, $spec, $kind, $n >> } >> >> // Generate helper's code >> - gen_code($f, $spec, $kind, $code, $op1, $op2); >> + gen_code($f, $spec, $kind, 0, $code, $op1, $op2); >> } >> >> // Generates array of opcode handlers (specialized or unspecialized) >> @@ -685,10 +689,9 @@ function gen_null_handler($f) { >> // for undefined opcodes, do we emit code for it only once >> if (!$done) { >> $done = 1; >> - out($f,"static int >> ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); >> + out($f,"ZEND_FASTCALL static int >> ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); >> out($f,"{\n"); >> out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode >> %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n"); >> - out($f,"\tZEND_VM_RETURN_FROM_EXECUTE_LOOP();\n"); >> out($f,"}\n\n"); >> } >> } >> @@ -763,12 +766,10 @@ function gen_executor_code($f, $spec, $k >> case ZEND_VM_KIND_SWITCH: >> out($f,"default:\n"); >> out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid >> opcode %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n"); >> - out($f,"\tZEND_VM_RETURN_FROM_EXECUTE_LOOP();\n"); >> break; >> case ZEND_VM_KIND_GOTO: >> out($f,"ZEND_NULL_HANDLER:\n"); >> out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid >> opcode %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n"); >> - out($f,"\tZEND_VM_RETURN_FROM_EXECUTE_LOOP();\n"); >> break; >> } >> } >> @@ -790,7 +791,7 @@ function gen_executor($f, $skl, $spec, $ >> if (preg_match("/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) { >> switch ($m[2]) { >> case "DEFINES": >> - if (ZEND_VM_OLD_EXECUTOR) { >> + if (ZEND_VM_OLD_EXECUTOR && $spec) { >> out($f,"static int zend_vm_old_executor = 0;\n\n"); >> } >> out($f,"static opcode_handler_t >> zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);\n\n"); >> @@ -799,6 +800,8 @@ function gen_executor($f, $skl, $spec, $ >> out($f,"\n"); >> out($f,"#define ZEND_VM_CONTINUE() return 0\n"); >> out($f,"#define ZEND_VM_RETURN() return 1\n"); >> + out($f,"#define ZEND_VM_ENTER() return 2\n"); >> + out($f,"#define ZEND_VM_LEAVE() return 3\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"); >> @@ -807,7 +810,9 @@ function gen_executor($f, $skl, $spec, $ >> 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_RETURN() EG(in_execution) = original_in_execution; return\n"); >> + out($f,"#define >> ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\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"); >> out($f,"#define >> ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); >> out($f,"#undef EX\n"); >> @@ -816,7 +821,9 @@ function gen_executor($f, $skl, $spec, $ >> 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_RETURN() EG(in_execution) = original_in_execution; return\n"); >> + out($f,"#define >> ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\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"); >> out($f,"#define >> ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); >> out($f,"#undef EX\n"); >> @@ -857,7 +864,10 @@ function gen_executor($f, $skl, $spec, $ >> } >> break; >> case "ZEND_VM_CONTINUE_LABEL": >> - if ($kind == ZEND_VM_KIND_SWITCH) { >> + if ($kind == ZEND_VM_KIND_CALL) { >> + // Only SWITCH dispatch method use it >> + out($f,$m[1]."\tint ret;".$m[3]."\n"); >> + } else if ($kind == ZEND_VM_KIND_SWITCH) { >> // Only SWITCH dispatch method use it >> >> out($f,"zend_vm_continue:".$m[3]."\n"); >> } else { >> @@ -868,7 +878,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 ((ret = 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"); >> @@ -881,7 +891,18 @@ function gen_executor($f, $skl, $spec, $ >> case "INTERNAL_EXECUTOR": >> if ($kind == ZEND_VM_KIND_CALL) { >> // Executor is defined as a set of functions >> - out($f, $m[1]."return;".$m[3]."\n"); >> + 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]."\t\top_array = EG(active_op_array);\n". >> + $m[1]."\t\tgoto zend_vm_enter;\n". >> + $m[1]."\tcase 3:\n" . >> + >> $m[1]."\t\texecute_data = EG(current_execute_data);\n". >> + $m[1]."\tdefault:\n". >> + $m[1]."\t\tbreak;\n". >> + $m[1]."}".$m[3]."\n"); >> } else { >> // Emit executor code >> gen_executor_code($f, $spec, $kind, $m[1]); >> @@ -1102,11 +1123,11 @@ function gen_vm($def, $skel) { >> out($f, $GLOBALS['header_text']); >> >> // Support for ZEND_USER_OPCODE >> - out($f, "static opcode_handler_t zend_user_opcode_handlers[256] = {"); >> + out($f, "static user_opcode_handler_t >> zend_user_opcode_handlers[256] = {"); >> for ($i = 0; $i < 255; ++$i) { >> - out($f, "(opcode_handler_t)NULL,"); >> + out($f, "(user_opcode_handler_t)NULL,"); >> } >> - out($f, "(opcode_handler_t)NULL};\n\n"); >> + out($f, "(user_opcode_handler_t)NULL};\n\n"); >> >> out($f, "static zend_uchar zend_user_opcodes[256] = {"); >> for ($i = 0; $i < 255; ++$i) { >> @@ -1124,6 +1145,8 @@ function gen_vm($def, $skel) { >> out($f,"#define EX(element) execute_data.element\n\n"); >> out($f,"#undef ZEND_VM_CONTINUE\n\n"); >> out($f,"#undef ZEND_VM_RETURN\n\n"); >> + out($f,"#undef ZEND_VM_ENTER\n\n"); >> + out($f,"#undef ZEND_VM_LEAVE\n\n"); >> out($f,"#undef ZEND_VM_DISPATCH\n\n"); >> out($f,"#undef >> ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n"); >> gen_executor($f, $skl, 0, ZEND_VM_KIND_CALL, >> "old_execute", "zend_vm_use_old_executor", 1); >> @@ -1180,10 +1203,14 @@ function gen_vm($def, $skel) { >> out($f,"#define EX(element) execute_data->element\n\n"); >> out($f,"#undef ZEND_VM_CONTINUE\n"); >> out($f,"#undef ZEND_VM_RETURN\n"); >> + out($f,"#undef ZEND_VM_ENTER\n"); >> + out($f,"#undef ZEND_VM_LEAVE\n"); >> out($f,"#undef ZEND_VM_DISPATCH\n"); >> out($f,"#undef >> ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n"); >> out($f,"#define ZEND_VM_CONTINUE() return 0\n"); >> out($f,"#define ZEND_VM_RETURN() return 1\n"); >> + out($f,"#define ZEND_VM_ENTER() return 2\n"); >> + out($f,"#define ZEND_VM_LEAVE() return 3\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\n"); >> } >> @@ -1227,7 +1254,7 @@ function gen_vm($def, $skel) { >> } >> } >> if (!$done) { >> - gen_code($f, 0, ZEND_VM_KIND_CALL, $code, 'ANY', 'ANY'); >> + gen_code($f, 0, ZEND_VM_KIND_CALL, 1, $code, 'ANY', 'ANY'); >> } >> } >> > > > > > Best regards, > Marcus >