issue #60 explore further optimization of table operations

pull/81/head
Dibyendu Majumdar 9 years ago
parent 4115f35867
commit 55df8ea9cd

@ -442,11 +442,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
op = OP_RAVI_GETTABLE_AF; op = OP_RAVI_GETTABLE_AF;
else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_type == RAVI_TNUMINT) else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_type == RAVI_TNUMINT)
op = OP_RAVI_GETTABLE_AI; op = OP_RAVI_GETTABLE_AI;
else else {
op = OP_GETTABLE; if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TSTRING)
op = OP_RAVI_GETTABLES;
else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TNUMINT)
op = OP_RAVI_GETTABLEI;
else
op = OP_GETTABLE;
}
if (e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TARRAYINT) if (e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TARRAYINT)
/* set the type of resulting expression */ /* set the type of resulting expression */
e->ravi_type = e->ravi_type == RAVI_TARRAYFLT ? RAVI_TNUMFLT : RAVI_TNUMINT; e->ravi_type = e->ravi_type == RAVI_TARRAYFLT ? RAVI_TNUMFLT : RAVI_TNUMINT;
else
e->ravi_type = RAVI_TANY;
} }
e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
e->k = VRELOCABLE; e->k = VRELOCABLE;
@ -516,6 +524,9 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
case RAVI_TARRAYFLT: case RAVI_TARRAYFLT:
luaK_codeABC(fs, OP_RAVI_MOVEAF, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVEAF, reg, e->u.info, 0);
break; break;
case RAVI_TTABLE:
luaK_codeABC(fs, OP_RAVI_MOVETAB, reg, e->u.info, 0);
break;
default: default:
luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
break; break;
@ -638,7 +649,12 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
/* VNONRELOC means we have fixed register and do we know the type? */ /* VNONRELOC means we have fixed register and do we know the type? */
if (ex->k == VNONRELOC && (var->ravi_type == RAVI_TNUMFLT || var->ravi_type == RAVI_TNUMINT || var->ravi_type == RAVI_TARRAYFLT || var->ravi_type == RAVI_TARRAYINT)) { if (ex->k == VNONRELOC &&
(var->ravi_type == RAVI_TNUMFLT ||
var->ravi_type == RAVI_TNUMINT ||
var->ravi_type == RAVI_TARRAYFLT ||
var->ravi_type == RAVI_TARRAYINT ||
var->ravi_type == RAVI_TTABLE)) {
/* handled by MOVEI, MOVEF, MOVEAI, MOVEAF at runtime */ /* handled by MOVEI, MOVEF, MOVEAI, MOVEAF at runtime */
return; return;
} }
@ -668,7 +684,9 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
var->ravi_type, var->ravi_type,
ex->ravi_type)); ex->ravi_type));
} }
else if (var->ravi_type == RAVI_TARRAYFLT || var->ravi_type == RAVI_TARRAYINT) { else if (var->ravi_type == RAVI_TARRAYFLT ||
var->ravi_type == RAVI_TARRAYINT ||
var->ravi_type == RAVI_TTABLE) {
if (ex->ravi_type == var->ravi_type) if (ex->ravi_type == var->ravi_type)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
@ -739,6 +757,12 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
else else
/* input value is known to be integer */ /* input value is known to be integer */
op = OP_RAVI_SETTABLE_AII; op = OP_RAVI_SETTABLE_AII;
} else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_type == RAVI_TNUMINT) {
/* table with integer key */
op = OP_RAVI_SETTABLEI;
} else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_type == RAVI_TSTRING) {
/* table with string key */
op = OP_RAVI_SETTABLES;
} }
} }
int e = luaK_exp2RK(fs, ex); int e = luaK_exp2RK(fs, ex);

