/* Free all MCode areas. */ void lj_mcode_free(jit_State *J) { MCode *mc = J->mcarea; J->mcarea = NULL; J->szallmcarea = 0; while (mc) { MCode *next = ((MCLink *)mc)->next; mcode_free(J, mc, ((MCLink *)mc)->size); mc = next; } }
/* All memory addresses are reachable by relative jumps. */ static void *mcode_alloc(jit_State *J, size_t sz) { #ifdef __OpenBSD__ /* Allow better executable memory allocation for OpenBSD W^X mode. */ void *p = mcode_alloc_at(J, 0, sz, MCPROT_RUN); if (p && mcode_setprot(p, sz, MCPROT_GEN)) { mcode_free(J, p, sz); return NULL; } return p; #else return mcode_alloc_at(J, 0, sz, MCPROT_GEN); #endif }
/* Link generated code. Return mcode address, size and status. */ int luaJIT_link(jit_State *J, void **mcodep, size_t *szp) { size_t sz; void *mcode; /* Pass 2: link sections. */ if ((J->dasmstatus = dasm_link(Dst, &sz))) return JIT_S_DASM_ERROR; /* Check for hardcoded limit on mcode size. */ if (sz > LUAJIT_LIM_MCODE) return JIT_S_TOOLARGE; /* TODO: mark mcode readonly when we're done. */ mcode = mcode_alloc(J, sz); /* Pass 3: encode sections. */ if ((J->dasmstatus = dasm_encode(Dst, mcode))) { mcode_free(J->L, J, mcode, sz); return JIT_S_DASM_ERROR; } *mcodep = mcode; *szp = sz; return JIT_S_OK; }
/* Get memory within relative jump distance of our code in 64 bit mode. */ 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 & 0xf0000000u) + 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. */ uintptr_t hint = J->mcarea ? (uintptr_t)J->mcarea - sz : 0; int i; /* Limit probing iterations, depending on the available pool size. */ for (i = 0; i < LJ_TARGET_JUMPRANGE; i++) { if (mcode_validptr(hint)) { 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)) return p; if (p) mcode_free(J, p, sz); /* Free badly placed area. */ } /* Next try probing 64K-aligned pseudo-random addresses. */ do { hint = LJ_PRNG_BITS(J, LJ_TARGET_JUMPRANGE-16) << 16; } while (!(hint + sz < range+range)); hint = target + hint - range; } lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */ return NULL; }