new instructions to optimize indexing on upvalues

This commit is contained in:
Roberto Ierusalimschy
2010-02-26 17:40:29 -03:00
parent d08d237a49
commit 0fe2576a39
8 changed files with 89 additions and 31 deletions

22
lcode.c
View File

@@ -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 ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -384,6 +384,12 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; 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 VVARARG:
case VCALL: { case VCALL: {
luaK_setoneret(fs, e); 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) { void luaK_exp2val (FuncState *fs, expdesc *e) {
if (hasjumps(e)) if (hasjumps(e))
luaK_exp2anyreg(fs, 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); luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
break; 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: { default: {
lua_assert(0); /* invalid var kind to store */ lua_assert(0); /* invalid var kind to store */
break; break;
@@ -695,8 +712,9 @@ static void codenot (FuncState *fs, expdesc *e) {
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
lua_assert(!hasjumps(t));
t->u.s.aux = luaK_exp2RK(fs, k); t->u.s.aux = luaK_exp2RK(fs, k);
t->k = VINDEXED; t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED;
} }

View File

@@ -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 ** Code generator for Lua
** See Copyright Notice in lua.h ** 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 int luaK_numberK (FuncState *fs, lua_Number r);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (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_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);

View File

@@ -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 ** Debug Interface
** See Copyright Notice in lua.h ** 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, static const char *getobjname (lua_State *L, CallInfo *ci, int reg,
const char **name) { const char **name) {
Proto *p; Proto *p = ci_func(ci)->l.p;
int lastpc, pc;
const char *what = NULL; const char *what = NULL;
lua_assert(isLua(ci)); int lastpc = currentpc(ci);
p = ci_func(ci)->l.p; int pc;
lastpc = currentpc(ci);
*name = luaF_getlocalname(p, reg + 1, lastpc); *name = luaF_getlocalname(p, reg + 1, lastpc);
if (*name) /* is a local? */ if (*name) /* is a local? */
return "local"; return "local";
@@ -305,6 +303,7 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg,
} }
break; break;
} }
case OP_GETTABUP:
case OP_GETTABLE: { case OP_GETTABLE: {
if (reg == a) { if (reg == a) {
int k = GETARG_C(i); /* key index */ 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); return getobjname(L, ci, GETARG_A(i), name);
case OP_GETGLOBAL: case OP_GETGLOBAL:
case OP_SELF: case OP_SELF:
case OP_GETTABUP:
case OP_GETTABLE: tm = TM_INDEX; break; case OP_GETTABLE: tm = TM_INDEX; break;
case OP_SETGLOBAL: case OP_SETGLOBAL:
case OP_SETTABLE: tm = TM_NEWINDEX; break; 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) { void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
const char *name = NULL; const char *name = NULL;
const char *t = typename(ttype(o)); const char *t = typename(ttype(o));
const char *kind = (isLua(ci) && isinstack(ci, o)) ? const char *kind = NULL;
getobjname(L, ci, cast_int(o - ci->u.l.base), &name) : if (isLua(ci)) {
NULL; 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) if (kind)
luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
op, kind, name, t); op, kind, name, t);

View File

@@ -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 ** See Copyright Notice in lua.h
*/ */
@@ -20,8 +20,10 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"LOADNIL", "LOADNIL",
"GETUPVAL", "GETUPVAL",
"GETGLOBAL", "GETGLOBAL",
"GETTABUP",
"GETTABLE", "GETTABLE",
"SETGLOBAL", "SETGLOBAL",
"SETTABUP",
"SETUPVAL", "SETUPVAL",
"SETTABLE", "SETTABLE",
"NEWTABLE", "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, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ,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, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ,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, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */

View File

@@ -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 ** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h ** 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_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx - 1)] */ 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_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx - 1)] := R(A) */ 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_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */

View File