@ -446,12 +446,15 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
case OP_RAVI_MOVEF: case OP_RAVI_MOVEF:
case OP_RAVI_MOVEAF: case OP_RAVI_MOVEAF:
case OP_RAVI_MOVEAI: case OP_RAVI_MOVEAI:
case OP_RAVI_MOVETAB:
case OP_MOVE: { case OP_MOVE: {
int b = GETARG_B(i); /* move from 'b' to 'a' */ int b = GETARG_B(i); /* move from 'b' to 'a' */
if (b < GETARG_A(i)) if (b < GETARG_A(i))
return getobjname(p, pc, b, name); /* get name for 'b' */ return getobjname(p, pc, b, name); /* get name for 'b' */
break; break;
} }
case OP_RAVI_GETTABLEI:
case OP_RAVI_GETTABLES:
case OP_RAVI_GETTABLE_AI: case OP_RAVI_GETTABLE_AI:
case OP_RAVI_GETTABLE_AF: case OP_RAVI_GETTABLE_AF:
case OP_GETTABUP: case OP_GETTABUP:

@ -566,7 +566,10 @@ static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type)
luaK_codeABC(ls->fs, ravi_type == RAVI_TARRAYINT ? OP_RAVI_TOARRAYI luaK_codeABC(ls->fs, ravi_type == RAVI_TARRAYINT ? OP_RAVI_TOARRAYI
: OP_RAVI_TOARRAYF, : OP_RAVI_TOARRAYF,
reg, 0, 0); reg, 0, 0);
// TODO handle table, string, function, userdata, boolean types else if (ravi_type == RAVI_TTABLE)
luaK_codeABC(ls->fs, OP_RAVI_TOTAB,
reg, 0, 0);
// TODO handle string, function, userdata, boolean types
} }
/* RAVI code an instruction to initialize a typed value */ /* RAVI code an instruction to initialize a typed value */
@ -1086,7 +1089,7 @@ static void constructor (LexState *ls, expdesc *t) {
struct ConsControl cc; struct ConsControl cc;
cc.na = cc.nh = cc.tostore = 0; cc.na = cc.nh = cc.tostore = 0;
cc.t = t; cc.t = t;
init_exp(t, VRELOCABLE, pc, RAVI_TANY); /* RAVI TODO - set table of type */ init_exp(t, VRELOCABLE, pc, RAVI_TTABLE); /* RAVI TODO - set table of type */
init_exp(&cc.v, VVOID, 0, RAVI_TANY); /* no value (yet) */ init_exp(&cc.v, VVOID, 0, RAVI_TANY); /* no value (yet) */
luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */
checknext(ls, '{'); checknext(ls, '{');
@ -1222,9 +1225,10 @@ static int explist (LexState *ls, expdesc *v) {
/* TODO instead of using vars here could we just rely upon register_typeinfo? */ /* TODO instead of using vars here could we just rely upon register_typeinfo? */
static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars, static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
int n) { int n) {
if (n < nvars && vars[n] != RAVI_TANY && v->ravi_type != vars[n]) { ravitype_t vartype = vars[n];
if (v->ravi_type != vars[n] && if (n < nvars && vartype != RAVI_TANY && v->ravi_type != vartype) {
(vars[n] == RAVI_TARRAYFLT || vars[n] == RAVI_TARRAYINT) && if (v->ravi_type != vartype &&
(vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) &&
v->k == VNONRELOC) { v->k == VNONRELOC) {
/* as the bytecode for generating a table is already emitted by this stage /* as the bytecode for generating a table is already emitted by this stage
* we have to amend the generated byte code - not sure if there is a * we have to amend the generated byte code - not sure if there is a
@ -1246,7 +1250,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
if (reg != v->u.info) if (reg != v->u.info)
continue; continue;
op = op =
(vars[n] == RAVI_TARRAYINT) ? OP_RAVI_NEWARRAYI : OP_RAVI_NEWARRAYF; (vartype == RAVI_TARRAYINT) ? OP_RAVI_NEWARRAYI : OP_RAVI_NEWARRAYF;
SET_OPCODE(*pc, op); /* modify opcode */ SET_OPCODE(*pc, op); /* modify opcode */
DEBUG_CODEGEN( DEBUG_CODEGEN(
raviY_printf(ls->fs, "[%d]* %o ; modify opcode\n", i, *pc)); raviY_printf(ls->fs, "[%d]* %o ; modify opcode\n", i, *pc));
@ -1256,9 +1260,10 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
luaX_syntaxerror(ls, "expecting array initializer"); luaX_syntaxerror(ls, "expecting array initializer");
} }
/* if we are calling a function then convert return types */ /* if we are calling a function then convert return types */
else if (v->ravi_type != vars[n] && else if (v->ravi_type != vartype &&
(vars[n] == RAVI_TNUMFLT || vars[n] == RAVI_TNUMINT || (vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT ||
vars[n] == RAVI_TARRAYFLT || vars[n] == RAVI_TARRAYINT) && vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT ||
vartype == RAVI_TTABLE) &&
v->k == VCALL) { v->k == VCALL) {
/* For local variable declarations that call functions e.g. /* For local variable declarations that call functions e.g.
* local i = func() * local i = func()
@ -1284,13 +1289,14 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
for (i = n; i < (n + nrets); i++) for (i = n; i < (n + nrets); i++)
/* do we need to convert ? */ /* do we need to convert ? */
ravi_code_typecoersion(ls, a + (i - n), vars[i]); ravi_code_typecoersion(ls, a + (i - n), vars[i]);
} else if ((vars[n] == RAVI_TNUMFLT || vars[n] == RAVI_TNUMINT) && } else if ((vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT) &&
v->k == VINDEXED) { v->k == VINDEXED) {
if ((vars[n] == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) || if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) ||
(vars[n] == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT)) (vartype == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT))
luaX_syntaxerror(ls, "Invalid local assignment"); luaX_syntaxerror(ls, "Invalid local assignment");
} else } else {
luaX_syntaxerror(ls, "Invalid local assignment"); luaX_syntaxerror(ls, "Invalid local assignment");
}
} }
} }

