diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-07-09 13:40:19 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-07-09 13:40:19 +0300 |
commit | 92448d9db2424bb6fee13a2a63018c17f7f1fc04 (patch) | |
tree | 8e42fc618398dcab3bf27d294474d1c1c41cae9b /ext | |
parent | e33dd6ab1f039cca0de3c1ebc106f4bce77e959f (diff) | |
parent | 5872bfc481d7a969eb80c7be35f248841d9d8e65 (diff) | |
download | php-git-92448d9db2424bb6fee13a2a63018c17f7f1fc04.tar.gz |
Merge branch 'jit-jumptable-x64'
* jit-jumptable-x64:
Use RIP-relative addressing
Align jumptables
Fix jumtable index calculation
Support JIT jumptables on x64
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/jit/dynasm/dasm_x86.h | 18 | ||||
-rw-r--r-- | ext/opcache/jit/dynasm/dasm_x86.lua | 8 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit.c | 3 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 52 |
4 files changed, 48 insertions, 33 deletions
diff --git a/ext/opcache/jit/dynasm/dasm_x86.h b/ext/opcache/jit/dynasm/dasm_x86.h index 77945ac655..39449c15af 100644 --- a/ext/opcache/jit/dynasm/dasm_x86.h +++ b/ext/opcache/jit/dynasm/dasm_x86.h @@ -17,11 +17,11 @@ /* Action definitions. DASM_STOP must be 255. */ enum { - DASM_DISP = 233, + DASM_DISP = 232, DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB, DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, - DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, - DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP + DASM_IMM_LG, DASM_IMM_PC, DASM_IMM_PC64, DASM_LABEL_LG, DASM_LABEL_PC, + DASM_ALIGN, DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP }; /* Maximum number of section buffer positions for a single dasm_put() call. */ @@ -228,6 +228,7 @@ void dasm_put(Dst_DECL, int start, ...) pl -= 246; n = *pl; if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ goto linkrel; + case DASM_IMM_PC64: ofs += 4; case DASM_REL_PC: case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); putrel: @@ -335,7 +336,8 @@ int dasm_link(Dst_DECL, size_t *szp) case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++; case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W: case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB: - case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break; + case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: case DASM_IMM_PC64: + pos++; break; case DASM_LABEL_LG: p++; case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */ case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */ @@ -359,10 +361,13 @@ int dasm_link(Dst_DECL, size_t *szp) #ifndef DASM_ALIGNED_WRITES typedef ZEND_SET_ALIGNED(1, unsigned short unaligned_short); typedef ZEND_SET_ALIGNED(1, unsigned int unaligned_int); +typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t); #define dasmw(x) \ do { *((unaligned_short *)cp) = (unsigned short)(x); cp+=2; } while (0) #define dasmd(x) \ do { *((unaligned_int *)cp) = (unsigned int)(x); cp+=4; } while (0) +#define dasmq(x) \ + do { *((unaligned_uint64_t *)cp) = (uint64_t)(x); cp+=8; } while (0) #else #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) @@ -442,6 +447,11 @@ int dasm_encode(Dst_DECL, void *buffer) n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); goto wd; } + case DASM_IMM_PC64: { + int *pb = DASM_POS2PTR(D, n); + dasmq(*pb < 0 ? pb[1] : (*pb + (ptrdiff_t)base)); + break; + } case DASM_LABEL_LG: { int idx = *p++; if (idx >= 10) diff --git a/ext/opcache/jit/dynasm/dasm_x86.lua b/ext/opcache/jit/dynasm/dasm_x86.lua index a5efd98fb5..f7d81d838f 100644 --- a/ext/opcache/jit/dynasm/dasm_x86.lua +++ b/ext/opcache/jit/dynasm/dasm_x86.lua @@ -47,7 +47,7 @@ local action_names = { -- action arg (1 byte) or int arg, 2 buffer pos (link, offset): "REL_LG", "REL_PC", -- action arg (1 byte) or int arg, 1 buffer pos (link): - "IMM_LG", "IMM_PC", + "IMM_LG", "IMM_PC", "IMM_PC64", -- action arg (1 byte) or int arg, 1 buffer pos (offset): "LABEL_LG", "LABEL_PC", -- action arg (1 byte), 1 buffer pos (offset): @@ -434,7 +434,11 @@ local function wputlabel(aprefix, imm, num) end wputxb(imm) else - waction(aprefix.."PC", imm, num) + if aprefix == "IMM_" and x64 then + waction("IMM_PC64", imm, num) + else + waction(aprefix.."PC", imm, num) + end end end diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 478244b6d7..0031dc6731 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -309,6 +309,9 @@ static void *dasm_link_and_encode(dasm_State **dasm_state, if (ret != DASM_S_OK) { // TODO: dasm_encode() failed ??? +#if ZEND_DEBUG + ZEND_UNREACHABLE(); +#endif return NULL; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 12dccc00ff..7ba23e3d10 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -11377,10 +11377,6 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o { HashTable *jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - if (sizeof(void*) == 8 && !IS_32BIT(dasm_end)) { - // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - return 1; - } if (opline->op1_type == IS_CONST) { zval *zv = RT_CONSTANT(opline, opline->op1); zval *jump_zv; @@ -11444,23 +11440,25 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | cmp FCARG2a, jumptable->nNumUsed | jae >3 |.if X64 - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - | movsxd r0, dword [FCARG2a * 4 + >4] - | jmp r0 + if (!IS_32BIT(dasm_end)) { + | lea r0, aword [>4] + | jmp aword [r0 + FCARG2a * 8] + } else { + | jmp aword [FCARG2a * 8 + >4] + } |.else | jmp aword [FCARG2a * 4 + >4] |.endif |3: |.cold_code + |.align aword |4: p = jumptable->arData; do { if (Z_TYPE(p->val) == IS_UNDEF) { - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? | .aword =>b } else { int b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL(p->val)) - op_array->opcodes]; - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? | .aword =>b } p++; @@ -11474,8 +11472,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | jz =>b | LOAD_ADDR FCARG1a, jumptable | sub r0, aword [FCARG1a + offsetof(HashTable, arData)] - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - | mov FCARG1a, (sizeof(Bucket) / sizeof(uint32_t)) + | mov FCARG1a, (sizeof(Bucket) / sizeof(void*)) |.if X64 | cqo |.else @@ -11483,18 +11480,21 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o |.endif | idiv FCARG1a |.if X64 - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - | movsxd r0, dword [r0 + >4] - | jmp r0 + if (!IS_32BIT(dasm_end)) { + | lea FCARG1a, aword [>4] + | jmp aword [FCARG1a + r0] + } else { + | jmp aword [r0 + >4] + } |.else - | jmp dword [r0 + >4] + | jmp aword [r0 + >4] |.endif |3: |.cold_code + |.align aword |4: ZEND_HASH_FOREACH_VAL(jumptable, val) { b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(val)) - op_array->opcodes]; - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? | .aword =>b } ZEND_HASH_FOREACH_END(); |.code @@ -11527,8 +11527,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | jz =>b | LOAD_ADDR FCARG1a, jumptable | sub r0, aword [FCARG1a + offsetof(HashTable, arData)] - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - | mov FCARG1a, (sizeof(Bucket) / sizeof(uint32_t)) + | mov FCARG1a, (sizeof(Bucket) / sizeof(void*)) |.if X64 | cqo |.else @@ -11536,23 +11535,22 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o |.endif | idiv FCARG1a |.if X64 - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - | movsxd r0, dword [r0 + >4] - | jmp r0 + if (!IS_32BIT(dasm_end)) { + | lea FCARG1a, aword [>4] + | jmp aword [FCARG1a + r0] + } else { + | jmp aword [r0 + >4] + } |.else - | jmp dword [r0 + >4] + | jmp aword [r0 + >4] |.endif |3: |.cold_code + |.align aword |4: ZEND_HASH_FOREACH_VAL(jumptable, val) { b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(val)) - op_array->opcodes]; - | // TODO: DynASM stores .aword as 4-bytes even in 64-bit mode ??? - |.if X64 | .aword =>b - |.else - | .aword =>b - |.endif } ZEND_HASH_FOREACH_END(); |.code } |