issue #163 'defer' implementation now controlled via RAVI_DEFER_STATEMENT macro. This allows testing of performance with and without the 'defer' statement

nometajit
Dibyendu Majumdar 4 years ago
parent ab9fb1f8fb
commit b8af71583d

@ -35,8 +35,12 @@
*/
struct UpVal {
TValue *v; /* points to stack or to its own value */
#ifdef RAVI_DEFER_STATEMENT
unsigned int refcount; /* reference counter */
unsigned int flags; /* Used to mark deferred values */
#else
lu_mem refcount; /* reference counter */
#endif
union {
struct { /* (when open) */
UpVal *next; /* linked list */
@ -54,7 +58,11 @@ LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
#ifdef RAVI_DEFER_STATEMENT
LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status);
#else
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
#endif
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
/* The additional type argument is a Ravi extension */
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,

@ -27,7 +27,11 @@ enum RESERVED {
/* terminal symbols denoted by reserved words */
TK_AND = FIRST_RESERVED, TK_BREAK,
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
#ifdef RAVI_DEFER_STATEMENT
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_DEFER, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
#else
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
#endif
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,

@ -280,13 +280,16 @@ OP_RAVI_GETFIELD, /* A B C R(A) := R(B)[RK(C)], string key */
OP_RAVI_SELF_SK, /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)], string key */
OP_RAVI_SETFIELD, /* A B C R(A)[RK(B)] := RK(C), string key */
OP_RAVI_GETTABUP_SK, /* A B C R(A) := UpValue[B][RK(C)], string key */
#ifdef RAVI_DEFER_STATEMENT
OP_RAVI_DEFER, /* A mark variable A "deferred" */
#endif
} OpCode;
#ifdef RAVI_DEFER_STATEMENT
#define NUM_OPCODES (cast(int, OP_RAVI_DEFER) + 1)
#else
#define NUM_OPCODES (cast(int, OP_RAVI_GETTABUP_SK) + 1)
#endif
/*===========================================================================
Notes:

@ -834,6 +834,8 @@
/* If following is defined as true then LLVM instructions emitted for arithmetic ops
priority floating point ops, else default is to prioritise integer ops */
#define RAVI_USE_LLVM_ARITH_FLOATPRIORITY 1
/* Enables the 'defer' statement - RAVI extension */
#define RAVI_DEFER_STATEMENT 1
#endif

