lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

After implementing JIT backends using LLVM and libgccjit, now it is
time to try again!

LLVM is great at generating high performance machine code, but the
trouble with LLVM is that it is a huge beast. gcc's JIT library still
uses intermediate files for compilation ... so it is a JIT in name
only.

I have been trying to figure out a way to create a small JIT backend
that trades size for performance. Additionally, writing the backend in
IR is tedious and errorprone, so it would be better if the backend
could be written in a language such as C.

So now I am doing just that. The new backend is being written to
generate C code, which gets translated to machine code at runtime
using another project of mine - dmrC. Now dmrC supports two different
JIT engines - LLVM and NanoJIT. The support for NanoJIT is recent, and
not yet well tested. But what better way to test it than to use it for
Ravi?

I have only just started on this work, so only about 5 byte codes are
implemented so far. But still we can compile following:

x = function()
  local j
  for i=1,10 do
    for k = 0,5,5 do
      j = k
    end
  end
  return j
end

The generated C code looks like this:

int jitf3(lua_State *L) {
CallInfo *ci = L->ci;
StkId ra = NULL;
StkId rb = NULL;
StkId rc = NULL;
LClosure *cl = clLvalue(ci->func);
TValue *k = cl->p->k;
StkId base = ci->u.l.base;
int i_1 = 0;
int limit_1 = 0;
int i_5 = 0;
int limit_5 = 0;
int step_5 = 0;
int nres_0 = 0;
int nres_1 = 0;
ra = R(0);
setnilvalue(ra++);
ra = R(1);
setivalue(ra, 1);
ra = R(2);
setivalue(ra, 10);
ra = R(3);
setivalue(ra, 1);
ra = R(1);
i_1 = ivalue(ra);
ra = R(2);
limit_1 = ivalue(ra);
i_1 -= 1;
goto Lbc_11;
Lbc_5:
ra = R(5);
setivalue(ra, 0);
ra = R(6);
setivalue(ra, 5);
ra = R(7);
setivalue(ra, 5);
ra = R(5);
i_5 = ivalue(ra);
ra = R(6);
limit_5 = ivalue(ra);
ra = R(7);
step_5 = ivalue(ra);
i_5 -= step_5;
goto Lbc_10;
Lbc_9:
ra = R(0);
rb = R(8);
setobj2s(L, ra, rb);
Lbc_10:
i_5 += step_5;
if (i_5 <= limit_5) {
  ra = R(8);
  setivalue(ra, i_5);
  goto Lbc_9;
}
Lbc_11:
i_1 += 1;
if (i_1 <= limit_1) {
  ra = R(4);
  setivalue(ra, i_1);
  goto Lbc_5;
}
ra = R(0);
if (cl->p->sizep > 0) luaF_close(L, base);
nres_0 = (2 != 0 ? 2 - 1 : cast_int(L->top - ra));
return luaD_poscall(L, ci, ra, nres_0);
ra = R(0);
if (cl->p->sizep > 0) luaF_close(L, base);
nres_1 = (1 != 0 ? 1 - 1 : cast_int(L->top - ra));
return luaD_poscall(L, ci, ra, nres_1);
}