diff options
author | Dmitry Stogov <dmitry@zend.com> | 2021-03-23 17:12:15 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2021-03-23 17:12:15 +0300 |
commit | 7adaec1ce8312995f65f1c177d1a2184c2f80671 (patch) | |
tree | 9d371a7c2d00a9c2e76930b4ad33138cdc049a18 | |
parent | c290de157caa03b34f9c5ee7cb987e35cca0e468 (diff) | |
download | php-git-7adaec1ce8312995f65f1c177d1a2184c2f80671.tar.gz |
Move system independent code out from x86 specific header
-rw-r--r-- | ext/opcache/jit/zend_jit_internal.h | 185 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 13 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.h | 196 |
3 files changed, 204 insertions, 190 deletions
diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 906262773f..a351dec030 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -20,6 +20,191 @@ #ifndef ZEND_JIT_INTERNAL_H #define ZEND_JIT_INTERNAL_H +/* Register Set */ +#define ZEND_REGSET_EMPTY 0 + +#define ZEND_REGSET_IS_EMPTY(regset) \ + (regset == ZEND_REGSET_EMPTY) + +#define ZEND_REGSET(reg) \ + (1u << (reg)) + +#define ZEND_REGSET_INTERVAL(reg1, reg2) \ + (((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1)) + +#define ZEND_REGSET_IN(regset, reg) \ + (((regset) & ZEND_REGSET(reg)) != 0) + +#define ZEND_REGSET_INCL(regset, reg) \ + (regset) |= ZEND_REGSET(reg) + +#define ZEND_REGSET_EXCL(regset, reg) \ + (regset) &= ~ZEND_REGSET(reg) + +#define ZEND_REGSET_UNION(set1, set2) \ + ((set1) | (set2)) + +#define ZEND_REGSET_INTERSECTION(set1, set2) \ + ((set1) & (set2)) + +#define ZEND_REGSET_DIFFERENCE(set1, set2) \ + ((set1) & ~(set2)) + +#ifndef _WIN32 +# if (ZREG_NUM <= 32) +# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctz(set)) +# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clz(set)^31))) +# elif(ZREG_NUM <= 64) +# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctzll(set)) +# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clzll(set)^63))) +# else +# errir "Too many registers" +# endif +#else +# include <intrin.h> +uint32_t __inline __zend_jit_ctz(uint32_t value) { + DWORD trailing_zero = 0; + if (_BitScanForward(&trailing_zero, value)) { + return trailing_zero; + } + return 32; +} +uint32_t __inline __zend_jit_clz(uint32_t value) { + DWORD leading_zero = 0; + if (_BitScanReverse(&leading_zero, value)) { + return 31 - leading_zero; + } + return 32; +} +# define ZEND_REGSET_FIRST(set) ((zend_reg)__zend_jit_ctz(set)) +# define ZEND_REGSET_LAST(set) ((zend_reg)(__zend_jit_clz(set)^31))) +#endif + +#define ZEND_REGSET_FOREACH(set, reg) \ + do { \ + zend_regset _tmp = (set); \ + while (!ZEND_REGSET_IS_EMPTY(_tmp)) { \ + zend_reg _reg = ZEND_REGSET_FIRST(_tmp); \ + ZEND_REGSET_EXCL(_tmp, _reg); \ + reg = _reg; \ + +#define ZEND_REGSET_FOREACH_END() \ + } \ + } while (0) + +/* Register Names */ +extern const char *zend_reg_name[]; + +/* Address Encoding */ +typedef uintptr_t zend_jit_addr; + +#define IS_CONST_ZVAL 0 +#define IS_MEM_ZVAL 1 +#define IS_REG 2 + +#define _ZEND_ADDR_MODE_MASK 0x3 +#define _ZEND_ADDR_REG_SHIFT 2 +#define _ZEND_ADDR_REG_MASK 0x3f /* no more than 64 registers */ +#define _ZEND_ADDR_OFFSET_SHIFT 8 +#define _ZEND_ADDR_REG_STORE_BIT 8 +#define _ZEND_ADDR_REG_LOAD_BIT 9 +#define _ZEND_ADDR_REG_LAST_USE_BIT 10 + +#define ZEND_ADDR_CONST_ZVAL(zv) \ + (((zend_jit_addr)(uintptr_t)(zv)) | IS_CONST_ZVAL) +#define ZEND_ADDR_MEM_ZVAL(reg, offset) \ + ((((zend_jit_addr)(uintptr_t)(offset)) << _ZEND_ADDR_OFFSET_SHIFT) | \ + (((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \ + IS_MEM_ZVAL) +#define ZEND_ADDR_REG(reg) \ + ((((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \ + IS_REG) + +#define Z_MODE(addr) (((addr) & _ZEND_ADDR_MODE_MASK)) +#define Z_ZV(addr) ((zval*)(addr)) +#define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT)) +#define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK)) +#define Z_STORE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_STORE_BIT) & 1)) +#define Z_LOAD(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LOAD_BIT) & 1)) +#define Z_LAST_USE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LAST_USE_BIT) & 1)) + +#define OP_REG_EX(reg, store, load, last_use) \ + ((reg) | \ + ((store) ? (1 << (_ZEND_ADDR_REG_STORE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \ + ((load) ? (1 << (_ZEND_ADDR_REG_LOAD_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \ + ((last_use) ? (1 << (_ZEND_ADDR_REG_LAST_USE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) \ + ) + +#define OP_REG(ssa_op, op) \ + (ra && ssa_op->op >= 0 && ra[ssa_op->op] ? \ + OP_REG_EX(ra[ssa_op->op]->reg, \ + (ra[ssa_op->op]->flags & ZREG_STORE), \ + (ra[ssa_op->op]->flags & ZREG_LOAD), \ + zend_ival_is_last_use(ra[ssa_op->op], ssa_op - ssa->ops) \ + ) : ZREG_NONE) + +static zend_always_inline zend_jit_addr _zend_jit_decode_op(zend_uchar op_type, znode_op op, const zend_op *opline, zend_reg reg) +{ + if (op_type == IS_CONST) { +#if ZEND_USE_ABS_CONST_ADDR + return ZEND_ADDR_CONST_ZVAL(op.zv); +#else + return ZEND_ADDR_CONST_ZVAL(RT_CONSTANT(opline, op)); +#endif + } else { + ZEND_ASSERT(op_type & (IS_CV|IS_TMP_VAR|IS_VAR)); + if (reg != ZREG_NONE) { + return ZEND_ADDR_REG(reg); + } else { + return ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var); + } + } +} + +#define OP_ADDR(opline, type, op) \ + _zend_jit_decode_op((opline)->type, (opline)->op, opline, ZREG_NONE) + +#define OP1_ADDR() \ + OP_ADDR(opline, op1_type, op1) +#define OP2_ADDR() \ + OP_ADDR(opline, op2_type, op2) +#define RES_ADDR() \ + OP_ADDR(opline, result_type, result) +#define OP1_DATA_ADDR() \ + OP_ADDR(opline + 1, op1_type, op1) + +#define OP_REG_ADDR(opline, type, _op, _ssa_op) \ + _zend_jit_decode_op((opline)->type, (opline)->_op, opline, \ + OP_REG(ssa_op, _ssa_op)) + +#define OP1_REG_ADDR() \ + OP_REG_ADDR(opline, op1_type, op1, op1_use) +#define OP2_REG_ADDR() \ + OP_REG_ADDR(opline, op2_type, op2, op2_use) +#define RES_REG_ADDR() \ + OP_REG_ADDR(opline, result_type, result, result_def) +#define OP1_DATA_REG_ADDR() \ + OP_REG_ADDR(opline + 1, op1_type, op1, op1_use) + +#define OP1_DEF_REG_ADDR() \ + OP_REG_ADDR(opline, op1_type, op1, op1_def) +#define OP2_DEF_REG_ADDR() \ + OP_REG_ADDR(opline, op2_type, op2, op2_def) +#define RES_USE_REG_ADDR() \ + OP_REG_ADDR(opline, result_type, result, result_use) +#define OP1_DATA_DEF_REG_ADDR() \ + OP_REG_ADDR(opline + 1, op1_type, op1, op1_def) + +static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2) +{ + if (addr1 == addr2) { + return 1; + } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) { + return Z_REG(addr1) == Z_REG(addr2); + } + return 0; +} + typedef struct _zend_jit_op_array_extension { zend_func_info func_info; const void *orig_handler; diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 142b08eed6..6bb4c78778 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -110,7 +110,6 @@ */ #include "Zend/zend_cpuinfo.h" -#include "jit/zend_jit_x86.h" #ifdef HAVE_VALGRIND # include <valgrind/valgrind.h> @@ -141,6 +140,18 @@ const char* zend_reg_name[] = { # define GCC_GLOBAL_REGS 0 #endif +/* Simulate x86 fastcall */ +#ifdef _WIN64 +# define ZREG_FCARG1a ZREG_RCX +# define ZREG_FCARG2a ZREG_RDX +#elif defined(__x86_64__) +# define ZREG_FCARG1a ZREG_RDI +# define ZREG_FCARG2a ZREG_RSI +#else +# define ZREG_FCARG1a ZREG_RCX +# define ZREG_FCARG2a ZREG_RDX +#endif + #if ZTS static size_t tsrm_ls_cache_tcb_offset = 0; static size_t tsrm_tls_index; diff --git a/ext/opcache/jit/zend_jit_x86.h b/ext/opcache/jit/zend_jit_x86.h index d47c5be056..f811a1d520 100644 --- a/ext/opcache/jit/zend_jit_x86.h +++ b/ext/opcache/jit/zend_jit_x86.h @@ -99,58 +99,20 @@ typedef struct _zend_jit_registers_buf { #define ZREG_RDI ZREG_R7 #ifdef _WIN64 -# define ZREG_FP ZREG_R14 -# define ZREG_IP ZREG_R15 -# define ZREG_RX ZREG_IP -# define ZREG_FCARG1a ZREG_RCX -# define ZREG_FCARG2a ZREG_RDX +# define ZREG_FP ZREG_R14 +# define ZREG_IP ZREG_R15 #elif defined(__x86_64__) -# define ZREG_FP ZREG_R14 -# define ZREG_IP ZREG_R15 -# define ZREG_RX ZREG_IP -# define ZREG_FCARG1a ZREG_RDI -# define ZREG_FCARG2a ZREG_RSI +# define ZREG_FP ZREG_R14 +# define ZREG_IP ZREG_R15 #else -# define ZREG_FP ZREG_RSI -# define ZREG_IP ZREG_RDI -# define ZREG_RX ZREG_IP -# define ZREG_FCARG1a ZREG_RCX -# define ZREG_FCARG2a ZREG_RDX +# define ZREG_FP ZREG_RSI +# define ZREG_IP ZREG_RDI #endif -extern const char *zend_reg_name[]; +#define ZREG_RX ZREG_IP typedef uint32_t zend_regset; -#define ZEND_REGSET_EMPTY 0 - -#define ZEND_REGSET_IS_EMPTY(regset) \ - (regset == ZEND_REGSET_EMPTY) - -#define ZEND_REGSET(reg) \ - (1u << (reg)) - -#define ZEND_REGSET_INTERVAL(reg1, reg2) \ - (((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1)) - -#define ZEND_REGSET_IN(regset, reg) \ - (((regset) & ZEND_REGSET(reg)) != 0) - -#define ZEND_REGSET_INCL(regset, reg) \ - (regset) |= ZEND_REGSET(reg) - -#define ZEND_REGSET_EXCL(regset, reg) \ - (regset) &= ~ZEND_REGSET(reg) - -#define ZEND_REGSET_UNION(set1, set2) \ - ((set1) | (set2)) - -#define ZEND_REGSET_INTERSECTION(set1, set2) \ - ((set1) & (set2)) - -#define ZEND_REGSET_DIFFERENCE(set1, set2) \ - ((set1) & ~(set2)) - #ifdef _WIN64 # define ZEND_REGSET_FIXED \ (ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_R14) | ZEND_REGSET(ZREG_R15)) @@ -186,148 +148,4 @@ typedef uint32_t zend_regset; (ZEND_REGSET(ZREG_RBX) | ZEND_REGSET(ZREG_RBP)) #endif -#ifndef _WIN32 -#define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctz(set)) -#define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clz(set)^31))) -#else -#include <intrin.h> -uint32_t __inline __zend_jit_ctz( uint32_t value ) { - DWORD trailing_zero = 0; - if (_BitScanForward(&trailing_zero, value)) { - return trailing_zero; - } - return 32; -} -uint32_t __inline __zend_jit_clz(uint32_t value) { - DWORD leading_zero = 0; - if (_BitScanReverse(&leading_zero, value)) { - return 31 - leading_zero; - } - return 32; -} -#define ZEND_REGSET_FIRST(set) ((zend_reg)__zend_jit_ctz(set)) -#define ZEND_REGSET_LAST(set) ((zend_reg)(__zend_jit_clz(set)^31))) -#endif - -#define ZEND_REGSET_FOREACH(set, reg) \ - do { \ - zend_regset _tmp = (set); \ - while (!ZEND_REGSET_IS_EMPTY(_tmp)) { \ - zend_reg _reg = ZEND_REGSET_FIRST(_tmp); \ - ZEND_REGSET_EXCL(_tmp, _reg); \ - reg = _reg; \ - -#define ZEND_REGSET_FOREACH_END() \ - } \ - } while (0) - -typedef uintptr_t zend_jit_addr; - -#define IS_CONST_ZVAL 0 -#define IS_MEM_ZVAL 1 -#define IS_REG 2 - -#define _ZEND_ADDR_MODE_MASK 0x3 -#define _ZEND_ADDR_REG_SHIFT 2 -#define _ZEND_ADDR_REG_MASK 0x3f -#define _ZEND_ADDR_OFFSET_SHIFT 8 -#define _ZEND_ADDR_REG_STORE_BIT 8 -#define _ZEND_ADDR_REG_LOAD_BIT 9 -#define _ZEND_ADDR_REG_LAST_USE_BIT 10 - -#define ZEND_ADDR_CONST_ZVAL(zv) \ - (((zend_jit_addr)(uintptr_t)(zv)) | IS_CONST_ZVAL) -#define ZEND_ADDR_MEM_ZVAL(reg, offset) \ - ((((zend_jit_addr)(uintptr_t)(offset)) << _ZEND_ADDR_OFFSET_SHIFT) | \ - (((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \ - IS_MEM_ZVAL) -#define ZEND_ADDR_REG(reg) \ - ((((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \ - IS_REG) - -#define Z_MODE(addr) (((addr) & _ZEND_ADDR_MODE_MASK)) -#define Z_ZV(addr) ((zval*)(addr)) -#define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT)) -#define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK)) -#define Z_STORE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_STORE_BIT) & 1)) -#define Z_LOAD(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LOAD_BIT) & 1)) -#define Z_LAST_USE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LAST_USE_BIT) & 1)) - -#define OP_REG_EX(reg, store, load, last_use) \ - ((reg) | \ - ((store) ? (1 << (_ZEND_ADDR_REG_STORE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \ - ((load) ? (1 << (_ZEND_ADDR_REG_LOAD_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \ - ((last_use) ? (1 << (_ZEND_ADDR_REG_LAST_USE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) \ - ) - -#define OP_REG(ssa_op, op) \ - (ra && ssa_op->op >= 0 && ra[ssa_op->op] ? \ - OP_REG_EX(ra[ssa_op->op]->reg, \ - (ra[ssa_op->op]->flags & ZREG_STORE), \ - (ra[ssa_op->op]->flags & ZREG_LOAD), \ - zend_ival_is_last_use(ra[ssa_op->op], ssa_op - ssa->ops) \ - ) : ZREG_NONE) - -static zend_always_inline zend_jit_addr _zend_jit_decode_op(zend_uchar op_type, znode_op op, const zend_op *opline, zend_reg reg) -{ - if (op_type == IS_CONST) { -#if ZEND_USE_ABS_CONST_ADDR - return ZEND_ADDR_CONST_ZVAL(op.zv); -#else - return ZEND_ADDR_CONST_ZVAL(RT_CONSTANT(opline, op)); -#endif - } else { - ZEND_ASSERT(op_type & (IS_CV|IS_TMP_VAR|IS_VAR)); - if (reg != ZREG_NONE) { - return ZEND_ADDR_REG(reg); - } else { - return ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var); - } - } -} - -#define OP_ADDR(opline, type, op) \ - _zend_jit_decode_op((opline)->type, (opline)->op, opline, ZREG_NONE) - -#define OP1_ADDR() \ - OP_ADDR(opline, op1_type, op1) -#define OP2_ADDR() \ - OP_ADDR(opline, op2_type, op2) -#define RES_ADDR() \ - OP_ADDR(opline, result_type, result) -#define OP1_DATA_ADDR() \ - OP_ADDR(opline + 1, op1_type, op1) - -#define OP_REG_ADDR(opline, type, _op, _ssa_op) \ - _zend_jit_decode_op((opline)->type, (opline)->_op, opline, \ - OP_REG(ssa_op, _ssa_op)) - -#define OP1_REG_ADDR() \ - OP_REG_ADDR(opline, op1_type, op1, op1_use) -#define OP2_REG_ADDR() \ - OP_REG_ADDR(opline, op2_type, op2, op2_use) -#define RES_REG_ADDR() \ - OP_REG_ADDR(opline, result_type, result, result_def) -#define OP1_DATA_REG_ADDR() \ - OP_REG_ADDR(opline + 1, op1_type, op1, op1_use) - -#define OP1_DEF_REG_ADDR() \ - OP_REG_ADDR(opline, op1_type, op1, op1_def) -#define OP2_DEF_REG_ADDR() \ - OP_REG_ADDR(opline, op2_type, op2, op2_def) -#define RES_USE_REG_ADDR() \ - OP_REG_ADDR(opline, result_type, result, result_use) -#define OP1_DATA_DEF_REG_ADDR() \ - OP_REG_ADDR(opline + 1, op1_type, op1, op1_def) - -static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2) -{ - if (addr1 == addr2) { - return 1; - } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) { - return Z_REG(addr1) == Z_REG(addr2); - } - return 0; -} - #endif /* ZEND_JIT_X86_H */ |