From: Dmitry Stogov Date: Wed, 20 Apr 2016 08:06:52 +0000 (+0300) Subject: Reduced amount of code generated for interrupt handling. X-Git-Tag: php-7.1.0alpha1~291 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f4848014837f8c1d577cc5b0d5d29f658b42369f;p=php Reduced amount of code generated for interrupt handling. Improved ZEND_VM_INTERRUPT_CHECK() placement (always perform checks after opcode handler completion, when instruction pointer value is alredy changed to the next opcode). --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f14434bff9..6ba72b324e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2101,9 +2101,15 @@ void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ /* }}} */ #ifdef ZEND_WIN32 +static zend_never_inline ZEND_COLD ZEND_NORETURN void ZEND_FASTCALL zend_interrupt(void) /* {{{ */ +{ + zend_timeout(0); +} +/* }}} */ + # define ZEND_VM_INTERRUPT_CHECK() do { \ - if (EG(timed_out)) { \ - zend_timeout(0); \ + if (UNEXPECTED(EG(timed_out))) { \ + zend_interrupt(); \ } \ } while (0) #else @@ -2198,7 +2204,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu EX_LOAD_LITERALS(op_array); EG(current_execute_data) = execute_data; - ZEND_VM_INTERRUPT_CHECK(); } /* }}} */ @@ -2235,7 +2240,6 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu EX_LOAD_LITERALS(op_array); EG(current_execute_data) = execute_data; - ZEND_VM_INTERRUPT_CHECK(); } /* }}} */ @@ -2326,7 +2330,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da EX_LOAD_LITERALS(op_array); EG(current_execute_data) = execute_data; - ZEND_VM_INTERRUPT_CHECK(); } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2b91605207..49d6b20516 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3577,8 +3577,8 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL)) @@ -3694,8 +3694,8 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) } HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) @@ -3854,8 +3854,8 @@ ZEND_VM_C_LABEL(fcall_end): HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) @@ -5405,8 +5405,8 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET) @@ -7078,8 +7078,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; int in_finally = 0; - ZEND_VM_INTERRUPT_CHECK(); - { const zend_op *exc_opline = EG(opline_before_exception); if ((exc_opline->opcode == ZEND_FREE || exc_opline->opcode == ZEND_FE_FREE) @@ -7539,10 +7537,10 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH, FAST_RET) if (fast_call->u2.lineno != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; - ZEND_VM_SET_OPCODE(fast_ret + 1); if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; } + ZEND_VM_SET_OPCODE(fast_ret + 1); ZEND_VM_CONTINUE(); } else { /* special case for unhandled exceptions */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3b2540d585..99e2333644 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -387,7 +387,7 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H #define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE() #define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE() #if defined(ZEND_VM_FP_GLOBAL_REG) -# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE() +# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() # define ZEND_VM_LEAVE() ZEND_VM_CONTINUE() #elif defined(ZEND_VM_IP_GLOBAL_REG) # define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; return 1 @@ -415,6 +415,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) LOAD_OPLINE(); + ZEND_VM_INTERRUPT_CHECK(); while (1) { #if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG) @@ -435,6 +436,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) #else if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); + ZEND_VM_INTERRUPT_CHECK(); } else { # ifdef ZEND_VM_IP_GLOBAL_REG opline = orig_opline; @@ -638,8 +640,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -685,8 +687,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -826,8 +828,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -919,8 +921,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1079,8 +1081,8 @@ fcall_end: HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1239,8 +1241,8 @@ fcall_end: HANDLE_EXCEPTION(); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1725,8 +1727,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; int in_finally = 0; - ZEND_VM_INTERRUPT_CHECK(); - { const zend_op *exc_opline = EG(opline_before_exception); if ((exc_opline->opcode == ZEND_FREE || exc_opline->opcode == ZEND_FE_FREE) @@ -1876,10 +1876,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC if (fast_call->u2.lineno != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; - ZEND_VM_SET_OPCODE(fast_ret + 1); if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; } + ZEND_VM_SET_OPCODE(fast_ret + 1); ZEND_VM_CONTINUE(); } else { /* special case for unhandled exceptions */ @@ -3457,8 +3457,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -35529,8 +35529,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -50276,8 +50276,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } - ZEND_VM_INTERRUPT_CHECK(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index ff877df76e..50c9178bc4 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -9,6 +9,7 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex) {%INTERNAL_LABELS%} LOAD_OPLINE(); + ZEND_VM_INTERRUPT_CHECK(); while (1) { {%ZEND_VM_CONTINUE_LABEL%} diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 4407d7dfe3..1f4bb884d2 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1575,7 +1575,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG)\n"); - out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n"); out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; return 1\n"); @@ -1611,7 +1611,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() return\n"); - out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n"); out($f,"\n"); @@ -1645,7 +1645,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); out($f,"#define ZEND_VM_RETURN() return\n"); - out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n"); out($f,"\n"); @@ -1747,6 +1747,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) "#else\n" . $m[1]."if (EXPECTED(ret > 0)) {\n" . $m[1]."\texecute_data = EG(current_execute_data);\n". + $m[1]."\tZEND_VM_INTERRUPT_CHECK();\n". $m[1]."} else {\n" . "# ifdef ZEND_VM_IP_GLOBAL_REG\n" . $m[1]."\topline = orig_opline;\n" .