From 6523585c66c04cea54df50013df8886b589847d8 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 23 Jan 2012 23:36:30 +1000 Subject: Add luaproc and LuaJIT libraries. Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly. --- libraries/LuaJIT-1.1.7/src/ljit_backend.c | 342 ++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 libraries/LuaJIT-1.1.7/src/ljit_backend.c (limited to 'libraries/LuaJIT-1.1.7/src/ljit_backend.c') diff --git a/libraries/LuaJIT-1.1.7/src/ljit_backend.c b/libraries/LuaJIT-1.1.7/src/ljit_backend.c new file mode 100644 index 0000000..698342f --- /dev/null +++ b/libraries/LuaJIT-1.1.7/src/ljit_backend.c @@ -0,0 +1,342 @@ +/* +** LuaJIT wrapper for architecture-specific compiler backend. +** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h +*/ + +#include +#include + +#define ljit_backend_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" +#include "lopcodes.h" +#include "ldebug.h" +#include "lzio.h" + +#include "ljit.h" +#include "ljit_hints.h" +#include "ljit_dasm.h" + +/* ------------------------------------------------------------------------ */ + +/* Get target of combined JMP op. */ +static int jit_jmp_target(jit_State *J) +{ + J->combine++; + jit_assert(GET_OPCODE(*J->nextins)==OP_JMP); + return J->nextpc + 1 + GETARG_sBx(*J->nextins); +} + +/* ------------------------------------------------------------------------ */ + +/* Include pre-processed architecture-specific backend. */ +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) +#ifndef LUA_NUMBER_DOUBLE +#error "No support for other number types on x86 (yet)" +#endif +#include "ljit_x86.h" +#else +#error "No support for this architecture (yet)" +#endif + +/* ------------------------------------------------------------------------ */ + +/* Compile instruction range. */ +static void jit_compile_irange(jit_State *J, int firstpc, int lastpc) +{ + J->combine = 0; + J->nextpc = firstpc; + J->nextins = J->pt->code + (firstpc-1); + while (J->nextpc <= lastpc) { + Instruction ins = *J->nextins++; + OpCode op = GET_OPCODE(ins); + int ra = GETARG_A(ins); + int rb = GETARG_B(ins); + int rc = GETARG_C(ins); + int rbx = GETARG_Bx(ins); + const TValue *combinehint; + + jit_ins_start(J); + J->nextpc++; + + combinehint = hint_get(J, COMBINE); + if (ttisboolean(combinehint)) { + if (bvalue(combinehint)) { /* COMBINE = true: combine with next ins. */ + if (!(J->flags & JIT_F_DEBUG)) /* But not when debugging. */ + J->combine = 1; + } else { /* COMBINE = false: dead instruction. */ + *J->mfm++ = JIT_MFM_DEAD; + continue; + } + } /* Other COMBINE hint value types are not defined (yet). */ + + if (J->flags & JIT_F_DEBUG_INS) + jit_ins_debug(J, luaG_checkopenop(ins)); + + switch (op) { + case OP_MOVE: jit_op_move(J, ra, rb); break; + case OP_LOADK: jit_op_loadk(J, ra, rbx); break; + case OP_LOADBOOL: jit_op_loadbool(J, ra, rb, rc); break; + case OP_LOADNIL: jit_op_loadnil(J, ra, rb); break; + + case OP_GETUPVAL: jit_op_getupval(J, ra, rb); break; + case OP_SETUPVAL: jit_op_setupval(J, ra, rb); break; + + case OP_GETGLOBAL: jit_op_getglobal(J, ra, rbx); break; + case OP_SETGLOBAL: jit_op_setglobal(J, ra, rbx); break; + + case OP_NEWTABLE: jit_op_newtable(J, ra, rb, rc); break; + case OP_GETTABLE: jit_op_gettable(J, ra, rb, rc); break; + case OP_SETTABLE: jit_op_settable(J, ra, rb, rc); break; + case OP_SELF: jit_op_self(J, ra, rb, rc); break; + case OP_SETLIST: jit_op_setlist(J, ra, rb, rc); break; + + case OP_ADD: jit_op_arith(J, ra, rb, rc, TM_ADD); break; + case OP_SUB: jit_op_arith(J, ra, rb, rc, TM_SUB); break; + case OP_MUL: jit_op_arith(J, ra, rb, rc, TM_MUL); break; + case OP_DIV: jit_op_arith(J, ra, rb, rc, TM_DIV); break; + case OP_MOD: jit_op_arith(J, ra, rb, rc, TM_MOD); break; + case OP_POW: jit_op_arith(J, ra, rb, rc, TM_POW); break; + case OP_UNM: jit_op_arith(J, ra, rb, rb, TM_UNM); break; /* rc unused. */ + + case OP_LEN: jit_op_len(J, ra, rb); break; + case OP_NOT: jit_op_not(J, ra, rb); break; + + case OP_CONCAT: jit_op_concat(J, ra, rb, rc); break; + + case OP_EQ: jit_op_eq(J, ra, rb, rc); break; + case OP_LT: jit_op_arith(J, ra, rb, rc, TM_LT); break; + case OP_LE: jit_op_arith(J, ra, rb, rc, TM_LE); break; + + case OP_TEST: jit_op_test(J, rc, ra, ra); break; + case OP_TESTSET: jit_op_test(J, rc, ra, rb); break; + + case OP_JMP: jit_op_jmp(J, J->nextpc + rbx-MAXARG_sBx); break; + + case OP_CALL: jit_op_call(J, ra, rb-1, rc-1); break; + case OP_TAILCALL: jit_op_tailcall(J, ra, rb-1); break; + case OP_RETURN: jit_op_return(J, ra, rb-1); break; + + case OP_FORLOOP: jit_op_forloop(J, ra, J->nextpc + rbx-MAXARG_sBx); break; + case OP_FORPREP: jit_op_forprep(J, ra, J->nextpc + rbx-MAXARG_sBx); break; + + case OP_TFORLOOP: jit_op_tforloop(J, ra, rc); break; + + case OP_CLOSE: jit_op_close(J, ra); break; + case OP_CLOSURE: jit_op_closure(J, ra, rbx); break; + + case OP_VARARG: jit_op_vararg(J, ra, rb-1); break; + + default: jit_assert(0); break; + } + + /* Convention: all opcodes start and end with the .code section. */ + if (dasm_checkstep(Dst, DASM_SECTION_CODE)) { J->nextpc--; return; } + + *J->mfm++ = 0; /* Placeholder mfm entry. Replaced later. */ + if (J->combine > 0) { /* Combine next J->combine ins with prev ins. */ + J->nextpc += J->combine; + J->nextins += J->combine; + do { *J->mfm++ = JIT_MFM_COMBINE; } while (--J->combine); + } + } +} + +/* Merge temporary mfm (forward) with PC labels to inverse mfm in mcode. */ +static void jit_mfm_merge(jit_State *J, jit_Mfm *from, jit_Mfm *to, int maxpc) +{ + int pc = 1, ofs = 0; + for (;;) { + int m = *from++; + if (m & JIT_MFM_MARK) { + switch (m) { + default: pc = m ^ JIT_MFM_MARK; break; + case JIT_MFM_COMBINE: case JIT_MFM_DEAD: break; + case JIT_MFM_STOP: return; + } + } else { + int idx, nofs; + for (idx = 0; from[idx] == JIT_MFM_COMBINE; idx++) ; + idx += pc; + if (idx == J->nextpc) idx = maxpc + 1; + nofs = dasm_getpclabel(Dst, idx); + m = nofs - ofs; + ofs = nofs; + jit_assert(nofs >= 0 && m >= 0 && m < JIT_MFM_MAX); + } + pc++; + *to-- = m; + } +} + +/* Compile function prototype. */ +static int jit_compile_proto(jit_State *J, Table *deopt) +{ + jit_Mfm *tempmfm; + void *mcode; + size_t sz; + int firstpc = 0, maxpc = J->pt->sizecode; + int deoptidx = 1; + int status; + /* (Ab)use the global string concatenation buffer for the temporary mfm. */ + /* Caveat: the GC must not be run while the backend is active. */ + tempmfm = (jit_Mfm *)luaZ_openspace(J->L, &G(J->L)->buff, + (1+maxpc+1+1+1)*sizeof(jit_Mfm)); +nextdeopt: + J->mfm = tempmfm; + J->tflags = 0; + /* Setup DynASM. */ + dasm_growpc(Dst, 1+maxpc+2); /* See jit_ins_last(). */ + dasm_setup(Dst, jit_actionlist); + if (deopt) { /* Partial deoptimization. */ + /* TODO: check deopt chain length? problem: pairs TFOR_CTL migration. */ + int pc, lastpc; + lua_Number n; + const TValue *obj = luaH_getnum(deopt, deoptidx++); + if (ttisnil(obj) && deoptidx != 2) return JIT_S_OK; + if (!ttisnumber(obj)) return JIT_S_COMPILER_ERROR; + n = nvalue(obj); + lua_number2int(pc, n); + firstpc = JIT_IH_IDX(pc); + lastpc = firstpc + JIT_IH_LIB(pc); + if (firstpc < 1 || firstpc > maxpc || lastpc > maxpc || + J->pt->jit_szmcode == 0) + return JIT_S_COMPILER_ERROR; + *J->mfm++ = JIT_MFM_MARK+firstpc; /* Seek to firstpc. */ + jit_compile_irange(J, firstpc, lastpc); + jit_assert(J->nextpc == lastpc+1); /* Problem with combined ins? */ + if (J->nextpc <= maxpc) jit_ins_chainto(J, J->nextpc); + *J->mfm++ = JIT_MFM_MARK+maxpc+1; /* Seek to .deopt/.tail. */ + for (pc = 1; pc <= maxpc; pc++) + if (dasm_getpclabel(Dst, pc) == -1) { /* Undefind label referenced? */ + jit_ins_setpc(J, pc, luaJIT_findmcode(J->pt, pc)); /* => Old mcode. */ + } + } else { /* Full compile. */ + *J->mfm++ = 0; /* Placeholder mfm entry for prologue. */ + jit_prologue(J); + jit_compile_irange(J, 1, maxpc); + } + *J->mfm++ = 0; /* Placeholder mfm entry for .deopt/.tail. */ + *J->mfm = JIT_MFM_STOP; + jit_ins_last(J, maxpc, (char *)J->mfm - (char *)tempmfm); + + status = luaJIT_link(J, &mcode, &sz); + if (status != JIT_S_OK) + return status; + + jit_mfm_merge(J, tempmfm, JIT_MCMFM(mcode, sz), maxpc); + + if (deopt) { + jit_MCTrailer tr; + /* Patch first instruction to jump to the deoptimized code. */ + jit_patch_jmp(J, luaJIT_findmcode(J->pt, firstpc), mcode); + /* Mark instruction as deoptimized in main mfm. */ + JIT_MCMFM(J->pt->jit_mcode, J->pt->jit_szmcode)[-firstpc] |= JIT_MFM_MARK; + /* Chain deopt mcode block between main mfm and existing mfms. */ + memcpy(JIT_MCTRAILER(mcode, sz), + JIT_MCTRAILER(J->pt->jit_mcode, J->pt->jit_szmcode), + sizeof(jit_MCTrailer)); + tr.mcode = (char *)mcode; + tr.sz = sz; + memcpy(JIT_MCTRAILER(J->pt->jit_mcode, J->pt->jit_szmcode), (void *)&tr, + sizeof(jit_MCTrailer)); + goto nextdeopt; + } + + if (J->pt->jit_szmcode != 0) { /* Full recompile? */ + jit_MCTrailer tr; + /* Patch old mcode entry so other closures get the new callgate. */ + jit_patch_jmp(J, J->pt->jit_mcode, J->jsub[JSUB_GATE_JL]); + /* Chain old main mfm after new main mfm. */ + tr.mcode = (char *)J->pt->jit_mcode; + tr.sz = J->pt->jit_szmcode; + memcpy(JIT_MCTRAILER(mcode, sz), (void *)&tr, sizeof(jit_MCTrailer)); + } + /* Set new main mcode block. */ + J->pt->jit_mcode = mcode; + J->pt->jit_szmcode = sz; + return JIT_S_OK; +} + +/* ------------------------------------------------------------------------ */ + +/* Compiler backend. */ +int luaJIT_backend(lua_State *L) +{ + jit_State *J = G(L)->jit_state; + const TValue *cl; + int status = JIT_S_COMPILER_ERROR; + lua_lock(L); + /* Remember compiler state table. */ + jit_assert(L->top > L->base && ttistable(L->top-1)); + J->comstate = hvalue(L->top-1); + /* Fetch prototoype. Better check this in case some handler screwed up. */ + cl = luaH_getstr(J->comstate, luaS_newliteral(L, "func")); + if (isLfunction(cl)) { + J->pt = clvalue(cl)->l.p; + if (J->pt->sizecode > LUAJIT_LIM_BYTECODE) { /* Hard backend limit. */ + status = JIT_S_TOOLARGE; + } else { + const TValue *obj = luaH_getstr(J->comstate, + luaS_newliteral(J->L, "deopt")); + status = jit_compile_proto(J, ttistable(obj) ? hvalue(obj) : (Table *)0); + } + } + lua_unlock(L); + J->comstate = NULL; /* Just in case. */ + J->pt = NULL; + if (status == JIT_S_OK) { + return 0; + } else { + if (status == JIT_S_DASM_ERROR) { + lua_pushinteger(L, J->nextpc); + lua_setfield(L, 1, "dasm_pc"); + lua_pushinteger(L, J->dasmstatus); + lua_setfield(L, 1, "dasm_err"); + } + lua_pushinteger(L, status); + return 1; + } +} + +/* Initialize compiler backend. */ +int luaJIT_initbackend(lua_State *L) +{ + jit_State *J = G(L)->jit_state; + J->L = L; + J->pt = NULL; /* Not in use. */ + J->D = NULL; + J->mcodeheap = NULL; + J->jsubmcode = NULL; + J->szjsubmcode = 0; + J->numjsub = JSUB__MAX; + J->jsub = luaM_newvector(J->L, JSUB__MAX, void *); + memset((void *)J->jsub, 0, JSUB__MAX*sizeof(void *)); /* Just in case. */ + dasm_init(Dst, DASM_MAXSECTION); + dasm_setupglobal(Dst, J->jsub, JSUB__MAX); + return jit_compile_jsub(J); +} + +/* Free compiler backend. */ +void luaJIT_freebackend(lua_State *L) +{ + jit_State *J = G(L)->jit_state; + J->L = L; + if (J->jsub) luaM_freearray(L, J->jsub, JSUB__MAX, void *); + luaJIT_freemcodeheap(J); /* Frees JSUB mcode, too. */ + dasm_free(Dst); +} + +/* ------------------------------------------------------------------------ */ + -- cgit v1.1