@ -161,7 +161,9 @@ LUAI_FUNC void raviV_gettable_i(lua_State *L, const TValue *t, TValue *key, StkI
LUAI_FUNC void raviV_settable_i(lua_State *L, const TValue *t, TValue *key, StkId val);
LUAI_FUNC void raviV_op_totype(lua_State *L, TValue *ra, TValue *rb);
LUAI_FUNC int raviV_check_usertype(lua_State *L, TString *name, const TValue *o);
#ifdef RAVI_DEFER_STATEMENT
LUAI_FUNC void raviV_op_defer(lua_State *L, TValue *ra);
#endif
LUAI_FUNC void raviV_debug_trace(lua_State *L, int opCode, int pc);
#endif

@ -288,7 +288,9 @@ struct LuaLLVMTypes {
llvm::FunctionType *raviV_gettable_iT;
llvm::FunctionType *raviV_settable_iT;
llvm::FunctionType *raviV_op_totypeT;
#ifdef RAVI_DEFER_STATEMENT
llvm::FunctionType *raviV_op_deferT;
#endif
llvm::FunctionType *raviH_set_intT;
llvm::FunctionType *raviH_set_floatT;
@ -830,7 +832,9 @@ struct RaviFunctionDef {
llvm::Function *raviV_gettable_iF;
llvm::Function *raviV_settable_iF;
llvm::Function *raviV_op_totypeF;
#ifdef RAVI_DEFER_STATEMENT
llvm::Function *raviV_op_deferF;
#endif
// array setters
llvm::Function *raviH_set_intF;
@ -1373,7 +1377,9 @@ class RaviCodeGenerator {
void emit_BNOT(RaviFunctionDef *def, int A, int B, int pc);
#ifdef RAVI_DEFER_STATEMENT
void emit_DEFER(RaviFunctionDef *def, int A, int pc);
#endif
void emit_bitwise_shiftl(RaviFunctionDef *def, llvm::Value *ra, int B, lua_Integer y);

@ -1736,6 +1736,8 @@ compile(x)
assert(x(2,3) == 2^3)
print 'Test 77 OK'
--
-- Test defer statement
y = 0
function x()
@ -1836,6 +1838,8 @@ assert(z.count == 0)
assert(y == 1)
print 'Test 82 OK'
--
for k,v in pairs(opcodes_coverage)
do
print(k, v)

@ -681,7 +681,11 @@ static int recover (lua_State *L, int status) {
if (ci == NULL) return 0; /* no recovery point */
/* "finish" luaD_pcall */
oldtop = restorestack(L, ci->extra);
#ifdef RAVI_DEFER_STATEMENT
luaF_close(L, oldtop, status);
#else
luaF_close(L, oldtop);
#endif
luaD_seterrorobj(L, status, oldtop);
L->ci = ci;
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
@ -826,12 +830,18 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
status = luaD_rawrunprotected(L, func, u);
if (status != LUA_OK) { /* an error occurred? */
StkId oldtop = restorestack(L, old_top);
#ifndef RAVI_DEFER_STATEMENT
luaF_close(L, oldtop); /* close possible pending closures */
luaD_seterrorobj(L, status, oldtop);
#endif
L->ci = old_ci;
L->allowhook = old_allowhooks;
L->nny = old_nny;
#ifdef RAVI_DEFER_STATEMENT
status = luaF_close(L, oldtop, status); /* close possible pending closures */
oldtop = restorestack(L, old_top);
luaD_seterrorobj(L, status, oldtop);
#endif
luaD_shrinkstack(L);
}
L->errfunc = old_errfunc;

@ -68,15 +68,22 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
lua_assert(isintwups(L) || L->openupval == NULL);
while (*pp != NULL && (p = *pp)->v >= level) {
lua_assert(upisopen(p));
#ifdef RAVI_DEFER_STATEMENT
if (p->v == level && !p->flags) /* found a corresponding upvalue that is not a deferred value? */ {
return p; /* return it */
}
#else
if (p->v == level) /* found a corresponding upvalue? */
return p; /* return it */
#endif
pp = &p->u.open.next;
}
/* not found: create a new upvalue */
uv = luaM_new(L, UpVal);
uv->refcount = 0;
#ifdef RAVI_DEFER_STATEMENT
uv->flags = 0;
#endif
uv->u.open.next = *pp; /* link it to list of open upvalues */
uv->u.open.touched = 1;
*pp = uv;
@ -88,6 +95,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
return uv;
}
#ifdef RAVI_DEFER_STATEMENT
static void calldeferred(lua_State *L, void *ud) {
UNUSED(ud);
luaD_callnoyield(L, L->top - 2, 0);
@ -167,6 +175,22 @@ int luaF_close (lua_State *L, StkId level, int status) {
}
return status;
}
#else
void luaF_close (lua_State *L, StkId level) {
UpVal *uv;
while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
lua_assert(upisopen(uv));
L->openupval = uv->u.open.next; /* remove from 'open' list */
if (uv->refcount == 0) /* no references? */
luaM_free(L, uv); /* free upvalue */
else {
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
uv->v = &uv->u.value; /* now current value lives here */
luaC_upvalbarrier(L, uv);
}
}
}
#endif
Proto *luaF_newproto (lua_State *L) {

@ -40,7 +40,11 @@
static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "goto", "if",
#ifdef RAVI_DEFER_STATEMENT
"in", "local", "defer", "nil", "not", "or", "repeat",
#else
"in", "local", "nil", "not", "or", "repeat",
#endif
"return", "then", "true", "until", "while",
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "<eof>",

@ -164,7 +164,9 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"SELF_SK", /* _SK*/ /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
"SETFIELD", /*_SK */ /* A B C R(A)[RK(B)] := RK(C), string key */
"GETTABUP_SK",
#ifdef RAVI_DEFER_STATEMENT
"DEFER",
#endif
NULL
};
@ -306,9 +308,9 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_RAVI_SELF_SK */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETFIELD */
,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_RAVI_GETTABUP_SK */
#ifdef RAVI_DEFER_STATEMENT
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_DEFER */
#endif
};

@ -920,6 +920,7 @@ static Proto *addprototype (LexState *ls) {
** so that, if it invokes the GC, the GC knows which registers
** are in use at that time.
*/
#ifdef RAVI_DEFER_STATEMENT
static void codeclosure (LexState *ls, expdesc *v, int deferred) {
FuncState *fs = ls->fs->prev;
int pc = -1;
@ -933,6 +934,14 @@ static void codeclosure (LexState *ls, expdesc *v, int deferred) {
}
DEBUG_VARS(raviY_printf(ls->fs, "codeclosure -> closure created %e\n", v));
}
#else
static void codeclosure (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs->prev;
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TFUNCTION, NULL);
luaK_exp2nextreg(fs, v); /* fix it at the last register */
DEBUG_VARS(raviY_printf(ls->fs, "codeclosure -> closure created %e\n", v));
}
#endif
static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
@ -1290,7 +1299,7 @@ static void parlist (LexState *ls) {
}
}
#ifdef RAVI_DEFER_STATEMENT
static void body (LexState *ls, expdesc *e, int ismethod, int line, int deferred) {
/* body -> '(' parlist ')' block END */
FuncState new_fs;
@ -1313,6 +1322,28 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line, int deferred
codeclosure(ls, e, deferred);
close_func(ls);
}
#else
static void body (LexState *ls, expdesc *e, int ismethod, int line) {
/* body -> '(' parlist ')' block END */
FuncState new_fs;
BlockCnt bl;
new_fs.f = addprototype(ls);
new_fs.f->linedefined = line;
open_func(ls, &new_fs, &bl);
checknext(ls, '(');
if (ismethod) {
new_localvarliteral(ls, "self"); /* create 'self' parameter */
adjustlocalvars(ls, 1);
}
parlist(ls);
checknext(ls, ')');
statlist(ls);
new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
codeclosure(ls, e);
close_func(ls);
}
#endif
/* parse expression list */
static int explist (LexState *ls, expdesc *v) {
@ -1602,7 +1633,11 @@ static void simpleexp (LexState *ls, expdesc *v) {
}
case TK_FUNCTION: {
luaX_next(ls);
#ifdef RAVI_DEFER_STATEMENT
body(ls, v, 0, ls->linenumber, 0);
#else
body(ls, v, 0, ls->linenumber);
#endif
return;
}
default: {
@ -2187,6 +2222,7 @@ static void ifstat (LexState *ls, int line) {
}
/* parse a local function statement - called from statement() */
#ifdef RAVI_DEFER_STATEMENT
static void localfunc (LexState *ls, int defer) {
expdesc b = {.ravi_type = RAVI_TANY, .pc = -1};
FuncState *fs = ls->fs;
@ -2203,6 +2239,18 @@ static void localfunc (LexState *ls, int defer) {
/* debug information will only see the variable after this point! */
getlocvar(fs, b.u.info)->startpc = fs->pc;
}
#else
static void localfunc (LexState *ls) {
expdesc b = {.ravi_type = RAVI_TANY, .pc = -1};
FuncState *fs = ls->fs;
/* RAVI change - add type */
new_localvar(ls, str_checkname(ls), RAVI_TFUNCTION, NULL); /* new local variable */
adjustlocalvars(ls, 1); /* enter its scope */
body(ls, &b, 0, ls->linenumber); /* function created in next register */
/* debug information will only see the variable after this point! */
getlocvar(fs, b.u.info)->startpc = fs->pc;
}
#endif
/* parse a local variable declaration statement - called from statement() */
static void localstat (LexState *ls) {
@ -2262,7 +2310,11 @@ static void funcstat (LexState *ls, int line) {
luaX_next(ls); /* skip FUNCTION */
ismethod = funcname(ls, &v);
DEBUG_VARS(raviY_printf(ls->fs, "funcstat -> declaring function %e\n", &v));
#ifdef RAVI_DEFER_STATEMENT
body(ls, &b, ismethod, line, 0);
#else
body(ls, &b, ismethod, line);
#endif
luaK_storevar(ls->fs, &v, &b);
luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
}
@ -2355,16 +2407,22 @@ static void statement (LexState *ls) {
case TK_LOCAL: { /* stat -> localstat */
luaX_next(ls); /* skip LOCAL */
if (testnext(ls, TK_FUNCTION)) /* local function? */
#ifdef RAVI_DEFER_STATEMENT
localfunc(ls, 0);
#else
localfunc(ls);
#endif
else
localstat(ls);
break;
}
#ifdef RAVI_DEFER_STATEMENT
case TK_DEFER: { /* stat -> deferstat */
luaX_next(ls); /* skip DEFER */
localfunc(ls, 1);
break;
}
#endif
case TK_DBCOLON: { /* stat -> label */
luaX_next(ls); /* skip double colon */
labelstat(ls, str_checkname(ls), line);

@ -266,7 +266,11 @@ void *ravi_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize)
static void close_state (lua_State *L) {
global_State *g = G(L);
#ifdef RAVI_DEFER_STATEMENT
luaF_close(L, L->stack, -1); /* close all upvalues for this thread */
#else
luaF_close(L, L->stack); /* close all upvalues for this thread */
#endif
luaC_freeallobjects(L); /* collect all objects */
if (g->version) /* closing a fully built state? */
luai_userstateclose(L);
@ -313,7 +317,11 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
void luaE_freethread (lua_State *L, lua_State *L1) {
LX *l = fromstate(L1);
#ifdef RAVI_DEFER_STATEMENT
luaF_close(L1, L1->stack, -1); /* close all upvalues for this thread */
#else
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
#endif
lua_assert(L1->openupval == NULL);
luai_userstatefree(L, L1);
freestack(L1);

@ -1025,6 +1025,7 @@ void luaV_finishOp (lua_State *L) {
** Execute a jump instruction. The 'updatemask' allows signals to stop
** tight loops. (Without it, the local copy of 'mask' could never change.)
*/
#ifdef RAVI_DEFER_STATEMENT
#define dojump(ci, i, e) \
{ \
int a = GETARG_A(i); \
@ -1033,6 +1034,12 @@ void luaV_finishOp (lua_State *L) {
pc += GETARG_sBx(i) + e; \
updatemask(L); \
}
#else
#define dojump(ci,i,e) \
{ int a = GETARG_A(i); \
if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
pc += GETARG_sBx(i) + e; updatemask(L); }
#endif
/* for test instructions, execute the jump instruction that follows it */
#define donextjump(ci) { i = *pc; dojump(ci, i, 1); }
@ -1274,7 +1281,9 @@ int luaV_execute (lua_State *L) {
&&vmlabel(OP_RAVI_SELF_SK),
&&vmlabel(OP_RAVI_SETFIELD),
&&vmlabel(OP_RAVI_GETTABUP_SK),
#ifdef RAVI_DEFER_STATEMENT
&&vmlabel(OP_RAVI_DEFER),
#endif
};
#endif
@ -1717,8 +1726,12 @@ int luaV_execute (lua_State *L) {
StkId lim = nci->u.l.base + getproto(nfunc)->numparams;
int aux;
/* close all upvalues from previous call */
#ifdef RAVI_DEFER_STATEMENT
if (cl->p->sizep > 0)
Protect_base(luaF_close(L, oci->u.l.base, LUA_OK));
#else
if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);
#endif
/* move new frame into old one */
for (aux = 0; nfunc + aux < lim; aux++)
setobjs2s(L, ofunc + aux, nfunc + aux);
@ -1735,8 +1748,12 @@ int luaV_execute (lua_State *L) {
}
vmcase(OP_RETURN) {
int b = GETARG_B(i);
#ifdef RAVI_DEFER_STATEMENT
if (cl->p->sizep > 0)
Protect_base(luaF_close(L, base, LUA_OK));
#else
if (cl->p->sizep > 0) luaF_close(L, base);
#endif
savepc(L);
int nres = (b != 0 ? b - 1 : cast_int(L->top - ra));
b = luaD_poscall(L, ci, ra, nres);
@ -2494,12 +2511,14 @@ int luaV_execute (lua_State *L) {
}
vmbreak;
}
#ifdef RAVI_DEFER_STATEMENT
vmcase(OP_RAVI_DEFER) {
UpVal *up = luaF_findupval(L, ra); /* create new upvalue */
up->flags = 1; /* mark it as deferred */
setnilvalue(ra); /* initialize it with nil */
vmbreak;
}
#endif
}
}
}
@ -3032,6 +3051,7 @@ void raviV_op_totype(lua_State *L, TValue *ra, TValue *rb) {
luaG_runerror(L, "type mismatch: expected %s", getstr(key));
}
#ifdef RAVI_DEFER_STATEMENT
/*
** OP_RAVI_DEFER
*/
@ -3040,6 +3060,7 @@ void raviV_op_defer(lua_State *L, TValue *ra) {
up->flags = 1; /* mark it as deferred */
setnilvalue(ra); /* initialize it with nil */
}
#endif
/* }================================================================== */

@ -517,8 +517,12 @@ static const char Lua_header[] =
"};\n"
"struct UpVal {\n"
" TValue *v;\n"
#ifdef RAVI_DEFER_STATEMENT
" unsigned int refcount;\n"
" unsigned int flags;\n"
#else
" lu_mem refcount;\n"
#endif
" union {\n"
" struct {\n"
" UpVal *next;\n"
@ -547,7 +551,11 @@ static const char Lua_header[] =
" (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))\n"
"extern int luaV_tonumber_(const TValue *obj, lua_Number *n);\n"
"extern int luaV_tointeger(const TValue *obj, lua_Integer *p, int mode);\n"
#ifdef RAVI_DEFER_STATEMENT
"extern int luaF_close (lua_State *L, StkId level, int status);\n"
#else
"extern void luaF_close (lua_State *L, StkId level);\n"
#endif
"extern int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres);\n"
"extern int luaV_equalobj(lua_State *L, const TValue *t1, const TValue *t2);\n"
"extern int luaV_lessthan(lua_State *L, const TValue *l, const TValue *r);\n"
@ -583,7 +591,9 @@ static const char Lua_header[] =
"extern void raviV_settable_sskey(lua_State *L, const TValue *t, TValue *key, TValue *val);\n"
"extern void raviV_gettable_i(lua_State *L, const TValue *t, TValue *key, TValue *val);\n"
"extern void raviV_settable_i(lua_State *L, const TValue *t, TValue *key, TValue *val);\n"
#ifdef RAVI_DEFER_STATEMENT
"extern void raviV_op_defer(lua_State *L, TValue *ra);\n"
#endif
"extern lua_Integer luaV_shiftl(lua_Integer x, lua_Integer y);\n"
"extern void ravi_dump_value(lua_State *L, const struct lua_TValue *v);\n"
"extern void raviV_op_bnot(lua_State *L, TValue *ra, TValue *rb);\n"
@ -981,8 +991,12 @@ static void emit_comparison(struct function *fn, int A, int B, int C, int j, int
membuff_add_fstring(&fn->body, "if (result == %d) {\n", A);
if (jA > 0) {
membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1);
#ifdef RAVI_DEFER_STATEMENT
membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n");
membuff_add_string(&fn->body, " base = ci->u.l.base;\n");
#else
membuff_add_string(&fn->body, " luaF_close(L, ra);\n");
#endif
}
membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j);
membuff_add_string(&fn->body, "}\n");
@ -1021,9 +1035,13 @@ static void emit_op_loadk(struct function *fn, int A, int Bx, int pc) {
static void emit_op_return(struct function *fn, int A, int B, int pc) {
(void)pc;
emit_reg(fn, "ra", A);
#ifdef RAVI_DEFER_STATEMENT
membuff_add_string(&fn->body, "if (cl->p->sizep > 0) {\n luaF_close(L, base, LUA_OK);\n");
membuff_add_string(&fn->body, " base = ci->u.l.base;\n");
membuff_add_string(&fn->body, "}\n");
#else
membuff_add_string(&fn->body, "if (cl->p->sizep > 0) luaF_close(L, base);\n");
#endif
membuff_add_fstring(&fn->body, "result = (%d != 0 ? %d - 1 : cast_int(L->top - ra));\n", B, B);
membuff_add_string(&fn->body, "return luaD_poscall(L, ci, ra, result);\n");
}
@ -1048,8 +1066,12 @@ static void emit_op_jmp(struct function *fn, int A, int sBx, int pc) {
(void)pc;
if (A > 0) {
membuff_add_fstring(&fn->body, "ra = R(%d);\n", A - 1);
#ifdef RAVI_DEFER_STATEMENT
membuff_add_string(&fn->body, "luaF_close(L, ra, LUA_OK);\n");
membuff_add_string(&fn->body, "base = ci->u.l.base;\n");
#else
membuff_add_string(&fn->body, "luaF_close(L, ra);\n");
#endif
}
membuff_add_fstring(&fn->body, "goto Lbc_%d;\n", sBx);
}
@ -1077,8 +1099,12 @@ static void emit_op_test(struct function *fn, int A, int B, int C, int j, int jA
membuff_add_fstring(&fn->body, "if (!result) {\n", A);
if (jA > 0) {
membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1);
#ifdef RAVI_DEFER_STATEMENT
membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n");
membuff_add_string(&fn->body, " base = ci->u.l.base;\n");
#else
membuff_add_string(&fn->body, " luaF_close(L, ra);\n");
#endif
}
membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j);
membuff_add_string(&fn->body, " }\n");
@ -1098,8 +1124,12 @@ static void emit_op_testset(struct function *fn, int A, int B, int C, int j, int
membuff_add_string(&fn->body, " setobjs2s(L, ra, rb);");
if (jA > 0) {
membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1);
#ifdef RAVI_DEFER_STATEMENT
membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n");
membuff_add_string(&fn->body, " base = ci->u.l.base;\n");
#else
membuff_add_string(&fn->body, " luaF_close(L, ra);\n");
#endif
}
membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j);
membuff_add_string(&fn->body, " }\n");
@ -1342,11 +1372,13 @@ static void emit_op_divii(struct function *fn, int A, int B, int C, int pc) {
"(lua_Number)(ivalue(rc)));\n");
}
#ifdef RAVI_DEFER_STATEMENT
static void emit_op_defer(struct function *fn, int A, int pc) {
(void)pc;
emit_reg(fn, "ra", A);
membuff_add_string(&fn->body, "raviV_op_defer(L, ra);\n");
}
#endif
static void emit_op_loadfz(struct function *fn, int A, int pc) {
(void)pc;
@ -2210,9 +2242,11 @@ bool raviJ_codegen(struct lua_State *L, struct Proto *p, struct ravi_compile_opt
int B = GETARG_B(i);
emit_op_len(&fn, A, B, pc);
} break;
#ifdef RAVI_DEFER_STATEMENT
case OP_RAVI_DEFER: {
emit_op_defer(&fn, A, pc);
} break;
#endif
case OP_RAVI_SHR_II:
case OP_RAVI_SHL_II:
case OP_RAVI_BXOR_II:

@ -51,10 +51,14 @@ void RaviCodeGenerator::emit_JMP(RaviFunctionDef *def, int A, int sBx, int pc) {
emit_load_base(def);
// base + a - 1
llvm::Value *val = emit_gep_register(def, A - 1);
#ifdef RAVI_DEFER_STATEMENT
if (!traced)
emit_update_savedpc(def, pc);
// Call luaF_close
CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
#else
CreateCall2(def->builder, def->luaF_closeF, def->L, val);
#endif
}
// Do the actual jump
@ -173,11 +177,13 @@ void RaviCodeGenerator::emit_CALL(RaviFunctionDef *def, int A, int B, int C,
def->builder->SetInsertPoint(end_block);
}
#ifdef RAVI_DEFER_STATEMENT
void RaviCodeGenerator::emit_DEFER(RaviFunctionDef *def, int A, int pc) {
emit_debug_trace(def, OP_RAVI_DEFER, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
CreateCall2(def->builder, def->raviV_op_deferF, def->L, ra);
}
#endif
}

@ -1204,10 +1204,11 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
def->raviV_op_totypeF = def->raviF->addExternFunction(
def->types->raviV_op_totypeT, reinterpret_cast<void *>(&raviV_op_totype),
"raviV_op_totype");
#ifdef RAVI_DEFER_STATEMENT
def->raviV_op_deferF = def->raviF->addExternFunction(
def->types->raviV_op_deferT, reinterpret_cast<void *>(&raviV_op_defer),
"raviV_op_defer");
#endif
#if 0
// DEBUG routines
def->ravi_dump_valueF = def->raviF->addExternFunction(
@ -1337,7 +1338,11 @@ llvm::Value *RaviCodeGenerator::emit_gep_upval_v(RaviFunctionDef *def,
// Get &upval->value -> result is TValue *
llvm::Value *RaviCodeGenerator::emit_gep_upval_value(
RaviFunctionDef *def, llvm::Instruction *pupval) {
#ifdef RAVI_DEFER_STATEMENT
return emit_gep(def, "value", pupval, 0, 3);
#else
return emit_gep(def, "value", pupval, 0, 2);
#endif
}
// Alternative code generator uses dmrC based C front-end
@ -2022,9 +2027,11 @@ bool RaviCodeGenerator::compile(lua_State *L, Proto *p,
int B = GETARG_B(i);
emit_UNM(def, A, B, pc);
} break;
#ifdef RAVI_DEFER_STATEMENT
case OP_RAVI_DEFER: {
emit_DEFER(def, A, pc);
} break;
#endif
default: {
fprintf(stderr, "Unexpected bytecode %d\n", op);
abort();

@ -131,10 +131,14 @@ void RaviCodeGenerator::emit_EQ(RaviFunctionDef *def, int A, int B, int C,
// base + a - 1
llvm::Value *val = emit_gep_register(def, jA - 1);
#ifdef RAVI_DEFER_STATEMENT
if (!traced)
emit_update_savedpc(def, pc);
// Call luaF_close
CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
#else
CreateCall2(def->builder, def->luaF_closeF, def->L, val);
#endif
}
// Do the jump
def->builder->CreateBr(def->jmp_targets[j].jmp1);
@ -238,10 +242,14 @@ void RaviCodeGenerator::emit_TEST(RaviFunctionDef *def, int A, int B, int C,
// base + a - 1
llvm::Value *val = emit_gep_register(def, jA - 1);
#ifdef RAVI_DEFER_STATEMENT
if (!traced)
emit_update_savedpc(def, pc);
// Call luaF_close
CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
#else
CreateCall2(def->builder, def->luaF_closeF, def->L, val);
#endif
}
// Do the jump
def->builder->CreateBr(def->jmp_targets[j].jmp1);
@ -311,10 +319,14 @@ void RaviCodeGenerator::emit_TESTSET(RaviFunctionDef *def, int A, int B, int C,
// base + a - 1
llvm::Value *val = emit_gep_register(def, jA - 1);
#ifdef RAVI_DEFER_STATEMENT
if (!traced)
emit_update_savedpc(def, pc);
// Call luaF_close
CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
#else
CreateCall2(def->builder, def->luaF_closeF, def->L, val);
#endif
}
// Do the jump
def->builder->CreateBr(def->jmp_targets[j].jmp1);

@ -56,6 +56,14 @@ void RaviCodeGenerator::emit_RETURN(RaviFunctionDef *def, int A, int B,
bool traced = emit_debug_trace(def, OP_RETURN, pc);
#ifndef RAVI_DEFER_STATEMENT
// Load pointer to base
emit_load_base(def);
// Get pointer to register A
llvm::Value *ra_ptr = emit_gep_register(def, A);
#endif
// if (cl->p->sizep > 0) luaF_close(L, base);
// Get pointer to Proto->sizep
llvm::Instruction *psize = emit_load_proto_sizep(def);
@ -70,22 +78,28 @@ void RaviCodeGenerator::emit_RETURN(RaviFunctionDef *def, int A, int B,
def->builder->CreateCondBr(psize_gt_0, then_block, else_block);
def->builder->SetInsertPoint(then_block);
#ifdef RAVI_DEFER_STATEMENT
// Load pointer to base
emit_load_base(def);
// Get pointer to register A
llvm::Value *ra_ptr = emit_gep_register(def, A);
if (!traced)
emit_update_savedpc(def, pc);
#endif
// Call luaF_close
#ifdef RAVI_DEFER_STATEMENT
CreateCall3(def->builder, def->luaF_closeF, def->L, def->base_ptr, def->types->kInt[LUA_OK]);
#else
CreateCall2(def->builder, def->luaF_closeF, def->L, def->base_ptr);
#endif
def->builder->CreateBr(else_block);
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
#ifdef RAVI_DEFER_STATEMENT
emit_load_base(def); // As luaF_close() may have changed the stack
ra_ptr = emit_gep_register(def, A); // load RA
#endif
//* b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
llvm::Value *nresults = NULL;
if (B != 0)

@ -694,8 +694,12 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
// struct UpVal {
// struct TValue *v; /* points to stack or to its own value */
#ifdef RAVI_DEFER_STATEMENT
// unsigned int refcount; /* reference counter */
// unsigned int flags; /* Used to mark deferred values */
#else
// unsigned long long refcount; /* reference counter */
#endif
// union {
// struct { /* (when open) */
// struct UpVal *next; /* linked list */
@ -706,8 +710,12 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
//};
elements.clear();
elements.push_back(pTValueT);
#ifdef RAVI_DEFER_STATEMENT
elements.push_back(C_intT);
elements.push_back(C_intT);
#else
elements.push_back(C_size_t);
#endif
elements.push_back(TValueT);
UpValT->setBody(elements);
@ -747,22 +755,31 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(plua_StateT);
luaV_executeT = llvm::FunctionType::get(C_intT, elements, false);
#ifdef RAVI_DEFER_STATEMENT
// int luaF_close (lua_State *L, StkId level, int status)
#else
// void luaF_close (lua_State *L, StkId level)
#endif
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(StkIdT);
#ifdef RAVI_DEFER_STATEMENT
elements.push_back(C_intT);
luaF_closeT =
llvm::FunctionType::get(C_intT, elements, false);
#else
luaF_closeT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
#endif
// int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2)
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(pTValueT);
#ifdef RAVI_DEFER_STATEMENT
// void raviV_op_defer(lua_State *L, TValue *ra);
raviV_op_deferT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
#endif
elements.push_back(pTValueT);
luaV_equalobjT = llvm::FunctionType::get(C_intT, elements, false);
@ -1266,8 +1283,12 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
nodes.clear();
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_pointerT, 0));
#ifdef RAVI_DEFER_STATEMENT
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_intT, 4));
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_intT, 4));
#else
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_longlongT, 8));
#endif
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_TValueT, 16));
tbaa_UpValT = mdbuilder.createTBAAStructTypeNode("UpVal", nodes);
tbaa_UpVal_vT =

