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 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php