From cb3d5dce30089512085f78a0bef79e30ef732e30 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 24 Apr 2017 17:26:39 -0300 Subject: [PATCH] opcodes 'OP_GETTABUP'/'OP_SETTABUP' operate only with string keys, so they can use fast-track table access --- lcode.c | 14 ++++++++++++-- lopcodes.h | 4 +++- lvm.c | 22 +++++++++++++++------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lcode.c b/lcode.c index f48221cf..a8f196b6 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.112 2016/12/22 13:08:50 roberto Exp roberto $ +** $Id: lcode.c,v 2.113 2017/04/20 19:53:55 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -947,12 +947,22 @@ 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])); +} + + /* ** Create expression 't[k]'. 't' must have its final result already in a -** register or upvalue. +** register or upvalue. Upvalues can only be indexed by literal strings. */ 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; diff --git a/lopcodes.h b/lopcodes.h index afb9205a..ed3ea66d 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.149 2016/07/19 17:12:21 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.150 2017/04/20 19:53:55 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -255,6 +255,8 @@ 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/lvm.c b/lvm.c index a15ebe56..e1268567 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.270 2017/04/11 18:41:09 roberto Exp roberto $ +** $Id: lvm.c,v 2.271 2017/04/20 19:53:55 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -838,9 +838,14 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_GETTABUP) { + const TValue *slot; TValue *upval = cl->upvals[GETARG_B(i)]->v; TValue *rc = RKC(i); - gettableProtected(L, upval, rc, ra); + TString *key = tsvalue(rc); /* key must be a string */ + if (luaV_fastget(L, upval, key, slot, luaH_getstr)) { + setobj2s(L, ra, slot); + } + else Protect(luaV_finishget(L, upval, rc, ra, slot)); vmbreak; } vmcase(OP_GETTABLE) { @@ -850,10 +855,13 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_SETTABUP) { + const TValue *slot; TValue *upval = cl->upvals[GETARG_A(i)]->v; TValue *rb = RKB(i); TValue *rc = RKC(i); - settableProtected(L, upval, rb, rc); + 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) { @@ -879,15 +887,15 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_SELF) { - const TValue *aux; + const TValue *slot; StkId rb = RB(i); TValue *rc = RKC(i); TString *key = tsvalue(rc); /* key must be a string */ setobjs2s(L, ra + 1, rb); - if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { - setobj2s(L, ra, aux); + if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { + setobj2s(L, ra, slot); } - else Protect(luaV_finishget(L, rb, rc, ra, aux)); + else Protect(luaV_finishget(L, rb, rc, ra, slot)); vmbreak; } vmcase(OP_ADD) {