@ -111,7 +111,9 @@ static LuaFunc Lua_functions[] = {
{ "raviV_settable_sskey", raviV_settable_sskey },
{ "raviV_gettable_i", raviV_gettable_i },
{ "raviV_settable_i", raviV_settable_i },
#ifdef RAVI_DEFER_STATEMENT
{ "raviV_op_defer", raviV_op_defer },
#endif
{ "raviV_op_bnot", raviV_op_bnot},
{ "lua_absindex", lua_absindex },

@ -319,8 +319,10 @@ int raviV_initjit(struct lua_State *L) {
register_builtin_arg2(jit->jit, "lua_setmetatable", lua_setmetatable, JIT_Int32, JIT_Address, JIT_Int32);
//LUA_API void (lua_setuservalue)(lua_State *L, int idx);
register_builtin_arg2(jit->jit, "lua_setuservalue", lua_setuservalue, JIT_NoType, JIT_Address, JIT_Int32);
#ifdef RAVI_DEFER_STATEMENT
//LUA_API void raviV_op_defer(lua_State *L, TValue *ra);
register_builtin_arg2(jit->jit, "raviV_op_defer", raviV_op_defer, JIT_NoType, JIT_Address, JIT_Address);
#endif
//LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
register_builtin_arg2(jit->jit, "luaV_shiftl", luaV_shiftl, JIT_Int64, JIT_Int64, JIT_Int64);
// extern void raviV_op_bnot(lua_State *L, TValue *ra, TValue *rb);

Loading…
Cancel
Save