From 55df8ea9cdc1868861035881619c16b9c9e29187 Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Fri, 6 Nov 2015 00:57:07 +0000 Subject: [PATCH] issue #60 explore further optimization of table operations --- src/lcode.c | 32 ++++++++++++++++++++++++++++---- src/ldebug.c | 3 +++ src/lparser.c | 32 +++++++++++++++++++------------- src/ravi_llvmcodegen.cpp | 8 ++++++++ tests/test_vm.c | 3 ++- 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index ebd855f..9cb7760 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -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); diff --git a/src/ldebug.c b/src/ldebug.c index 8d918e8..35fee32 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -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: diff --git a/src/lparser.c b/src/lparser.c index 0596a47..5cc9e0e 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -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"); + } } } diff --git a/src/ravi_llvmcodegen.cpp b/src/ravi_llvmcodegen.cpp index 0bf4e01..6fb2ea4 100644 --- a/src/ravi_llvmcodegen.cpp +++ b/src/ravi_llvmcodegen.cpp @@ -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); diff --git a/tests/test_vm.c b/tests/test_vm.c index db9cf8c..cdfaaa4 100644 --- a/tests/test_vm.c +++ b/tests/test_vm.c @@ -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);