From 60a5e52bf72f6a6462f164f912543e78ef70d53d Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 25 Feb 2017 17:46:43 +0300 Subject: [PATCH] Fixes #285: Increase available allocation range in mcode_alloc() Change mcode_alloc() so that instead of all execution threads using the same allocation range of '[target - range/2; target + range / 2]' (where 'range' is the jump range defined by the architecture), make some threads use the '[target - range; target]' range, and other ones use '[target; target + range]' based on a PRNG. The patch essentially doubles the available allocation pool for mcode_alloc() and helps reduce mmap() scalability issues for multi-threaded applications. --- src/lj_jit.h | 4 ++++ src/lj_mcode.c | 21 ++++++--------------- src/lj_state.c | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/lj_jit.h b/src/lj_jit.h index 92054e3d..5baa7447 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h @@ -452,6 +452,10 @@ typedef struct jit_State { uint32_t penaltyslot; /* Round-robin index into penalty slots. */ uint32_t prngstate; /* PRNG state. */ + uintptr_t target; /* target address for mcode_alloc() */ + uintptr_t range; /* allocation range for mcode_alloc() */ + uintptr_t allocbase; /* allocation base addred for mcode_alloc() */ + #ifdef LUAJIT_ENABLE_TABLE_BUMP RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ #endif diff --git a/src/lj_mcode.c b/src/lj_mcode.c index f4cb1b78..0c10f211 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c @@ -219,18 +219,8 @@ static void mcode_protect(jit_State *J, int prot) static void *mcode_alloc(jit_State *J, size_t sz) { /* Target an address in the static assembler code (64K aligned). - ** Try addresses within a distance of target-range/2+1MB..target+range/2-1MB. - ** Use half the jump range so every address in the range can reach any other. - */ -#if LJ_TARGET_MIPS - /* Use the middle of the 256MB-aligned region. */ - uintptr_t target = ((uintptr_t)(void *)lj_vm_exit_handler & - ~(uintptr_t)0x0fffffffu) + 0x08000000u; -#else - uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff; -#endif - const uintptr_t range = (1u << (LJ_TARGET_JUMPRANGE-1)) - (1u << 21); - /* First try a contiguous area below the last one. */ + ** Try addresses within a distance of J->allocbase..J->allocbase+J->range. + ** First try a contiguous area below the last one. */ uintptr_t hint = J->mcarea ? (uintptr_t)J->mcarea - sz : 0; int i; for (i = 0; i < 32; i++) { /* 32 attempts ought to be enough ... */ @@ -238,15 +228,16 @@ static void *mcode_alloc(jit_State *J, size_t sz) void *p = mcode_alloc_at(J, hint, sz, MCPROT_GEN); if (mcode_validptr(p) && - ((uintptr_t)p + sz - target < range || target - (uintptr_t)p < range)) + ((uintptr_t)p + sz - J->target < J->range || + J->target - (uintptr_t)p < J->range)) return p; if (p) mcode_free(J, p, sz); /* Free badly placed area. */ } /* Next try probing pseudo-random addresses. */ do { hint = LJ_PRNG_BITS(J, LJ_TARGET_JUMPRANGE-16) << 16; /* 64K aligned. */ - } while (!(hint + sz < range*2)); - hint = target + hint - range; + } while (!(hint + sz < J->range)); + hint = J->allocbase + hint; } lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */ return NULL; diff --git a/src/lj_state.c b/src/lj_state.c index 3cc0fea5..26ac7755 100644 --- a/src/lj_state.c +++ b/src/lj_state.c @@ -225,6 +225,23 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) return NULL; } L->status = 0; +#if LJ_TARGET_MIPS + /* Use the middle of the 256MB-aligned region. */ + uintptr_t target = ((uintptr_t)(void *)lj_vm_exit_handler & + ~(uintptr_t)0x0fffffffu) + 0x08000000u; +#else + uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff; +#endif + uintptr_t range = (1u << LJ_TARGET_JUMPRANGE) - (1u << 21); + uintptr_t allocbase; + if (LJ_PRNG_BITS(G2J(g), 1)) { + allocbase = (target - range > target) ? 0 : target - range; + } else { + allocbase = target; + } + G2J(g)->target = target; + G2J(g)->range = range; + G2J(g)->allocbase = allocbase; return L; }