@@ -1594,6 +1594,19 @@ function gen_halt_handler($f, $kind) {
15941594 out ($ f ,"} \n\n" );
15951595}
15961596
1597+ function gen_interrupt_func ($ f , $ kind , $ spec ) {
1598+ $ cconv = $ kind === ZEND_VM_KIND_TAILCALL ? 'ZEND_OPCODE_HANDLER_CCONV ' : 'ZEND_OPCODE_HANDLER_FUNC_CCONV ' ;
1599+ $ variant = $ kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL ' : '' ;
1600+ out ($ f , "static ZEND_COLD zend_never_inline ZEND_OPCODE_HANDLER_RET {$ cconv } zend_interrupt {$ variant }(ZEND_OPCODE_HANDLER_ARGS) { \n" );
1601+ out ($ f ,"\tSAVE_OPLINE(); \n" );
1602+ if ($ kind === ZEND_VM_KIND_TAILCALL ) {
1603+ out ($ f ,"\tZEND_VM_TAIL_CALL(zend_interrupt_helper " .($ spec ?"_SPEC " :"" )."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); \n" );
1604+ } else {
1605+ out ($ f , "\treturn &call_interrupt_op; \n" );
1606+ }
1607+ out ($ f , "} \n" );
1608+ }
1609+
15971610function extra_spec_name ($ extra_spec ) {
15981611 global $ prefix ;
15991612
@@ -1804,10 +1817,14 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
18041817 switch ($ kind ) {
18051818 case ZEND_VM_KIND_CALL :
18061819 gen_null_handler ($ f , $ kind );
1820+ out ($ f , "#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL \n" );
1821+ gen_interrupt_func ($ f , $ kind , $ spec );
1822+ out ($ f , "#endif \n" );
18071823 break ;
18081824 case ZEND_VM_KIND_TAILCALL :
18091825 gen_null_handler ($ f , $ kind );
18101826 gen_halt_handler ($ f , $ kind );
1827+ gen_interrupt_func ($ f , $ kind , $ spec );
18111828 break ;
18121829 case ZEND_VM_KIND_SWITCH :
18131830 out ($ f ,"default: ZEND_NULL_LABEL: \n" );
@@ -1845,7 +1862,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
18451862 out ($ f , "#pragma push_macro( \"ZEND_VM_INTERRUPT \") \n" );
18461863 out ($ f , "#undef ZEND_VM_INTERRUPT \n" );
18471864 out ($ f , "#define ZEND_VM_CONTINUE(handler) return opline \n" );
1848- out ($ f , "#define ZEND_VM_INTERRUPT() return zend_interrupt_helper " .( $ spec ? " _SPEC " : "" ). " (ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) \n" );
1865+ out ($ f , "#define ZEND_VM_INTERRUPT() return zend_interrupt (ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) \n" );
18491866 out ($ f , $ delayed_helpers );
18501867 out ($ f , "#pragma pop_macro( \"ZEND_VM_INTERRUPT \") \n" );
18511868 out ($ f , "#pragma pop_macro( \"ZEND_VM_CONTINUE \") \n" );
@@ -1900,7 +1917,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19001917 if ($ kind == ZEND_VM_KIND_HYBRID || $ kind == ZEND_VM_KIND_CALL ) {
19011918 out ($ f ,"#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL \n\n" );
19021919 out ($ f ,"static zend_vm_opcode_handler_func_t const * zend_opcode_handler_funcs; \n" );
1903- out ($ f ,"#endif \n" );
1920+ out ($ f ,"#endif \n\n" );
1921+ out ($ f ,"#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL \n" );
1922+ out ($ f ,"static const zend_op call_interrupt_op; \n" );
1923+ out ($ f ,"#endif \n\n" );
19041924 }
19051925 out ($ f ,"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC \n" );
19061926 out ($ f ,"static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op); \n" );
@@ -2139,9 +2159,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21392159 out ($ f ," ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); \\\n" );
21402160 out ($ f ," } while (0) \n" );
21412161 out ($ f ,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE() \n" );
2142- out ($ f ,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper " .( $ spec ? " _SPEC " : "" ). " _TAILCALL (ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) \n" );
2162+ out ($ f ,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_TAILCALL (ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) \n" );
21432163 out ($ f ,"\n" );
21442164 out ($ f ,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper " .($ spec ?"_SPEC " :"" )."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS); \n" );
2165+ out ($ f ,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt(ZEND_OPCODE_HANDLER_ARGS); \n" );
2166+ out ($ f ,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_TAILCALL(ZEND_OPCODE_HANDLER_ARGS); \n" );
21452167 out ($ f ,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); \n" );
21462168 out ($ f ,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HALT_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); \n" );
21472169 out ($ f ,"static zend_never_inline const zend_op *ZEND_OPCODE_HANDLER_CCONV zend_leave_helper_SPEC_TAILCALL(zend_execute_data *ex, const zend_op *opline); \n" );
@@ -2152,6 +2174,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21522174 out ($ f ,"static const zend_op call_leave_op = { \n" );
21532175 out ($ f ," .handler = zend_leave_helper_SPEC_TAILCALL, \n" );
21542176 out ($ f ,"}; \n" );
2177+ out ($ f ,"static const zend_op call_interrupt_op = { \n" );
2178+ out ($ f ," .handler = zend_interrupt_helper_SPEC_TAILCALL, \n" );
2179+ out ($ f ,"}; \n" );
21552180 out ($ f ,"\n" );
21562181
21572182 gen_executor_code ($ f , $ spec , ZEND_VM_KIND_TAILCALL , $ m [1 ]);
0 commit comments