@ -758,6 +758,10 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_RAVI_SHR_II: case OP_RAVI_SHR_II:
case OP_SHR: case OP_SHR:
case OP_SHL: case OP_SHL:
case OP_RAVI_GETTABLEI:
case OP_RAVI_GETTABLES:
case OP_RAVI_SETTABLEI:
case OP_RAVI_SETTABLES:
break; break;
default: default:
return false; return false;
@ -1405,11 +1409,15 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
emit_CALL(def, A, B, C, pc); emit_CALL(def, A, B, C, pc);
} break; } break;
case OP_RAVI_SETTABLEI:
case OP_RAVI_SETTABLES:
case OP_SETTABLE: { case OP_SETTABLE: {
int B = GETARG_B(i); int B = GETARG_B(i);
int C = GETARG_C(i); int C = GETARG_C(i);
emit_SETTABLE(def, A, B, C, pc); emit_SETTABLE(def, A, B, C, pc);
} break; } break;
case OP_RAVI_GETTABLEI:
case OP_RAVI_GETTABLES:
case OP_GETTABLE: { case OP_GETTABLE: {
int B = GETARG_B(i); int B = GETARG_B(i);
int C = GETARG_C(i); int C = GETARG_C(i);

@ -124,7 +124,8 @@ static int test_luacompexec1(const char *code, int expected)
int main() int main()
{ {
int failures = 0; int failures = 0;
// //
failures += test_luacomp1("function x() local t : table = {}; t.name = 'd'; end");
failures += test_luacompexec1("function test(); local x: integer = 1; return function (j) x = j; return x; end; end; fn = test(); return fn('55')", 55); failures += test_luacompexec1("function test(); local x: integer = 1; return function (j) x = j; return x; end; end; fn = test(); return fn('55')", 55);
failures += test_luacompexec1("ravi.auto(true); function arrayaccess (); local x: integer[] = {5}; return x[1]; end; assert(ravi.compile(arrayaccess)); return arrayaccess()", 5); failures += test_luacompexec1("ravi.auto(true); function arrayaccess (); local x: integer[] = {5}; return x[1]; end; assert(ravi.compile(arrayaccess)); return arrayaccess()", 5);
failures += test_luacompexec1("ravi.auto(true); function cannotload (msg, a,b); assert(not a and string.find(b, msg)); end; ravi.compile(cannotload); return 1", 1); failures += test_luacompexec1("ravi.auto(true); function cannotload (msg, a,b); assert(not a and string.find(b, msg)); end; ravi.compile(cannotload); return 1", 1);

Loading…
Cancel
Save