From: Dmitry Stogov Date: Mon, 6 Apr 2020 20:48:20 +0000 (+0300) Subject: Save CPU regesters on side exit for deoptimization X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4006c0008e2b9646540a427b830dd46c11458786;p=php Save CPU regesters on side exit for deoptimization --- diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 76acfc29de..b5c4ca82d7 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -33,6 +33,7 @@ #include "Optimizer/zend_call_graph.h" #include "Optimizer/zend_dump.h" +#include "jit/zend_jit_x86.h" #include "jit/zend_jit_internal.h" #ifdef ZTS @@ -165,7 +166,6 @@ static zend_bool zend_long_is_power_of_two(zend_long x) #define OP1_DATA_RANGE_EX() OP_RANGE_EX(ssa_op + 1, op1) #include "dynasm/dasm_x86.h" -#include "jit/zend_jit_x86.h" #include "jit/zend_jit_helpers.c" #include "jit/zend_jit_disasm_x86.c" #ifndef _WIN32 diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 60f9520d0b..54eaca15c6 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -422,7 +422,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HAND ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS); int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline); -int ZEND_FASTCALL zend_jit_trace_exit(uint32_t trace_num, uint32_t exit_num); +int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs); zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *execute_data, const zend_op *opline, zend_jit_trace_rec *trace_buffer, uint8_t start); static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit_trace_rec *trace, const zend_op *opline, zend_bool *exit_if_true) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index d2fe33b63f..f24ae1c2a1 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3879,8 +3879,9 @@ blacklist: return (stop == ZEND_JIT_TRACE_STOP_HALT) ? -1 : 0; } -int ZEND_FASTCALL zend_jit_trace_exit(uint32_t trace_num, uint32_t exit_num) +int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs) { + uint32_t trace_num = (uint32_t)(uintptr_t)EG(reserved)[zend_func_info_rid]; zend_execute_data *execute_data = EG(current_execute_data); const zend_op *opline; zend_jit_trace_info *t = &zend_jit_traces[trace_num]; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 906cba3458..450fa6055d 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -28,6 +28,7 @@ #include "Optimizer/zend_func_info.h" #include "Optimizer/zend_call_graph.h" #include "zend_jit.h" +#include "zend_jit_x86.h" #include "zend_jit_internal.h" #ifdef HAVE_GCC_GLOBAL_REGS diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 2306c7a392..b5c71f2cbb 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -2326,16 +2326,62 @@ static int zend_jit_trace_exit_stub(dasm_State **Dst) { |->trace_exit: | - | // TODO: Save CPU registers ??? + | // Save CPU registers + |.if X64 + | sub r4, 16*8+16*8-8 /* CPU regs + SSE regs */ + | mov aword [r4+11*8], r11 + | mov aword [r4+10*8], r10 + | mov aword [r4+9*8], r9 + | mov aword [r4+8*8], r8 + | mov aword [r4+7*8], rdi + | mov aword [r4+6*8], rsi + | mov aword [r4+2*8], rdx + | mov aword [r4+1*8], rcx + | mov aword [r4+0*8], rax + | mov FCARG1a, aword [r4+16*8+16*8-8] // exit_num = POP + | mov FCARG2a, r4 + | movsd qword [r4+16*8+15*8], xmm15 + | movsd qword [r4+16*8+14*8], xmm14 + | movsd qword [r4+16*8+13*8], xmm13 + | movsd qword [r4+16*8+12*8], xmm12 + | movsd qword [r4+16*8+11*8], xmm11 + | movsd qword [r4+16*8+10*8], xmm10 + | movsd qword [r4+16*8+9*8], xmm9 + | movsd qword [r4+16*8+8*8], xmm8 + | movsd qword [r4+16*8+7*8], xmm7 + | movsd qword [r4+16*8+6*8], xmm6 + | movsd qword [r4+16*8+5*8], xmm5 + | movsd qword [r4+16*8+4*8], xmm4 + | movsd qword [r4+16*8+3*8], xmm3 + | movsd qword [r4+16*8+2*8], xmm2 + | movsd qword [r4+16*8+1*8], xmm1 + | movsd qword [r4+16*8+0*8], xmm0 + |.else + | sub r4, 8*4+8*8-4 /* CPU regs + SSE regs */ + | mov aword [r4+2*4], edx + | mov aword [r4+1*4], ecx + | mov aword [r4+0*4], eax + | mov FCARG1a, aword [r4+8*4+8*8-4] // exit_num = POP + | mov FCARG2a, r4 + | movsd qword [r4+8*4+7*8], xmm7 + | movsd qword [r4+8*4+6*8], xmm6 + | movsd qword [r4+8*4+5*8], xmm5 + | movsd qword [r4+8*4+4*8], xmm4 + | movsd qword [r4+8*4+3*8], xmm3 + | movsd qword [r4+8*4+2*8], xmm2 + | movsd qword [r4+8*4+1*8], xmm1 + | movsd qword [r4+8*4+0*8], xmm0 + |.endif | - | // trace_num = EG(reserved)[zend_func_info_rid] - | MEM_OP2_2_ZTS mov, FCARG1a, aword, executor_globals, reserved[zend_func_info_rid], r0 - | // exit_num = POP - | pop FCARG2a | // EX(opline) = opline | SAVE_OPLINE | // zend_jit_trace_exit(trace_num, exit_num) | EXT_CALL zend_jit_trace_exit, r0 + |.if X64 + | add r4, 16*8+16*8 /* CPU regs + SSE regs */ + |.else + | add r4, 8*4+8*8 /* CPU regs + SSE regs */ + |.endif | // execute_data = EG(current_excute_data) | MEM_OP2_2_ZTS mov, FP, aword, executor_globals, current_execute_data, r0 | test eax, eax diff --git a/ext/opcache/jit/zend_jit_x86.h b/ext/opcache/jit/zend_jit_x86.h index 71fcb93ae1..8b2365efad 100644 --- a/ext/opcache/jit/zend_jit_x86.h +++ b/ext/opcache/jit/zend_jit_x86.h @@ -65,6 +65,16 @@ typedef enum _zend_reg { ZREG_NUM } zend_reg; +typedef struct _zend_jit_registers_buf { +#if defined(__x86_64__) || defined(_WIN64) + uint64_t r[16]; + double xmm[16]; +#else + uint32_t r[8]; + double xmm[8]; +#endif +} zend_jit_registers_buf; + #define ZREG_RAX ZREG_R0 #define ZREG_RCX ZREG_R1 #define ZREG_RDX ZREG_R2