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;
else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_type == RAVI_TNUMINT)
op = OP_RAVI_GETTABLE_AI;
else
op = OP_GETTABLE;
else {
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)
/* set the type of resulting expression */
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->k = VRELOCABLE;
@ -516,6 +524,9 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
case RAVI_TARRAYFLT:
luaK_codeABC(fs, OP_RAVI_MOVEAF, reg, e->u.info, 0);
break;
case RAVI_TTABLE:
luaK_codeABC(fs, OP_RAVI_MOVETAB, reg, e->u.info, 0);
break;
default:
luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
break;
@ -638,7 +649,12 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
/* 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 */
return;
}
@ -668,7 +684,9 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
var->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)
return;
luaX_syntaxerror(
@ -739,6 +757,12 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
else
/* input value is known to be integer */
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);

@ -446,12 +446,15 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
case OP_RAVI_MOVEF:
case OP_RAVI_MOVEAF:
case OP_RAVI_MOVEAI:
case OP_RAVI_MOVETAB:
case OP_MOVE: {
int b = GETARG_B(i); /* move from 'b' to 'a' */
if (b < GETARG_A(i))
return getobjname(p, pc, b, name); /* get name for 'b' */
break;
}
case OP_RAVI_GETTABLEI:
case OP_RAVI_GETTABLES:
case OP_RAVI_GETTABLE_AI:
case OP_RAVI_GETTABLE_AF:
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
: OP_RAVI_TOARRAYF,
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 */
@ -1086,7 +1089,7 @@ static void constructor (LexState *ls, expdesc *t) {
struct ConsControl cc;
cc.na = cc.nh = cc.tostore = 0;
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) */
luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */
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? */
static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
int n) {
if (n < nvars && vars[n] != RAVI_TANY && v->ravi_type != vars[n]) {
if (v->ravi_type != vars[n] &&
(vars[n] == RAVI_TARRAYFLT || vars[n] == RAVI_TARRAYINT) &&
ravitype_t vartype = vars[n];
if (n < nvars && vartype != RAVI_TANY && v->ravi_type != vartype) {
if (v->ravi_type != vartype &&
(vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) &&
v->k == VNONRELOC) {
/* 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
@ -1246,7 +1250,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
if (reg != v->u.info)
continue;
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 */
DEBUG_CODEGEN(
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");
}
/* if we are calling a function then convert return types */
else if (v->ravi_type != vars[n] &&
(vars[n] == RAVI_TNUMFLT || vars[n] == RAVI_TNUMINT ||
vars[n] == RAVI_TARRAYFLT || vars[n] == RAVI_TARRAYINT) &&
else if (v->ravi_type != vartype &&
(vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT ||
vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT ||
vartype == RAVI_TTABLE) &&
v->k == VCALL) {
/* For local variable declarations that call functions e.g.
* 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++)
/* do we need to convert ? */
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) {
if ((vars[n] == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) ||
(vars[n] == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT))
if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) ||
(vartype == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT))
luaX_syntaxerror(ls, "Invalid local assignment");
} else
} else {
luaX_syntaxerror(ls, "Invalid local assignment");
}
}
}

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

@ -124,7 +124,8 @@ static int test_luacompexec1(const char *code, int expected)
int main()
{
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("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);

Loading…
Cancel
Save