JIT compiler update.
This commit is contained in:
parent
25029849c3
commit
b6acebe497
|
@ -158,6 +158,8 @@ extern "C" {
|
|||
#define SLJIT_CONFIG_MIPS_64 1
|
||||
#elif defined(__sparc__) || defined(__sparc)
|
||||
#define SLJIT_CONFIG_SPARC_32 1
|
||||
#elif defined(__s390x__)
|
||||
#define SLJIT_CONFIG_S390X 1
|
||||
#else
|
||||
/* Unsupported architecture */
|
||||
#define SLJIT_CONFIG_UNSUPPORTED 1
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
|
@ -91,65 +92,76 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
|||
VirtualFree(chunk, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifdef MAP_ANON
|
||||
/* Configures TARGET_OS_OSX when appropriate */
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_OSX && defined(MAP_JIT)
|
||||
#include <sys/utsname.h>
|
||||
#endif /* TARGET_OS_OSX && MAP_JIT */
|
||||
|
||||
#ifdef MAP_JIT
|
||||
#else /* POSIX */
|
||||
|
||||
#if defined(__APPLE__) && defined(MAP_JIT)
|
||||
/*
|
||||
On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a
|
||||
version where it's OK to have more than one JIT block.
|
||||
version where it's OK to have more than one JIT block or where MAP_JIT is
|
||||
required.
|
||||
On non-macOS systems, returns MAP_JIT if it is defined.
|
||||
*/
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_OSX
|
||||
#if defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86
|
||||
#ifdef MAP_ANON
|
||||
#include <sys/utsname.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SLJIT_MAP_JIT (get_map_jit_flag())
|
||||
|
||||
static SLJIT_INLINE int get_map_jit_flag()
|
||||
{
|
||||
#if TARGET_OS_OSX
|
||||
sljit_sw page_size = get_page_alignment() + 1;
|
||||
sljit_sw page_size;
|
||||
void *ptr;
|
||||
struct utsname name;
|
||||
static int map_jit_flag = -1;
|
||||
|
||||
/*
|
||||
The following code is thread safe because multiple initialization
|
||||
sets map_jit_flag to the same value and the code has no side-effects.
|
||||
Changing the kernel version witout system restart is (very) unlikely.
|
||||
*/
|
||||
if (map_jit_flag == -1) {
|
||||
struct utsname name;
|
||||
|
||||
if (map_jit_flag < 0) {
|
||||
map_jit_flag = 0;
|
||||
uname(&name);
|
||||
|
||||
/* Kernel version for 10.14.0 (Mojave) */
|
||||
/* Kernel version for 10.14.0 (Mojave) or later */
|
||||
if (atoi(name.release) >= 18) {
|
||||
page_size = get_page_alignment() + 1;
|
||||
/* Only use MAP_JIT if a hardened runtime is used */
|
||||
ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
|
||||
ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
|
||||
if (ptr == MAP_FAILED) {
|
||||
map_jit_flag = MAP_JIT;
|
||||
} else {
|
||||
if (ptr != MAP_FAILED)
|
||||
munmap(ptr, page_size);
|
||||
}
|
||||
else
|
||||
map_jit_flag = MAP_JIT;
|
||||
}
|
||||
}
|
||||
|
||||
return map_jit_flag;
|
||||
#else /* !TARGET_OS_OSX */
|
||||
return MAP_JIT;
|
||||
#endif /* TARGET_OS_OSX */
|
||||
}
|
||||
|
||||
#endif /* MAP_JIT */
|
||||
#endif /* MAP_ANON */
|
||||
#endif /* __APPLE__ */
|
||||
#else /* !SLJIT_CONFIG_X86 */
|
||||
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
|
||||
#error Unsupported architecture
|
||||
#endif /* SLJIT_CONFIG_ARM */
|
||||
#include <pthread.h>
|
||||
|
||||
#define SLJIT_MAP_JIT (MAP_JIT)
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
|
||||
apple_update_wx_flags(enable_exec)
|
||||
|
||||
static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
|
||||
{
|
||||
pthread_jit_write_protect_np(enable_exec);
|
||||
}
|
||||
#endif /* SLJIT_CONFIG_X86 */
|
||||
#else /* !TARGET_OS_OSX */
|
||||
#define SLJIT_MAP_JIT (MAP_JIT)
|
||||
#endif /* TARGET_OS_OSX */
|
||||
#endif /* __APPLE__ && MAP_JIT */
|
||||
#ifndef SLJIT_UPDATE_WX_FLAGS
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
#endif /* !SLJIT_UPDATE_WX_FLAGS */
|
||||
#ifndef SLJIT_MAP_JIT
|
||||
#define SLJIT_MAP_JIT (0)
|
||||
#endif /* !SLJIT_MAP_JIT */
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
|
@ -157,12 +169,7 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
|||
const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
|
||||
#ifdef MAP_ANON
|
||||
|
||||
int flags = MAP_PRIVATE | MAP_ANON;
|
||||
|
||||
#ifdef MAP_JIT
|
||||
flags |= get_map_jit_flag();
|
||||
#endif
|
||||
int flags = MAP_PRIVATE | MAP_ANON | SLJIT_MAP_JIT;
|
||||
|
||||
retval = mmap(NULL, size, prot, flags, -1, 0);
|
||||
#else /* !MAP_ANON */
|
||||
|
@ -173,14 +180,15 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
|||
#endif /* MAP_ANON */
|
||||
|
||||
if (retval == MAP_FAILED)
|
||||
retval = NULL;
|
||||
else {
|
||||
if (mprotect(retval, size, prot) < 0) {
|
||||
munmap(retval, size);
|
||||
retval = NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
if (mprotect(retval, size, prot) < 0) {
|
||||
munmap(retval, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -189,7 +197,7 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
|||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* windows */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Common functions */
|
||||
|
@ -261,6 +269,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
|||
while (free_block) {
|
||||
if (free_block->size >= size) {
|
||||
chunk_size = free_block->size;
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
if (chunk_size > size + 64) {
|
||||
/* We just cut a block from the end of the free block. */
|
||||
chunk_size -= size;
|
||||
|
@ -326,6 +335,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
|||
allocated_size -= header->size;
|
||||
|
||||
/* Connecting free blocks together if possible. */
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
|
||||
/* If header->prev_size == 0, free_block will equal to header.
|
||||
In this case, free_block->header.size will be > 0. */
|
||||
|
@ -358,6 +368,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
|||
}
|
||||
}
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
}
|
||||
|
||||
|
@ -367,6 +378,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
|||
struct free_block* next_free_block;
|
||||
|
||||
SLJIT_ALLOCATOR_LOCK();
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
|
@ -381,5 +393,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
|||
}
|
||||
|
||||
SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
|||
typedef sljit_uw sljit_ins;
|
||||
|
||||
/* Instruction tags (most significant halfword). */
|
||||
const sljit_ins sljit_ins_const = (sljit_ins)1 << 48;
|
||||
static const sljit_ins sljit_ins_const = (sljit_ins)1 << 48;
|
||||
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
14, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1
|
||||
|
@ -66,22 +66,22 @@ typedef sljit_uw sljit_gpr;
|
|||
* will be retired ASAP (TODO: carenas)
|
||||
*/
|
||||
|
||||
const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */
|
||||
const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */
|
||||
const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */
|
||||
const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */
|
||||
const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */
|
||||
const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */
|
||||
const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */
|
||||
const sljit_gpr r7 = 7; /* reg_map[6] */
|
||||
const sljit_gpr r8 = 8; /* reg_map[7] */
|
||||
const sljit_gpr r9 = 9; /* reg_map[8] */
|
||||
const sljit_gpr r10 = 10; /* reg_map[9] */
|
||||
const sljit_gpr r11 = 11; /* reg_map[10] */
|
||||
const sljit_gpr r12 = 12; /* reg_map[11]: GOT */
|
||||
const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */
|
||||
const sljit_gpr r14 = 14; /* reg_map[0]: return address and flag register */
|
||||
const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */
|
||||
static const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */
|
||||
static const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */
|
||||
static const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */
|
||||
static const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */
|
||||
static const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */
|
||||
static const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */
|
||||
static const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */
|
||||
static const sljit_gpr r7 = 7; /* reg_map[6] */
|
||||
static const sljit_gpr r8 = 8; /* reg_map[7] */
|
||||
static const sljit_gpr r9 = 9; /* reg_map[8] */
|
||||
static const sljit_gpr r10 = 10; /* reg_map[9] */
|
||||
static const sljit_gpr r11 = 11; /* reg_map[10] */
|
||||
static const sljit_gpr r12 = 12; /* reg_map[11]: GOT */
|
||||
static const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */
|
||||
static const sljit_gpr r14 = 14; /* reg_map[0]: return address and flag register */
|
||||
static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */
|
||||
|
||||
/* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */
|
||||
/* TODO(carenas): r12 might conflict in PIC code, reserve? */
|
||||
|
@ -100,8 +100,8 @@ const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack point
|
|||
/* Link registers. The normal link register is r14, but since
|
||||
we use that for flags we need to use r0 instead to do fast
|
||||
calls so that flags are preserved. */
|
||||
const sljit_gpr link_r = 14; /* r14 */
|
||||
const sljit_gpr fast_link_r = 0; /* r0 */
|
||||
static const sljit_gpr link_r = 14; /* r14 */
|
||||
static const sljit_gpr fast_link_r = 0; /* r0 */
|
||||
|
||||
/* Flag register layout:
|
||||
|
||||
|
@ -110,7 +110,7 @@ const sljit_gpr fast_link_r = 0; /* r0 */
|
|||
| ZERO | 0 | 0 | C C |///////|
|
||||
+---------------+---+---+-------+-------+
|
||||
*/
|
||||
const sljit_gpr flag_r = 14; /* r14 */
|
||||
static const sljit_gpr flag_r = 14; /* r14 */
|
||||
|
||||
struct sljit_s390x_const {
|
||||
struct sljit_const const_; /* must be first */
|
||||
|
@ -1465,7 +1465,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
|||
op = GET_OPCODE(op) | (op & SLJIT_I32_OP);
|
||||
switch (op) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
/* TODO(mundaym): insert real breakpoint? */
|
||||
/* The following invalid instruction is emitted by gdb. */
|
||||
return push_inst(compiler, 0x0001 /* 2-byte trap */);
|
||||
case SLJIT_NOP:
|
||||
return push_inst(compiler, 0x0700 /* 2-byte nop */);
|
||||
case SLJIT_LMUL_UW:
|
||||
|
|
Loading…
Reference in New Issue