lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 0fe2576a39633ab7873f9d4fd989f1e5203a5725
parent d08d237a49ff3cb961012b1de374914af6da3000
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Fri, 26 Feb 2010 17:40:05 -0300

new instructions to optimize indexing on upvalues

Diffstat:
Mlcode.c | 22++++++++++++++++++++--
Mlcode.h | 3++-
Mldebug.c | 35++++++++++++++++++++++++++---------
Mlopcodes.c | 6+++++-
Mlopcodes.h | 4+++-
Mlparser.c | 23++++++++++++++---------
Mlparser.h | 11++++++-----
Mlvm.c | 16+++++++++++++---
8 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/lcode.c b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.42 2009/09/23 20:33:05 roberto Exp roberto $ +** $Id: lcode.c,v 2.43 2010/01/11 17:38:30 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -384,6 +384,12 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { e->k = VRELOCABLE; break; } + case VINDEXEDUP: { + freereg(fs, e->u.s.aux); + e->u.s.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.s.info, e->u.s.aux); + e->k = VRELOCABLE; + break; + } case VVARARG: case VCALL: { luaK_setoneret(fs, e); @@ -493,6 +499,12 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { } +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + void luaK_exp2val (FuncState *fs, expdesc *e) { if (hasjumps(e)) luaK_exp2anyreg(fs, e); @@ -553,6 +565,11 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); break; } + case VINDEXEDUP: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABUP, var->u.s.info, var->u.s.aux, e); + break; + } default: { lua_assert(0); /* invalid var kind to store */ break; @@ -695,8 +712,9 @@ static void codenot (FuncState *fs, expdesc *e) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + lua_assert(!hasjumps(t)); t->u.s.aux = luaK_exp2RK(fs, k); - t->k = VINDEXED; + t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED; } diff --git a/lcode.h b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.51 2009/06/18 16:35:05 roberto Exp roberto $ +** $Id: lcode.h,v 1.52 2009/09/23 20:33:05 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -57,6 +57,7 @@ LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); diff --git a/ldebug.c b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.62 2010/01/11 17:37:59 roberto Exp roberto $ +** $Id: ldebug.c,v 2.63 2010/01/13 16:18:25 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -270,12 +270,10 @@ static const char *kname (Proto *p, int c) { static const char *getobjname (lua_State *L, CallInfo *ci, int reg, const char **name) { - Proto *p; - int lastpc, pc; + Proto *p = ci_func(ci)->l.p; const char *what = NULL; - lua_assert(isLua(ci)); - p = ci_func(ci)->l.p; - lastpc = currentpc(ci); + int lastpc = currentpc(ci); + int pc; *name = luaF_getlocalname(p, reg + 1, lastpc); if (*name) /* is a local? */ return "local"; @@ -305,6 +303,7 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, } break; } + case OP_GETTABUP: case OP_GETTABLE: { if (reg == a) { int k = GETARG_C(i); /* key index */ @@ -378,6 +377,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { return getobjname(L, ci, GETARG_A(i), name); case OP_GETGLOBAL: case OP_SELF: + case OP_GETTABUP: case OP_GETTABLE: tm = TM_INDEX; break; case OP_SETGLOBAL: case OP_SETTABLE: tm = TM_NEWINDEX; break; @@ -413,13 +413,30 @@ static int isinstack (CallInfo *ci, const TValue *o) { } +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = &ci_func(ci)->l; + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = getstr(c->p->upvalues[i].name); + return "upvalue"; + } + } + return NULL; +} + + void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { CallInfo *ci = L->ci; const char *name = NULL; const char *t = typename(ttype(o)); - const char *kind = (isLua(ci) && isinstack(ci, o)) ? - getobjname(L, ci, cast_int(o - ci->u.l.base), &name) : - NULL; + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(L, ci, cast_int(o - ci->u.l.base), &name); + } if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", op, kind, name, t); diff --git a/lopcodes.c b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.40 2008/10/30 15:39:30 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.41 2009/11/19 19:06:52 roberto Exp roberto $ ** See Copyright Notice in lua.h */ @@ -20,8 +20,10 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "LOADNIL", "GETUPVAL", "GETGLOBAL", + "GETTABUP", "GETTABLE", "SETGLOBAL", + "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", @@ -68,8 +70,10 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ diff --git a/lopcodes.h b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.132 2009/10/28 12:20:07 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.133 2009/11/19 19:06:52 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -172,9 +172,11 @@ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ OP_GETUPVAL,/* A B R(A) := UpValue[B] */ OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx - 1)] */ +OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx - 1)] := R(A) */ +OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ OP_SETUPVAL,/* A B UpValue[B] := R(A) */ OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ diff --git a/lparser.c b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.74 2010/01/05 18:46:58 roberto Exp roberto $ +** $Id: lparser.c,v 2.75 2010/01/06 11:48:02 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -452,7 +452,7 @@ static void fieldsel (LexState *ls, expdesc *v) { /* fieldsel -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); luaK_indexed(fs, v, &key); @@ -747,7 +747,7 @@ static void primaryexp (LexState *ls, expdesc *v) { } case '[': { /* `[' exp1 `]' */ expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; @@ -951,24 +951,27 @@ struct LHS_assign { ** local value in a safe place and use this safe copy in the previous ** assignment. */ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, + expkind ix, OpCode op) { FuncState *fs = ls->fs; int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; for (; lh; lh = lh->prev) { - if (lh->v.k == VINDEXED) { + if (lh->v.k == ix) { if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ conflict = 1; + lh->v.k = VINDEXED; lh->v.u.s.info = extra; /* previous assignment will use safe copy */ } - if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + if (v->k == VLOCAL && lh->v.u.s.aux == v->u.s.info) { /* conflict? */ conflict = 1; + lua_assert(lh->v.k == VINDEXED); lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ } } } if (conflict) { - luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + luaK_codeABC(fs, op, fs->freereg, v->u.s.info, 0); /* make copy */ luaK_reserveregs(fs, 1); } } @@ -976,14 +979,16 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; - check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) - check_conflict(ls, lh, &nv.v); + check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE); + else if (nv.v.k == VUPVAL) + check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL); checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, "variable names"); assignment(ls, &nv, nvars+1); diff --git a/lparser.h b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.60 2009/09/30 15:38:37 roberto Exp roberto $ +** $Id: lparser.h,v 1.61 2009/10/11 20:02:19 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -23,10 +23,11 @@ typedef enum { VFALSE, VK, /* info = index of constant in `k' */ VKNUM, /* nval = numerical value */ - VLOCAL, /* info = local register; aux = read only */ - VUPVAL, /* info = index of upvalue in 'upvalues'; aux = read only */ - VGLOBAL, /* info = index of table; aux = index of global name in `k' */ - VINDEXED, /* info = table register; aux = index register (or `k') */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in 'upvalues' */ + VGLOBAL, /* info = index of global name in 'k' */ + VINDEXED, /* info = table R/K; aux = index R/K */ + VINDEXEDUP, /* info = table upvalue; aux = R/K */ VJMP, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */ VNONRELOC, /* info = result register */ diff --git a/lvm.c b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.102 2009/12/17 16:20:01 roberto Exp roberto $ +** $Id: lvm.c,v 2.103 2010/01/15 16:23:58 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -362,7 +362,7 @@ void luaV_finishOp (lua_State *L) { switch (op) { /* finish its execution */ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: - case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: { + case OP_GETGLOBAL: case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { setobjs2s(L, base + GETARG_A(inst), --L->top); break; } @@ -403,7 +403,7 @@ void luaV_finishOp (lua_State *L) { L->top = ci->top; /* adjust results */ break; } - case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE: + case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABUP: case OP_SETTABLE: break; default: lua_assert(0); } @@ -504,6 +504,11 @@ void luaV_execute (lua_State *L) { Protect(luaV_gettable(L, &g, rb, ra)); continue; } + case OP_GETTABUP: { + int b = GETARG_B(i); + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + continue; + } case OP_GETTABLE: { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; @@ -516,6 +521,11 @@ void luaV_execute (lua_State *L) { Protect(luaV_settable(L, &g, rb, ra)); continue; } + case OP_SETTABUP: { + int a = GETARG_A(i); + Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); + continue; + } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra);