'luaH_get' functions return 'TValue'

Instead of receiving a parameter telling them where to put the result
of the query, these functions return the TValue directly. (That is,
they return a structure.)
This commit is contained in:
Roberto Ierusalimschy 2024-03-18 15:56:32 -03:00
parent ba71060381
commit ce6f5502c9
9 changed files with 124 additions and 122 deletions

61
lapi.c
View File

@ -666,47 +666,45 @@ LUA_API int lua_pushthread (lua_State *L) {
static int auxgetstr (lua_State *L, const TValue *t, const char *k) { static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
int hres; TValue aux;
TString *str = luaS_new(L, k); TString *str = luaS_new(L, k);
luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, hres); luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, aux);
if (hres == HOK) { if (!isemptyV(aux)) {
api_incr_top(L); api_incr_top(L);
} }
else { else {
setsvalue2s(L, L->top.p, str); setsvalue2s(L, L->top.p, str);
api_incr_top(L); api_incr_top(L);
luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, hres); luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, aux);
} }
lua_unlock(L); lua_unlock(L);
return ttype(s2v(L->top.p - 1)); return ttype(s2v(L->top.p - 1));
} }
static void getGlobalTable (lua_State *L, TValue *gt) { static TValue getGlobalTable (lua_State *L) {
Table *registry = hvalue(&G(L)->l_registry); Table *registry = hvalue(&G(L)->l_registry);
int hres = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); return luaH_getint(registry, LUA_RIDX_GLOBALS);
(void)hres; /* avoid warnings (not used) when checks are off */
api_check(L, hres == HOK, "global table must exist");
} }
LUA_API int lua_getglobal (lua_State *L, const char *name) { LUA_API int lua_getglobal (lua_State *L, const char *name) {
TValue gt; TValue gt;
lua_lock(L); lua_lock(L);
getGlobalTable(L, &gt); gt = getGlobalTable(L);
return auxgetstr(L, &gt, name); return auxgetstr(L, &gt, name);
} }
LUA_API int lua_gettable (lua_State *L, int idx) { LUA_API int lua_gettable (lua_State *L, int idx) {
int hres; TValue aux;
TValue *t; TValue *t;
lua_lock(L); lua_lock(L);
api_checkpop(L, 1); api_checkpop(L, 1);
t = index2value(L, idx); t = index2value(L, idx);
luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, hres); luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, aux);
if (hres != HOK) if (isemptyV(aux))
luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, hres); luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, aux);
lua_unlock(L); lua_unlock(L);
return ttype(s2v(L->top.p - 1)); return ttype(s2v(L->top.p - 1));
} }
@ -720,14 +718,14 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
TValue *t; TValue *t;
int hres; TValue aux;
lua_lock(L); lua_lock(L);
t = index2value(L, idx); t = index2value(L, idx);
luaV_fastgeti(t, n, s2v(L->top.p), hres); luaV_fastgeti(t, n, s2v(L->top.p), aux);
if (hres != HOK) { if (isemptyV(aux)) {
TValue key; TValue key;
setivalue(&key, n); setivalue(&key, n);
luaV_finishget(L, t, &key, L->top.p, hres); luaV_finishget(L, t, &key, L->top.p, aux);
} }
api_incr_top(L); api_incr_top(L);
lua_unlock(L); lua_unlock(L);
@ -735,12 +733,14 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
} }
l_sinline int finishrawget (lua_State *L, int hres) { l_sinline int finishrawget (lua_State *L, TValue res) {
if (hres != HOK) /* avoid copying empty items to the stack */ if (isemptyV(res)) /* avoid copying empty items to the stack */
setnilvalue(s2v(L->top.p)); setnilvalue(s2v(L->top.p));
else
setobjV(L, s2v(L->top.p), res);
api_incr_top(L); api_incr_top(L);
lua_unlock(L); lua_unlock(L);
return ttype(s2v(L->top.p - 1)); return ttypeV(res);
} }
@ -753,23 +753,23 @@ l_sinline Table *gettable (lua_State *L, int idx) {
LUA_API int lua_rawget (lua_State *L, int idx) { LUA_API int lua_rawget (lua_State *L, int idx) {
Table *t; Table *t;
TValue res;
lua_lock(L); lua_lock(L);
api_checkpop(L, 1); api_checkpop(L, 1);
t = gettable(L, idx); t = gettable(L, idx);
if (luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)) != HOK) res = luaH_get(t, s2v(L->top.p - 1));
setnilvalue(s2v(L->top.p - 1)); L->top.p--; /* pop key */
lua_unlock(L); return finishrawget(L, res);
return ttype(s2v(L->top.p - 1));
} }
LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
Table *t; Table *t;
int hres; TValue aux;
lua_lock(L); lua_lock(L);
t = gettable(L, idx); t = gettable(L, idx);
luaH_fastgeti(t, n, s2v(L->top.p), hres); luaH_fastgeti(t, n, s2v(L->top.p), aux);
return finishrawget(L, hres); return finishrawget(L, aux);
} }
@ -779,7 +779,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
lua_lock(L); lua_lock(L);
t = gettable(L, idx); t = gettable(L, idx);
setpvalue(&k, cast_voidp(p)); setpvalue(&k, cast_voidp(p));
return finishrawget(L, luaH_get(t, &k, s2v(L->top.p))); return finishrawget(L, luaH_get(t, &k));
} }
@ -872,7 +872,7 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
LUA_API void lua_setglobal (lua_State *L, const char *name) { LUA_API void lua_setglobal (lua_State *L, const char *name) {
TValue gt; TValue gt;
lua_lock(L); /* unlock done in 'auxsetstr' */ lua_lock(L); /* unlock done in 'auxsetstr' */
getGlobalTable(L, &gt); gt = getGlobalTable(L);
auxsetstr(L, &gt, name); auxsetstr(L, &gt, name);
} }
@ -1122,8 +1122,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */
if (f->nupvalues >= 1) { /* does it have an upvalue? */ if (f->nupvalues >= 1) { /* does it have an upvalue? */
/* get global table from registry */ /* get global table from registry */
TValue gt; TValue gt = getGlobalTable(L);
getGlobalTable(L, &gt);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[0]->v.p, &gt); setobj(L, f->upvals[0]->v.p, &gt);
luaC_barrier(L, f->upvals[0], &gt); luaC_barrier(L, f->upvals[0], &gt);

View File

@ -541,12 +541,11 @@ static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) {
** a function can make some indices wrong. ** a function can make some indices wrong.
*/ */
static int addk (FuncState *fs, TValue *key, TValue *v) { static int addk (FuncState *fs, TValue *key, TValue *v) {
TValue val;
lua_State *L = fs->ls->L; lua_State *L = fs->ls->L;
Proto *f = fs->f; Proto *f = fs->f;
int aux = luaH_get(fs->ls->h, key, &val); /* query scanner table */ TValue val = luaH_get(fs->ls->h, key); /* query scanner table */
int k, oldsize; int k, oldsize;
if (aux == HOK && ttisinteger(&val)) { /* is there an index there? */ if (ttisintegerV(val)) { /* is there an index there? */
k = cast_int(ivalue(&val)); k = cast_int(ivalue(&val));
/* correct value? (warning: must distinguish floats from integers!) */ /* correct value? (warning: must distinguish floats from integers!) */
if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) &&

View File

@ -132,8 +132,8 @@ static void dumpString (DumpState *D, TString *ts) {
if (ts == NULL) if (ts == NULL)
dumpSize(D, 0); dumpSize(D, 0);
else { else {
TValue idx; TValue idx = luaH_getstr(D->h, ts);
if (luaH_getstr(D->h, ts, &idx) == HOK) { /* string already saved? */ if (!isemptyV(idx)) { /* string already saved? */
dumpSize(D, 1); /* reuse a saved string */ dumpSize(D, 1); /* reuse a saved string */
dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */
} }

View File

@ -75,6 +75,7 @@ typedef struct TValue {
/* raw type tag of a TValue */ /* raw type tag of a TValue */
#define rawtt(o) ((o)->tt_) #define rawtt(o) ((o)->tt_)
#define rawttV(o) ((o).tt_)
/* tag with no variants (bits 0-3) */ /* tag with no variants (bits 0-3) */
#define novariant(t) ((t) & 0x0F) #define novariant(t) ((t) & 0x0F)
@ -82,14 +83,18 @@ typedef struct TValue {
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define withvariant(t) ((t) & 0x3F) #define withvariant(t) ((t) & 0x3F)
#define ttypetag(o) withvariant(rawtt(o)) #define ttypetag(o) withvariant(rawtt(o))
#define ttypetagV(o) withvariant(rawttV(o))
/* type of a TValue */ /* type of a TValue */
#define ttype(o) (novariant(rawtt(o))) #define ttype(o) (novariant(rawtt(o)))
#define ttypeV(o) (novariant(rawttV(o)))
/* Macros to test type */ /* Macros to test type */
#define checktag(o,t) (rawtt(o) == (t)) #define checktag(o,t) (rawtt(o) == (t))
#define checktagV(o,t) (rawttV(o) == (t))
#define checktype(o,t) (ttype(o) == (t)) #define checktype(o,t) (ttype(o) == (t))
#define checktypeV(o,t) (ttypeV(o) == (t))
/* Macros for internal tests */ /* Macros for internal tests */
@ -112,6 +117,7 @@ typedef struct TValue {
/* set a value's tag */ /* set a value's tag */
#define settt_(o,t) ((o)->tt_=(t)) #define settt_(o,t) ((o)->tt_=(t))
#define setttV_(o,t) ((o).tt_=(t))
/* main macro to copy values (from 'obj2' to 'obj1') */ /* main macro to copy values (from 'obj2' to 'obj1') */
@ -120,6 +126,11 @@ typedef struct TValue {
io1->value_ = io2->value_; settt_(io1, io2->tt_); \ io1->value_ = io2->value_; settt_(io1, io2->tt_); \
checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
#define setobjV(L,obj1,obj2) \
{ TValue *io1=(obj1); const TValue io2=(obj2); \
io1->value_ = io2.value_; settt_(io1, io2.tt_); \
checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
/* /*
** Different types of assignments, according to source and destination. ** Different types of assignments, according to source and destination.
** (They are mostly equal now, but may be different in the future.) ** (They are mostly equal now, but may be different in the future.)
@ -188,9 +199,15 @@ typedef union {
/* Value returned for a key not found in a table (absent key) */ /* Value returned for a key not found in a table (absent key) */
#define LUA_VABSTKEY makevariant(LUA_TNIL, 2) #define LUA_VABSTKEY makevariant(LUA_TNIL, 2)
/* Special "value" to signal that a fast get is accessing a non-table */
#define LUA_VNOTABLE makevariant(LUA_TNIL, 3)
#define setnotableV(obj) setttV_(obj, LUA_VNOTABLE)
/* macro to test for (any kind of) nil */ /* macro to test for (any kind of) nil */
#define ttisnil(v) checktype((v), LUA_TNIL) #define ttisnil(v) checktype((v), LUA_TNIL)
#define ttisnilV(v) checktypeV((v), LUA_TNIL)
#define tagisempty(tag) (novariant(tag) == LUA_TNIL) #define tagisempty(tag) (novariant(tag) == LUA_TNIL)
@ -217,6 +234,7 @@ typedef union {
** be accepted as empty.) ** be accepted as empty.)
*/ */
#define isempty(v) ttisnil(v) #define isempty(v) ttisnil(v)
#define isemptyV(v) checktypeV((v), LUA_TNIL)
/* macro defining a value corresponding to an absent key */ /* macro defining a value corresponding to an absent key */
@ -328,6 +346,7 @@ typedef struct GCObject {
#define ttisnumber(o) checktype((o), LUA_TNUMBER) #define ttisnumber(o) checktype((o), LUA_TNUMBER)
#define ttisfloat(o) checktag((o), LUA_VNUMFLT) #define ttisfloat(o) checktag((o), LUA_VNUMFLT)
#define ttisinteger(o) checktag((o), LUA_VNUMINT) #define ttisinteger(o) checktag((o), LUA_VNUMINT)
#define ttisintegerV(o) checktagV((o), LUA_VNUMINT)
#define nvalue(o) check_exp(ttisnumber(o), \ #define nvalue(o) check_exp(ttisnumber(o), \
(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))

View File

@ -904,28 +904,14 @@ static int hashkeyisempty (Table *t, lua_Integer key) {
} }
static int finishnodeget (const TValue *val, TValue *res) { TValue luaH_getint (Table *t, lua_Integer key) {
if (!ttisnil(val)) {
setobj(((lua_State*)NULL), res, val);
return HOK; /* success */
}
else
return HNOTFOUND; /* could not get value */
}
int luaH_getint (Table *t, lua_Integer key, TValue *res) {
if (keyinarray(t, key)) { if (keyinarray(t, key)) {
int tag = *getArrTag(t, key - 1); TValue res;
if (!tagisempty(tag)) { arr2objV(t, key, res);
farr2val(t, key, tag, res); return res;
return HOK; /* success */
}
else
return ~cast_int(key); /* empty slot in the array part */
} }
else else
return finishnodeget(getintfromhash(t, key), res); return *getintfromhash(t, key);
} }
@ -948,8 +934,8 @@ const TValue *luaH_Hgetshortstr (Table *t, TString *key) {
} }
int luaH_getshortstr (Table *t, TString *key, TValue *res) { TValue luaH_getshortstr (Table *t, TString *key) {
return finishnodeget(luaH_Hgetshortstr(t, key), res); return *luaH_Hgetshortstr(t, key);
} }
@ -964,8 +950,8 @@ static const TValue *Hgetstr (Table *t, TString *key) {
} }
int luaH_getstr (Table *t, TString *key, TValue *res) { TValue luaH_getstr (Table *t, TString *key) {
return finishnodeget(Hgetstr(t, key), res); return *Hgetstr(t, key);
} }
@ -981,34 +967,31 @@ TString *luaH_getstrkey (Table *t, TString *key) {
/* /*
** main search function ** main search function
*/ */
int luaH_get (Table *t, const TValue *key, TValue *res) { TValue luaH_get (Table *t, const TValue *key) {
const TValue *slot;
switch (ttypetag(key)) { switch (ttypetag(key)) {
case LUA_VSHRSTR: case LUA_VSHRSTR:
slot = luaH_Hgetshortstr(t, tsvalue(key)); return *luaH_Hgetshortstr(t, tsvalue(key));
break; break;
case LUA_VNUMINT: case LUA_VNUMINT:
return luaH_getint(t, ivalue(key), res); return luaH_getint(t, ivalue(key));
case LUA_VNIL: case LUA_VNIL:
slot = &absentkey; return absentkey;
break; break;
case LUA_VNUMFLT: { case LUA_VNUMFLT: {
lua_Integer k; lua_Integer k;
if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */
return luaH_getint(t, k, res); /* use specialized version */ return luaH_getint(t, k); /* use specialized version */
/* else... */ /* else... */
} /* FALLTHROUGH */ } /* FALLTHROUGH */
default: default:
slot = getgeneric(t, key, 0); return *getgeneric(t, key, 0);
break;
} }
return finishnodeget(slot, res);
} }
static int finishnodeset (Table *t, const TValue *slot, TValue *val) { static int finishnodeset (Table *t, const TValue *slot, TValue *val) {
if (!ttisnil(slot)) { if (!ttisnil(slot)) {
setobj(((lua_State*)NULL), cast(TValue*, slot), val); setobj(cast(lua_State*, NULL), cast(TValue*, slot), val);
return HOK; /* success */ return HOK; /* success */
} }
else if (isabstkey(slot)) else if (isabstkey(slot))
@ -1022,7 +1005,7 @@ static int rawfinishnodeset (const TValue *slot, TValue *val) {
if (isabstkey(slot)) if (isabstkey(slot))
return 0; /* no slot with that key */ return 0; /* no slot with that key */
else { else {
setobj(((lua_State*)NULL), cast(TValue*, slot), val); setobj(cast(lua_State*, NULL), cast(TValue*, slot), val);
return 1; /* success */ return 1; /* success */
} }
} }

View File

@ -46,13 +46,11 @@
#define luaH_fastgeti(t,k,res,hres) \ #define luaH_fastgeti(t,k,res,aux) \
{ Table *h = t; lua_Unsigned u = l_castS2U(k); \ { Table *h = t; lua_Unsigned u = l_castS2U(k); \
if ((u - 1u < h->alimit)) { \ if ((u - 1u < h->alimit)) arr2objV(h,u,aux); \
int tag = *getArrTag(h,(u)-1u); \ else aux = luaH_getint(h, u); \
if (tagisempty(tag)) hres = HNOTFOUND; \ if (!isemptyV(aux)) setobjV(cast(lua_State*, NULL), res, aux); }
else { farr2val(h, u, tag, res); hres = HOK; }} \
else { hres = luaH_getint(h, u, res); }}
#define luaH_fastseti(t,k,val,hres) \ #define luaH_fastseti(t,k,val,hres) \
@ -64,15 +62,13 @@
else { hres = luaH_psetint(h, u, val); }} else { hres = luaH_psetint(h, u, val); }}
/* results from get/pset */ /* results from pset */
#define HOK 0 #define HOK 0
#define HNOTFOUND 1 #define HNOTFOUND 1
#define HNOTATABLE 2 #define HNOTATABLE 2
#define HFIRSTNODE 3 #define HFIRSTNODE 3
/* /*
** 'luaH_get*' operations set 'res' and return HOK, unless the value is
** absent. In that case, they set nothing and return HNOTFOUND.
** The 'luaH_pset*' (pre-set) operations set the given value and return ** The 'luaH_pset*' (pre-set) operations set the given value and return
** HOK, unless the original value is absent. In that case, if the key ** HOK, unless the original value is absent. In that case, if the key
** is really absent, they return HNOTFOUND. Otherwise, if there is a ** is really absent, they return HNOTFOUND. Otherwise, if there is a
@ -109,8 +105,10 @@ struct ArrayCell {
/* /*
** Move TValues to/from arrays, using Lua indices ** Move TValues to/from arrays, using Lua indices
*/ */
#define arr2obj(h,k,val) \ #define arr2objV(h,k,val) \
((val)->tt_ = *getArrTag(h,(k)-1u), (val)->value_ = *getArrVal(h,(k)-1u)) ((val).tt_ = *getArrTag(h,(k)-1u), (val).value_ = *getArrVal(h,(k)-1u))
#define arr2obj(h,k,val) arr2objV(h,k,*(val))
#define obj2arr(h,k,val) \ #define obj2arr(h,k,val) \
(*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) (*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
@ -128,12 +126,11 @@ struct ArrayCell {
(*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) (*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res); LUAI_FUNC TValue luaH_get (Table *t, const TValue *key);
LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res); LUAI_FUNC TValue luaH_getshortstr (Table *t, TString *key);
LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res); LUAI_FUNC TValue luaH_getstr (Table *t, TString *key);
LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res); LUAI_FUNC TValue luaH_getint (Table *t, lua_Integer key);
/* Special get for metamethods */
LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key);
LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key); LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key);

View File

@ -149,8 +149,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
} }
else if (size == 1) { /* previously saved string? */ else if (size == 1) { /* previously saved string? */
lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */ lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */
TValue stv; TValue stv = luaH_getint(S->h, idx); /* get its value */
luaH_getint(S->h, idx, &stv); /* get its value */
*sl = ts = tsvalue(&stv); *sl = ts = tsvalue(&stv);
luaC_objbarrier(L, p, ts); luaC_objbarrier(L, p, ts);
return; /* do not save it again */ return; /* do not save it again */

54
lvm.c
View File

@ -287,12 +287,13 @@ static int floatforloop (StkId ra) {
/* /*
** Finish the table access 'val = t[key]'. ** Finish the table access 'val = t[key]'.
*/ */
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key, StkId val,
int hres) { int tag) {
int loop; /* counter to avoid infinite loops */ int loop; /* counter to avoid infinite loops */
const TValue *tm; /* metamethod */ const TValue *tm; /* metamethod */
TValue aux;
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
if (hres == HNOTATABLE) { /* 't' is not a table? */ if (tag == LUA_VNOTABLE) { /* 't' is not a table? */
lua_assert(!ttistable(t)); lua_assert(!ttistable(t));
tm = luaT_gettmbyobj(L, t, TM_INDEX); tm = luaT_gettmbyobj(L, t, TM_INDEX);
if (l_unlikely(notm(tm))) if (l_unlikely(notm(tm)))
@ -312,10 +313,11 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
return; return;
} }
t = tm; /* else try to access 'tm[key]' */ t = tm; /* else try to access 'tm[key]' */
luaV_fastget(t, key, s2v(val), luaH_get, hres); luaV_fastget(t, key, s2v(val), luaH_get, aux);
if (hres == HOK) if (!isemptyV(aux))
return; /* done */ return; /* done */
/* else repeat (tail call 'luaV_finishget') */ /* else repeat (tail call 'luaV_finishget') */
tag = ttypetagV(aux);
} }
luaG_runerror(L, "'__index' chain too long; possible loop"); luaG_runerror(L, "'__index' chain too long; possible loop");
} }
@ -1245,36 +1247,36 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *upval = cl->upvals[GETARG_B(i)]->v.p; TValue *upval = cl->upvals[GETARG_B(i)]->v.p;
TValue *rc = KC(i); TValue *rc = KC(i);
TString *key = tsvalue(rc); /* key must be a short string */ TString *key = tsvalue(rc); /* key must be a short string */
int hres; TValue aux;
luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, hres); luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, aux);
if (hres != HOK) if (isemptyV(aux))
Protect(luaV_finishget(L, upval, rc, ra, hres)); Protect(luaV_finishget(L, upval, rc, ra, aux));
vmbreak; vmbreak;
} }
vmcase(OP_GETTABLE) { vmcase(OP_GETTABLE) {
StkId ra = RA(i); StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = vRC(i); TValue *rc = vRC(i);
int hres; TValue aux;
if (ttisinteger(rc)) { /* fast track for integers? */ if (ttisinteger(rc)) { /* fast track for integers? */
luaV_fastgeti(rb, ivalue(rc), s2v(ra), hres); luaV_fastgeti(rb, ivalue(rc), s2v(ra), aux);
} }
else else
luaV_fastget(rb, rc, s2v(ra), luaH_get, hres); luaV_fastget(rb, rc, s2v(ra), luaH_get, aux);
if (hres != HOK) /* fast track for integers? */ if (isemptyV(aux)) /* fast track for integers? */
Protect(luaV_finishget(L, rb, rc, ra, hres)); Protect(luaV_finishget(L, rb, rc, ra, aux));
vmbreak; vmbreak;
} }
vmcase(OP_GETI) { vmcase(OP_GETI) {
StkId ra = RA(i); StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
int c = GETARG_C(i); int c = GETARG_C(i);
int hres; TValue aux;
luaV_fastgeti(rb, c, s2v(ra), hres); luaV_fastgeti(rb, c, s2v(ra), aux);
if (hres != HOK) { if (isemptyV(aux)) {
TValue key; TValue key;
setivalue(&key, c); setivalue(&key, c);
Protect(luaV_finishget(L, rb, &key, ra, hres)); Protect(luaV_finishget(L, rb, &key, ra, aux));
} }
vmbreak; vmbreak;
} }
@ -1283,10 +1285,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = KC(i); TValue *rc = KC(i);
TString *key = tsvalue(rc); /* key must be a short string */ TString *key = tsvalue(rc); /* key must be a short string */
int hres; TValue aux;
luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, hres); luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, aux);
if (hres != HOK) if (isemptyV(aux))
Protect(luaV_finishget(L, rb, rc, ra, hres)); Protect(luaV_finishget(L, rb, rc, ra, aux));
vmbreak; vmbreak;
} }
vmcase(OP_SETTABUP) { vmcase(OP_SETTABUP) {
@ -1368,14 +1370,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
vmcase(OP_SELF) { vmcase(OP_SELF) {
StkId ra = RA(i); StkId ra = RA(i);
int hres; TValue aux;
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = RKC(i); TValue *rc = RKC(i);
TString *key = tsvalue(rc); /* key must be a string */ TString *key = tsvalue(rc); /* key must be a string */
setobj2s(L, ra + 1, rb); setobj2s(L, ra + 1, rb);
luaV_fastget(rb, key, s2v(ra), luaH_getstr, hres); luaV_fastget(rb, key, s2v(ra), luaH_getstr, aux);
if (hres != HOK) if (isemptyV(aux))
Protect(luaV_finishget(L, rb, rc, ra, hres)); Protect(luaV_finishget(L, rb, rc, ra, aux));
vmbreak; vmbreak;
} }
vmcase(OP_ADDI) { vmcase(OP_ADDI) {

18
lvm.h
View File

@ -78,17 +78,19 @@ typedef enum {
/* /*
** fast track for 'gettable' ** fast track for 'gettable'
*/ */
#define luaV_fastget(t,k,res,f, hres) \ #define luaV_fastget(t,k,res,f, aux) \
(hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, res))) {if (!ttistable(t)) setnotableV(aux); \
else { aux = f(hvalue(t), k); \
if (!isemptyV(aux)) { setobjV(cast(lua_State*, NULL), res, aux); } } }
/* /*
** Special case of 'luaV_fastget' for integers, inlining the fast case ** Special case of 'luaV_fastget' for integers, inlining the fast case
** of 'luaH_getint'. ** of 'luaH_getint'.
*/ */
#define luaV_fastgeti(t,k,res,hres) \ #define luaV_fastgeti(t,k,res,aux) \
if (!ttistable(t)) hres = HNOTATABLE; \ { if (!ttistable(t)) setnotableV(aux); \
else { luaH_fastgeti(hvalue(t), k, res, hres); } else { luaH_fastgeti(hvalue(t), k, res, aux); } }
#define luaV_fastset(t,k,val,hres,f) \ #define luaV_fastset(t,k,val,hres,f) \
@ -120,8 +122,10 @@ LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode);
LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
F2Imod mode); F2Imod mode);
LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, #define luaV_finishget(L,t,key,val,aux) \
StkId val, int aux); luaV_finishget_(L,t,key,val,ttypetagV(aux))
LUAI_FUNC void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key,
StkId val, int tag);
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
TValue *val, int aux); TValue *val, int aux);
LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_finishOp (lua_State *L);