]> granicus.if.org Git - php/commitdiff
Reduced amount of code generated for interrupt handling.
authorDmitry Stogov <dmitry@zend.com>
Wed, 20 Apr 2016 08:06:52 +0000 (11:06 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 20 Apr 2016 08:06:52 +0000 (11:06 +0300)
Improved ZEND_VM_INTERRUPT_CHECK() placement (always perform checks after opcode handler completion, when instruction pointer value is alredy changed to the next opcode).

Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
Zend/zend_vm_gen.php

index f14434bff92b01e09ff434605ada553614a04b8c..6ba72b324e6ad3ccb228469c7d4abe65c38f9ea4 100644 (file)
@@ -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();
 }
 /* }}} */
 
index 2b9160520778951e83c3d380c680966433cb29f1..49d6b205162258c8b9f0c52d8973de517ff917ef 100644 (file)
@@ -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 */
index 3b2540d5850b80d7a0d20e0e4e1ea775585a81f8..99e2333644ca80bca4408df7a9a44fe3a8e5df31 100644 (file)
@@ -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)
index ff877df76ea150a957769740c5b6e51059a9746a..50c9178bc40f7c2d6d61e5c662ade8b8d9ef06e8 100644 (file)
@@ -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%}
index 4407d7dfe31e9deb7cb40b833758643e9d83dd7d..1f4bb884d274bc5bdd317fe79175ed5ce104b170 100644 (file)
@@ -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" .