Re: [PATCH] Executor improvements
| From: | Dmitry Stogov | Date: | Tue, 10 Jun 2008 17:53:09 +0000 |
| Subject: | Re: [PATCH] Executor improvements | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-38146@lists.php.net to get a copy of this message | ||
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.hIs this like __fastcall under windows? If so, please add it when _MSC_VER is defined.--- 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+ #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.hBest regards, Marcus--- 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_handlereturn 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_BZEND_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_helpif (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_helpzval_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_helpEX_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); + }+#elsezend_execute(EG(active_op_array) TSRMLS_CC);+#endifEG(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_EVALif (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_EVALzend_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_EVALEG(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_EVALZ_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|TMPFREE_OP1(); }#endif- ZEND_VM_EXIT_FROM_EXECUTE_LOOP(); zend_bailout(); ZEND_VM_NEXT_OPCODE();} @@ -4156,7 +4263,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTIEX(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, Acase 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, $ncase 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 intZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");+ out($f,"ZEND_FASTCALL static intZEND_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, $kcase ZEND_VM_KIND_SWITCH: out($f,"default:\n"); out($f,"\tzend_error_noreturn(E_ERROR, \"Invalidopcode %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, \"Invalidopcode %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_tzend_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,"#defineZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");out($f,"#defineZEND_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,"#defineZEND_VM_CONTINUE() goto zend_vm_continue\n");- out($f,"#define ZEND_VM_RETURN() return\n"); + out($f,"#defineZEND_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,"#defineZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n");out($f,"#defineZEND_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,"#defineZEND_VM_CONTINUE() goto *(void**)(EX(opline)->handler)\n");- out($f,"#define ZEND_VM_RETURN() return\n"); + out($f,"#defineZEND_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,"#defineZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n");out($f,"#defineZEND_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_tzend_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,"#undefZEND_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,"#undefZEND_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) returnzend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");out($f,"#defineZEND_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'); } }