@@ -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 ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -452,7 +452,7 @@ static void fieldsel (LexState *ls, expdesc *v) {
/* fieldsel -> ['.' | ':'] NAME */ /* fieldsel -> ['.' | ':'] NAME */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
expdesc key; expdesc key;
luaK_exp2anyreg(fs, v); luaK_exp2anyregup(fs, v);
luaX_next(ls); /* skip the dot or colon */ luaX_next(ls); /* skip the dot or colon */
checkname(ls, &key); checkname(ls, &key);
luaK_indexed(fs, v, &key); luaK_indexed(fs, v, &key);
@@ -747,7 +747,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
} }
case '[': { /* `[' exp1 `]' */ case '[': { /* `[' exp1 `]' */
expdesc key; expdesc key;
luaK_exp2anyreg(fs, v); luaK_exp2anyregup(fs, v);
yindex(ls, &key); yindex(ls, &key);
luaK_indexed(fs, v, &key); luaK_indexed(fs, v, &key);
break; break;
@@ -951,24 +951,27 @@ struct LHS_assign {
** local value in a safe place and use this safe copy in the previous ** local value in a safe place and use this safe copy in the previous
** assignment. ** 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; FuncState *fs = ls->fs;
int extra = fs->freereg; /* eventual position to save local variable */ int extra = fs->freereg; /* eventual position to save local variable */
int conflict = 0; int conflict = 0;
for (; lh; lh = lh->prev) { 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? */ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
conflict = 1; conflict = 1;
lh->v.k = VINDEXED;
lh->v.u.s.info = extra; /* previous assignment will use safe copy */ 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; conflict = 1;
lua_assert(lh->v.k == VINDEXED);
lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
} }
} }
} }
if (conflict) { 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); 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) { static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
expdesc e; 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"); "syntax error");
if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
struct LHS_assign nv; struct LHS_assign nv;
nv.prev = lh; nv.prev = lh;
primaryexp(ls, &nv.v); primaryexp(ls, &nv.v);
if (nv.v.k == VLOCAL) 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, checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls,
"variable names"); "variable names");
assignment(ls, &nv, nvars+1); assignment(ls, &nv, nvars+1);

View File

@@ -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 ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -23,10 +23,11 @@ typedef enum {
VFALSE, VFALSE,
VK, /* info = index of constant in `k' */ VK, /* info = index of constant in `k' */
VKNUM, /* nval = numerical value */ VKNUM, /* nval = numerical value */
VLOCAL, /* info = local register; aux = read only */ VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in 'upvalues'; aux = read only */ VUPVAL, /* info = index of upvalue in 'upvalues' */
VGLOBAL, /* info = index of table; aux = index of global name in `k' */ VGLOBAL, /* info = index of global name in 'k' */
VINDEXED, /* info = table register; aux = index register (or `k') */ VINDEXED, /* info = table R/K; aux = index R/K */
VINDEXEDUP, /* info = table upvalue; aux = R/K */
VJMP, /* info = instruction pc */ VJMP, /* info = instruction pc */
VRELOCABLE, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */
VNONRELOC, /* info = result register */ VNONRELOC, /* info = result register */

16
lvm.c
View File

@@ -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 ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -362,7 +362,7 @@ void luaV_finishOp (lua_State *L) {
switch (op) { /* finish its execution */ switch (op) { /* finish its execution */
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: 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_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); setobjs2s(L, base + GETARG_A(inst), --L->top);
break; break;
} }
@@ -403,7 +403,7 @@ void luaV_finishOp (lua_State *L) {
L->top = ci->top; /* adjust results */ L->top = ci->top; /* adjust results */
break; break;
} }
case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE: case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABUP: case OP_SETTABLE:
break; break;
default: lua_assert(0); default: lua_assert(0);
} }
@@ -504,6 +504,11 @@ void luaV_execute (lua_State *L) {
Protect(luaV_gettable(L, &g, rb, ra)); Protect(luaV_gettable(L, &g, rb, ra));
continue; continue;
} }
case OP_GETTABUP: {
int b = GETARG_B(i);
Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
continue;
}
case OP_GETTABLE: { case OP_GETTABLE: {
Protect(luaV_gettable(L, RB(i), RKC(i), ra)); Protect(luaV_gettable(L, RB(i), RKC(i), ra));
continue; continue;
@@ -516,6 +521,11 @@ void luaV_execute (lua_State *L) {
Protect(luaV_settable(L, &g, rb, ra)); Protect(luaV_settable(L, &g, rb, ra));
continue; 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: { case OP_SETUPVAL: {
UpVal *uv = cl->upvals[GETARG_B(i)]; UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra); setobj(L, uv->v, ra);