Added support for separate mcode areas

This commit is contained in:
fsfod 2016-02-09 08:04:51 +00:00
parent bd00094c3b
commit 235ab3bf6f
4 changed files with 61 additions and 50 deletions

View File

@ -389,6 +389,15 @@ typedef struct FoldState {
IRIns right[2]; /* Instruction referenced by right operand. */ IRIns right[2]; /* Instruction referenced by right operand. */
} FoldState; } FoldState;
typedef struct MCodeArea {
int prot; /* Protection of current mcode area. */
MCode *base; /* Base of current mcode area. */
MCode *top; /* Top of current mcode area. */
MCode *bot; /* Bottom of current mcode area. */
size_t sz; /* Size of current mcode area. */
size_t szall; /* Total size of all allocated mcode areas in this chain. */
} MCodeArea;
/* JIT compiler state. */ /* JIT compiler state. */
typedef struct jit_State { typedef struct jit_State {
GCtrace cur; /* Current trace. */ GCtrace cur; /* Current trace. */
@ -474,12 +483,8 @@ typedef struct jit_State {
BCIns *patchpc; /* PC for pending re-patch. */ BCIns *patchpc; /* PC for pending re-patch. */
BCIns patchins; /* Instruction for pending re-patch. */ BCIns patchins; /* Instruction for pending re-patch. */
int mcprot; /* Protection of current mcode area. */ MCodeArea mcarea; /* JIT mcode area */
MCode *mcarea; /* Base of current mcode area. */ MCodeArea *curmcarea; /* Current mcode area by default is mcarea */
MCode *mctop; /* Top of current mcode area. */
MCode *mcbot; /* Bottom of current mcode area. */
size_t szmcarea; /* Size of current mcode area. */
size_t szallmcarea; /* Total size of all allocated mcode areas. */
TValue errinfo; /* Additional info element for trace errors. */ TValue errinfo; /* Additional info element for trace errors. */

View File

@ -191,12 +191,12 @@ static LJ_NOINLINE void mcode_protfail(jit_State *J)
} }
/* Change protection of MCode area. */ /* Change protection of MCode area. */
static void mcode_protect(jit_State *J, int prot) static void mcode_protect(jit_State *J, MCodeArea *area, int prot)
{ {
if (J->mcprot != prot) { if (area->prot != prot) {
if (LJ_UNLIKELY(mcode_setprot(J->mcarea, J->szmcarea, prot))) if (LJ_UNLIKELY(mcode_setprot(area->base, area->sz, prot)))
mcode_protfail(J); mcode_protfail(J);
J->mcprot = prot; area->prot = prot;
} }
} }
@ -213,7 +213,7 @@ static void mcode_protect(jit_State *J, int prot)
#ifdef LJ_TARGET_JUMPRANGE #ifdef LJ_TARGET_JUMPRANGE
/* Get memory within relative jump distance of our code in 64 bit mode. */ /* Get memory within relative jump distance of our code in 64 bit mode. */
static void *mcode_alloc(jit_State *J, size_t sz) static void *mcode_alloc(jit_State *J, MCodeArea *area, size_t sz)
{ {
/* Target an address in the static assembler code (64K aligned). /* Target an address in the static assembler code (64K aligned).
** Try addresses within a distance of target-range/2+1MB..target+range/2-1MB. ** Try addresses within a distance of target-range/2+1MB..target+range/2-1MB.
@ -228,7 +228,7 @@ static void *mcode_alloc(jit_State *J, size_t sz)
#endif #endif
const uintptr_t range = (1u << (LJ_TARGET_JUMPRANGE-1)) - (1u << 21); const uintptr_t range = (1u << (LJ_TARGET_JUMPRANGE-1)) - (1u << 21);
/* First try a contiguous area below the last one. */ /* First try a contiguous area below the last one. */
uintptr_t hint = J->mcarea ? (uintptr_t)J->mcarea - sz : 0; uintptr_t hint = area->base ? (uintptr_t)area->base - sz : 0;
int i; int i;
/* Limit probing iterations, depending on the available pool size. */ /* Limit probing iterations, depending on the available pool size. */
for (i = 0; i < LJ_TARGET_JUMPRANGE; i++) { for (i = 0; i < LJ_TARGET_JUMPRANGE; i++) {
@ -253,7 +253,7 @@ static void *mcode_alloc(jit_State *J, size_t sz)
#else #else
/* All memory addresses are reachable by relative jumps. */ /* All memory addresses are reachable by relative jumps. */
static void *mcode_alloc(jit_State *J, size_t sz) static void *mcode_alloc(jit_State *J, MCodeArea *area, size_t sz)
{ {
#if defined(__OpenBSD__) || LJ_TARGET_UWP #if defined(__OpenBSD__) || LJ_TARGET_UWP
/* Allow better executable memory allocation for OpenBSD W^X mode. */ /* Allow better executable memory allocation for OpenBSD W^X mode. */
@ -273,27 +273,28 @@ static void *mcode_alloc(jit_State *J, size_t sz)
/* -- MCode area management ----------------------------------------------- */ /* -- MCode area management ----------------------------------------------- */
/* Allocate a new MCode area. */ /* Allocate a new MCode area. */
static void mcode_allocarea(jit_State *J) static void mcode_allocarea(jit_State *J, MCodeArea *area)
{ {
MCode *oldarea = J->mcarea; MCode *oldarea = area->base;
size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10; size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10;
sz = (sz + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1); sz = (sz + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1);
J->mcarea = (MCode *)mcode_alloc(J, sz); area->base = (MCode *)mcode_alloc(J, area, sz);
J->szmcarea = sz; area->sz = sz;
J->mcprot = MCPROT_GEN; area->prot = MCPROT_GEN;
J->mctop = (MCode *)((char *)J->mcarea + J->szmcarea); area->top = (MCode *)((char *)area->base + area->sz);
J->mcbot = (MCode *)((char *)J->mcarea + sizeof(MCLink)); area->bot = (MCode *)((char *)area->base + sizeof(MCLink));
((MCLink *)J->mcarea)->next = oldarea; ((MCLink *)area->base)->next = oldarea;
((MCLink *)J->mcarea)->size = sz; ((MCLink *)area->base)->size = sz;
J->szallmcarea += sz; area->szall += sz;
} }
/* Free all MCode areas. */ /* Free an MCode areas. */
void lj_mcode_free(jit_State *J) void lj_mcode_free(jit_State *J, MCodeArea *area)
{ {
MCode *mc = J->mcarea; MCode *mc = area->base;
J->mcarea = NULL; area->base = NULL;
J->szallmcarea = 0; area->szall = 0;
while (mc) { while (mc) {
MCode *next = ((MCLink *)mc)->next; MCode *next = ((MCLink *)mc)->next;
mcode_free(J, mc, ((MCLink *)mc)->size); mcode_free(J, mc, ((MCLink *)mc)->size);
@ -306,26 +307,29 @@ void lj_mcode_free(jit_State *J)
/* Reserve the remainder of the current MCode area. */ /* Reserve the remainder of the current MCode area. */
MCode *lj_mcode_reserve(jit_State *J, MCode **lim) MCode *lj_mcode_reserve(jit_State *J, MCode **lim)
{ {
if (!J->mcarea) MCodeArea *area = J->curmcarea;
mcode_allocarea(J); if (!area->base)
mcode_allocarea(J, area);
else else
mcode_protect(J, MCPROT_GEN); mcode_protect(J, area, MCPROT_GEN);
*lim = J->mcbot; *lim = area->bot;
return J->mctop; return area->top;
} }
/* Commit the top part of the current MCode area. */ /* Commit the top part of the current MCode area. */
void lj_mcode_commit(jit_State *J, MCode *top) void lj_mcode_commit(jit_State *J, MCode *top)
{ {
J->mctop = top; MCodeArea *area = J->curmcarea;
mcode_protect(J, MCPROT_RUN); area->top = top;
mcode_protect(J, area, MCPROT_RUN);
} }
/* Abort the reservation. */ /* Abort the reservation. */
void lj_mcode_abort(jit_State *J) void lj_mcode_abort(jit_State *J)
{ {
if (J->mcarea) MCodeArea *area = J->curmcarea;
mcode_protect(J, MCPROT_RUN); if (area->base)
mcode_protect(J, area, MCPROT_RUN);
} }
/* Set/reset protection to allow patching of MCode areas. */ /* Set/reset protection to allow patching of MCode areas. */
@ -335,17 +339,18 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
UNUSED(J); UNUSED(ptr); UNUSED(finish); UNUSED(J); UNUSED(ptr); UNUSED(finish);
return NULL; return NULL;
#else #else
MCodeArea *area = J->curmcarea;
if (finish) { if (finish) {
if (J->mcarea == ptr) if (area->base == ptr)
mcode_protect(J, MCPROT_RUN); mcode_protect(J, area, MCPROT_RUN);
else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN)))
mcode_protfail(J); mcode_protfail(J);
return NULL; return NULL;
} else { } else {
MCode *mc = J->mcarea; MCode *mc = area->base;
/* Try current area first to use the protection cache. */ /* Try current area first to use the protection cache. */
if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) { if (ptr >= mc && ptr < (MCode *)((char *)mc + area->sz)) {
mcode_protect(J, MCPROT_GEN); mcode_protect(J, area, MCPROT_GEN);
return mc; return mc;
} }
/* Otherwise search through the list of MCode areas. */ /* Otherwise search through the list of MCode areas. */
@ -366,15 +371,16 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
void lj_mcode_limiterr(jit_State *J, size_t need) void lj_mcode_limiterr(jit_State *J, size_t need)
{ {
size_t sizemcode, maxmcode; size_t sizemcode, maxmcode;
MCodeArea *area = J->curmcarea;
lj_mcode_abort(J); lj_mcode_abort(J);
sizemcode = (size_t)J->param[JIT_P_sizemcode] << 10; sizemcode = (size_t)J->param[JIT_P_sizemcode] << 10;
sizemcode = (sizemcode + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1); sizemcode = (sizemcode + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1);
maxmcode = (size_t)J->param[JIT_P_maxmcode] << 10; maxmcode = (size_t)J->param[JIT_P_maxmcode] << 10;
if ((size_t)need > sizemcode) if ((size_t)need > sizemcode)
lj_trace_err(J, LJ_TRERR_MCODEOV); /* Too long for any area. */ lj_trace_err(J, LJ_TRERR_MCODEOV); /* Too long for any area. */
if (J->szallmcarea + sizemcode > maxmcode) if (area == &J->mcarea && area->szall + sizemcode > maxmcode)
lj_trace_err(J, LJ_TRERR_MCODEAL); lj_trace_err(J, LJ_TRERR_MCODEAL);
mcode_allocarea(J); mcode_allocarea(J, area);
lj_trace_err(J, LJ_TRERR_MCODELM); /* Retry with new area. */ lj_trace_err(J, LJ_TRERR_MCODELM); /* Retry with new area. */
} }

View File

@ -16,14 +16,14 @@ LJ_FUNC void lj_mcode_sync(void *start, void *end);
#include "lj_jit.h" #include "lj_jit.h"
LJ_FUNC void lj_mcode_free(jit_State *J); LJ_FUNC void lj_mcode_free(jit_State *J, MCodeArea *area);
LJ_FUNC MCode *lj_mcode_reserve(jit_State *J, MCode **lim); LJ_FUNC MCode *lj_mcode_reserve(jit_State *J, MCode **lim);
LJ_FUNC void lj_mcode_commit(jit_State *J, MCode *m); LJ_FUNC void lj_mcode_commit(jit_State *J, MCode *m);
LJ_FUNC void lj_mcode_abort(jit_State *J); LJ_FUNC void lj_mcode_abort(jit_State *J);
LJ_FUNC MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish); LJ_FUNC MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish);
LJ_FUNC_NORET void lj_mcode_limiterr(jit_State *J, size_t need); LJ_FUNC_NORET void lj_mcode_limiterr(jit_State *J, size_t need);
#define lj_mcode_commitbot(J, m) (J->mcbot = (m)) #define lj_mcode_commitbot(J, m) (J->curmcarea->bot = (m))
#endif #endif

View File

@ -294,7 +294,7 @@ int lj_trace_flushall(lua_State *L)
/* Clear penalty cache. */ /* Clear penalty cache. */
memset(J->penalty, 0, sizeof(J->penalty)); memset(J->penalty, 0, sizeof(J->penalty));
/* Free the whole machine code and invalidate all exit stub groups. */ /* Free the whole machine code and invalidate all exit stub groups. */
lj_mcode_free(J); lj_mcode_free(J, &J->mcarea);
memset(J->exitstubgroup, 0, sizeof(J->exitstubgroup)); memset(J->exitstubgroup, 0, sizeof(J->exitstubgroup));
lj_vmevent_send(L, TRACE, lj_vmevent_send(L, TRACE,
setstrV(L, L->top++, lj_str_newlit(L, "flush")); setstrV(L, L->top++, lj_str_newlit(L, "flush"));
@ -307,8 +307,8 @@ void lj_trace_initstate(global_State *g)
{ {
jit_State *J = G2J(g); jit_State *J = G2J(g);
TValue *tv; TValue *tv;
J->curmcarea = &J->mcarea;
/* Initialize aligned SIMD constants. */ /* Initialize SIMD constants. */
tv = LJ_KSIMD(J, LJ_KSIMD_ABS); tv = LJ_KSIMD(J, LJ_KSIMD_ABS);
tv[0].u64 = U64x(7fffffff,ffffffff); tv[0].u64 = U64x(7fffffff,ffffffff);
tv[1].u64 = U64x(7fffffff,ffffffff); tv[1].u64 = U64x(7fffffff,ffffffff);
@ -356,7 +356,7 @@ void lj_trace_freestate(global_State *g)
lua_assert(i == (ptrdiff_t)J->cur.traceno || traceref(J, i) == NULL); lua_assert(i == (ptrdiff_t)J->cur.traceno || traceref(J, i) == NULL);
} }
#endif #endif
lj_mcode_free(J); lj_mcode_free(J, &J->mcarea);
lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry); lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry);
lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot); lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot);
lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns); lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns);