From 502a1d1108d4e3b97e012d2ed9a496fd003b08db Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 28 Apr 2017 17:57:45 -0300 Subject: [PATCH] new opcodes for table access with constant keys (strings and integers) --- lcode.c | 74 ++++++++++++++++++++++++++++++++----------- ldebug.c | 92 ++++++++++++++++++++++++++++++++++++------------------ lopcodes.c | 18 ++++++++--- lopcodes.h | 20 ++++++------ lparser.c | 40 ++++++++++++++---------- lparser.h | 24 +++++++++----- lvm.c | 76 ++++++++++++++++++++++++++++++++++++-------- 7 files changed, 245 insertions(+), 99 deletions(-) diff --git a/lcode.c b/lcode.c index ccf7b1ae..a154c339 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.116 2017/04/25 20:01:14 roberto Exp roberto $ +** $Id: lcode.c,v 2.117 2017/04/26 17:46:52 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -580,18 +580,26 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { e->k = VRELOCABLE; break; } + case VINDEXUP: { + e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VINDEXI: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VINDEXSTR: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } case VINDEXED: { - OpCode op; - if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ - freeregs(fs, e->u.ind.t, e->u.ind.idx); - op = OP_GETTABLE; - } - else { - lua_assert(e->u.ind.vt == VUPVAL); - freereg(fs, e->u.ind.idx); - op = OP_GETTABUP; /* 't' is in an upvalue */ - } - e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + freeregs(fs, e->u.ind.t, e->u.ind.idx); + e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } @@ -807,10 +815,24 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); break; } + case VINDEXUP: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e); + break; + } + case VINDEXI: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, e); + break; + } + case VINDEXSTR: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, e); + break; + } case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e); break; } default: lua_assert(0); /* invalid var kind to store */ @@ -959,7 +981,8 @@ static void codenot (FuncState *fs, expdesc *e) { ** Check whether expression 'e' is a literal string */ static int isKstr (FuncState *fs, expdesc *e) { - return (e->k == VK && ttisstring(&fs->f->k[e->u.info])); + return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_C && + ttisstring(&fs->f->k[e->u.info])); } @@ -976,15 +999,30 @@ static int isKint (expdesc *e) { /* ** Create expression 't[k]'. 't' must have its final result already in a ** register or upvalue. Upvalues can only be indexed by literal strings. +** Keys can be literal strings in the constant table or arbitrary +** values in registers. */ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */ luaK_exp2anyreg(fs, t); /* put it in a register */ t->u.ind.t = t->u.info; /* register or upvalue index */ - t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ - t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; - t->k = VINDEXED; + if (t->k == VUPVAL) { + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXUP; + } + else if (isKstr(fs, k)) { + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXSTR; + } + else if (isKint(k)) { + t->u.ind.idx = k->u.ival; /* integer constant */ + t->k = VINDEXI; + } + else { + t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ + t->k = VINDEXED; + } } diff --git a/ldebug.c b/ldebug.c index 4f35d211..8a36e2f8 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.121 2016/10/19 12:32:10 roberto Exp roberto $ +** $Id: ldebug.c,v 2.122 2017/04/26 17:46:52 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -350,28 +350,36 @@ static const char *getobjname (Proto *p, int lastpc, int reg, /* -** find a "name" for the RK value 'c' +** Find a "name" for the constant 'c'. */ -static void kname (Proto *p, int pc, int c, const char **name) { - if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &p->k[INDEXK(c)]; - if (ttisstring(kvalue)) { /* literal constant? */ - *name = svalue(kvalue); /* it is its own name */ - return; - } - /* else no reasonable name found */ - } - else { /* 'c' is a register */ - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (what && *what == 'c') { /* found a constant name? */ - return; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - *name = "?"; /* no reasonable name found */ +static void kname (Proto *p, int c, const char **name) { + TValue *kvalue = &p->k[INDEXK(c)]; + *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?"; +} + + +/* +** Find a "name" for the register 'c'. +*/ +static void rname (Proto *p, int pc, int c, const char **name) { + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (!(what && *what == 'c')) /* did not find a constant name? */ + *name = "?"; +} + + +/* +** Find a "name" for the R/K index 'c'. +*/ +static void rkname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) /* is 'c' a constant? */ + kname(p, INDEXK(c), name); + else /* 'c' is a register */ + rname(p, pc, c, name); } + static int filterpc (int pc, int jmptarget) { if (pc < jmptarget) /* is code conditional (inside a jump)? */ return -1; /* cannot know who sets that register */ @@ -428,8 +436,22 @@ static int findsetreg (Proto *p, int lastpc, int reg) { } -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name) { +/* +** Check whether table being indexed by instruction 'i' is the +** environment '_ENV' +*/ +static const char *gxf (Proto *p, int pc, Instruction i, int isup) { + int t = GETARG_B(i); /* table index */ + const char *name; /* name of indexed variable */ + if (isup) /* is an upvalue? */ + name = upvalname(p, t); + else + getobjname(p, pc, t, &name); + return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; +} + + + const char *getobjname (Proto *p, int lastpc, int reg, const char **name) { int pc; *name = luaF_getlocalname(p, reg + 1, lastpc); if (*name) /* is a local? */ @@ -446,15 +468,24 @@ static const char *getobjname (Proto *p, int lastpc, int reg, return getobjname(p, pc, b, name); /* get name for 'b' */ break; } - case OP_GETTABUP: + case OP_GETTABUP: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 1); + } case OP_GETTABLE: { int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); /* table index */ - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : upvalname(p, t); - kname(p, pc, k, name); - return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + rname(p, pc, k, name); + return gxf(p, pc, i, 0); + } + case OP_GETI: { + *name = "integer index"; + return "field"; + } + case OP_GETFIELD: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 0); } case OP_GETUPVAL: { *name = upvalname(p, GETARG_B(i)); @@ -472,7 +503,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg, } case OP_SELF: { int k = GETARG_C(i); /* key index */ - kname(p, pc, k, name); + rkname(p, pc, k, name); return "method"; } default: break; /* go through to return NULL */ @@ -508,9 +539,10 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, } /* other instructions can do calls through metamethods */ case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: + case OP_GETI: case OP_GETFIELD: tm = TM_INDEX; break; - case OP_SETTABUP: case OP_SETTABLE: + case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: tm = TM_NEWINDEX; break; case OP_ADDI: diff --git a/lopcodes.c b/lopcodes.c index f66f209a..1ffc52c9 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.56 2017/04/20 19:53:55 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.57 2017/04/26 17:46:52 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -25,11 +25,15 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "LOADBOOL", "LOADNIL", "GETUPVAL", + "SETUPVAL", "GETTABUP", "GETTABLE", + "GETI", + "GETFIELD", "SETTABUP", - "SETUPVAL", "SETTABLE", + "SETI", + "SETFIELD", "NEWTABLE", "SELF", "ADDI", @@ -82,11 +86,15 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_GETTABLE */ + ,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_GETI */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETFIELD */ ,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, 0, OpArgR, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 0, OpArgU, OpArgK, iABC) /* OP_SETI */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETFIELD */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ ,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_ADDI */ diff --git a/lopcodes.h b/lopcodes.h index c359581d..6c9df6f3 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.151 2017/04/24 20:26:39 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.152 2017/04/26 17:46:52 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -178,17 +178,21 @@ OP_LOADKX,/* A R(A) := Kst(extra arg) */ OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ OP_GETUPVAL,/* A B R(A) := UpValue[B] */ +OP_SETUPVAL,/* A B UpValue[B] := R(A) */ -OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ -OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ +OP_GETTABUP,/* A B C R(A) := UpValue[B][K(C):string] */ +OP_GETTABLE,/* A B C R(A) := R(B)[R(C)] */ +OP_GETI,/* A B C R(A) := R(B)[C] */ +OP_GETFIELD,/* A B C R(A) := R(B)[Kst(C):string] */ -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) */ +OP_SETTABUP,/* A B C UpValue[A][K(B):string] := RK(C) */ +OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */ +OP_SETI,/* A B C R(A)[B] := RK(C) */ +OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */ OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ -OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ +OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ OP_ADDI,/* A B C R(A) := R(B) + C */ OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ @@ -259,8 +263,6 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. - (*) In OP_GETTABUP, OP_SETTABUP, and OP_SELF, the index must be a string. - (*) For comparisons, A specifies what condition the test should accept (true or false). diff --git a/lparser.c b/lparser.c index 25134f11..f78f64bd 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.155 2016/08/01 19:51:24 roberto Exp roberto $ +** $Id: lparser.c,v 2.156 2017/04/20 19:53:55 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -647,8 +647,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { /* recfield -> (NAME | '['exp1']') = exp1 */ FuncState *fs = ls->fs; int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; + expdesc tab, key, val; if (ls->t.token == TK_NAME) { checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); @@ -657,9 +656,10 @@ static void recfield (LexState *ls, struct ConsControl *cc) { yindex(ls, &key); cc->nh++; checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); + tab = *cc->t; + luaK_indexed(fs, &tab, &key); expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); + luaK_storevar(fs, &tab, &val); fs->freereg = reg; /* free registers */ } @@ -1121,17 +1121,25 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (lh->v.k == VINDEXED) { /* assigning to a table? */ - /* table is the upvalue/local being assigned now? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + if (vkisindexed(lh->v.k)) { /* assignment to table field? */ + if (lh->v.k == VINDEXUP) { /* is table an upvalue? */ + if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) { + conflict = 1; /* table is the upvalue being assigned now */ + lh->v.k = VINDEXSTR; + lh->v.u.ind.t = extra; /* assignment will use safe copy */ + } } - /* index is the local being assigned? (index cannot be upvalue) */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + else { /* table is a register */ + if (v->k == VLOCAL && lh->v.u.ind.t == v->u.info) { + conflict = 1; /* table is the local being assigned now */ + lh->v.u.ind.t = extra; /* assignment will use safe copy */ + } + /* is index the local being assigned? */ + if (lh->v.k == VINDEXED && v->k == VLOCAL && + lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } } } } @@ -1151,7 +1159,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { struct LHS_assign nv; nv.prev = lh; suffixedexp(ls, &nv.v); - if (nv.v.k != VINDEXED) + if (!vkisindexed(nv.v.k)) check_conflict(ls, lh, &nv.v); checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, "C levels"); diff --git a/lparser.h b/lparser.h index 13e613ac..16124181 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.75 2015/12/17 15:44:50 roberto Exp roberto $ +** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -36,9 +36,17 @@ typedef enum { VLOCAL, /* local variable; info = local register */ VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ VINDEXED, /* indexed variable; - ind.vt = whether 't' is register or upvalue; - ind.t = table register or upvalue; - ind.idx = key's R/K index */ + ind.t = table register; + ind.idx = key's R index */ + VINDEXUP, /* indexed upvalue; + ind.t = table upvalue; + ind.idx = key's K index */ + VINDEXI, /* indexed variable with constant integer; + ind.t = table register; + ind.idx = key's value */ + VINDEXSTR, /* indexed variable with literal string; + ind.t = table register; + ind.idx = key's K index */ VJMP, /* expression is a test/comparison; info = pc of corresponding jump instruction */ VRELOCABLE, /* expression can put result in any register; @@ -48,7 +56,8 @@ typedef enum { } expkind; -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR) +#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR) #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) typedef struct expdesc { @@ -57,10 +66,9 @@ typedef struct expdesc { lua_Integer ival; /* for VKINT */ lua_Number nval; /* for VKFLT */ int info; /* for generic use */ - struct { /* for indexed variables (VINDEXED) */ - short idx; /* index (R/K) */ + struct { /* for indexed variables */ + short idx; /* index (R or "long" K) */ lu_byte t; /* table (register or upvalue) */ - lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ } ind; } u; int t; /* patch list of 'exit when true' */ diff --git a/lvm.c b/lvm.c index 52a6ca35..9fa9daf5 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.272 2017/04/24 20:26:39 roberto Exp roberto $ +** $Id: lvm.c,v 2.273 2017/04/26 17:46:52 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -658,11 +658,13 @@ void luaV_finishOp (lua_State *L) { Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: + case OP_ADDI: case OP_ADD: case OP_SUB: + case OP_MUL: case OP_DIV: case OP_IDIV: case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: case OP_MOD: case OP_POW: case OP_UNM: case OP_BNOT: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: + case OP_GETFIELD: case OP_SELF: { setobjs2s(L, base + GETARG_A(inst), --L->top); break; } @@ -704,6 +706,7 @@ void luaV_finishOp (lua_State *L) { break; } case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + case OP_SETI: case OP_SETFIELD: break; default: lua_assert(0); } @@ -726,7 +729,9 @@ void luaV_finishOp (lua_State *L) { #define RA(i) (base+GETARG_A(i)) #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_Br(i)) +#define KB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define KC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, k+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ (GETARG_Bk(i)) ? k+GETARG_Br(i) : base+GETARG_Br(i)) #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ @@ -837,10 +842,16 @@ void luaV_execute (lua_State *L) { setobj2s(L, ra, cl->upvals[b]->v); vmbreak; } + vmcase(OP_SETUPVAL) { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + vmbreak; + } vmcase(OP_GETTABUP) { const TValue *slot; TValue *upval = cl->upvals[GETARG_B(i)]->v; - TValue *rc = RKC(i); + TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a string */ if (luaV_fastget(L, upval, key, slot, luaH_getstr)) { setobj2s(L, ra, slot); @@ -850,32 +861,71 @@ void luaV_execute (lua_State *L) { } vmcase(OP_GETTABLE) { StkId rb = RB(i); - TValue *rc = RKC(i); + TValue *rc = RC(i); gettableProtected(L, rb, rc, ra); vmbreak; } + vmcase(OP_GETI) { + const TValue *slot; + StkId rb = RB(i); + int c = GETARG_C(i); + if (luaV_fastget(L, rb, c, slot, luaH_getint)) { + setobj2s(L, ra, slot); + } + else { + TValue key; + setivalue(&key, c); + Protect(luaV_finishget(L, rb, &key, ra, slot)); + } + vmbreak; + } + vmcase(OP_GETFIELD) { + const TValue *slot; + StkId rb = RB(i); + TValue *rc = KC(i); + TString *key = tsvalue(rc); /* key must be a string */ + if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { + setobj2s(L, ra, slot); + } + else Protect(luaV_finishget(L, rb, rc, ra, slot)); + vmbreak; + } vmcase(OP_SETTABUP) { const TValue *slot; TValue *upval = cl->upvals[GETARG_A(i)]->v; - TValue *rb = RKB(i); + TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a string */ if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc)) Protect(luaV_finishset(L, upval, rb, rc, slot)); vmbreak; } - vmcase(OP_SETUPVAL) { - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - vmbreak; - } vmcase(OP_SETTABLE) { - TValue *rb = RKB(i); + TValue *rb = RB(i); TValue *rc = RKC(i); settableProtected(L, ra, rb, rc); vmbreak; } + vmcase(OP_SETI) { + const TValue *slot; + int c = GETARG_B(i); + TValue *rc = RKC(i); + if (!luaV_fastset(L, ra, c, slot, luaH_getint, rc)) { + TValue key; + setivalue(&key, c); + Protect(luaV_finishset(L, ra, &key, rc, slot)); + } + vmbreak; + } + vmcase(OP_SETFIELD) { + const TValue *slot; + TValue *rb = KB(i); + TValue *rc = RKC(i); + TString *key = tsvalue(rb); /* key must be a string */ + if (!luaV_fastset(L, ra, key, slot, luaH_getstr, rc)) + Protect(luaV_finishset(L, ra, rb, rc, slot)); + vmbreak; + } vmcase(OP_NEWTABLE) { int b = GETARG_B(i); int c = GETARG_C(i);