JIT compiler update.

This commit is contained in:
Zoltán Herczeg 2021-02-12 07:45:12 +00:00
parent 25029849c3
commit b6acebe497
3 changed files with 87 additions and 71 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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: