Просмотр исходного кода

'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.)
Roberto Ierusalimschy 1 год назад
Родитель
Сommit
ce6f5502c9
9 измененных файлов с 124 добавлено и 122 удалено
  1. 30 31
      lapi.c
  2. 2 3
      lcode.c
  3. 2 2
      ldump.c
  4. 19 0
      lobject.h
  5. 18 35
      ltable.c
  6. 13 16
      ltable.h
  7. 1 2
      lundump.c
  8. 28 26
      lvm.c
  9. 11 7
      lvm.h

+ 30 - 31
lapi.c

@@ -666,47 +666,45 @@ LUA_API int lua_pushthread (lua_State *L) {
 
 
 static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
-  int hres;
+  TValue aux;
   TString *str = luaS_new(L, k);
-  luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, hres);
-  if (hres == HOK) {
+  luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, aux);
+  if (!isemptyV(aux)) {
     api_incr_top(L);
   }
   else {
     setsvalue2s(L, L->top.p, str);
     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);
   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);
-  int hres = luaH_getint(registry, LUA_RIDX_GLOBALS, gt);
-  (void)hres;  /* avoid warnings (not used) when checks are off */
-  api_check(L, hres == HOK, "global table must exist");
+  return luaH_getint(registry, LUA_RIDX_GLOBALS);
 }
 
 
 LUA_API int lua_getglobal (lua_State *L, const char *name) {
   TValue gt;
   lua_lock(L);
-  getGlobalTable(L, &gt);
+  gt = getGlobalTable(L);
   return auxgetstr(L, &gt, name);
 }
 
 
 LUA_API int lua_gettable (lua_State *L, int idx) {
-  int hres;
+  TValue aux;
   TValue *t;
   lua_lock(L);
   api_checkpop(L, 1);
   t = index2value(L, idx);
-  luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, hres);
-  if (hres != HOK)
-    luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, hres);
+  luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, aux);
+  if (isemptyV(aux))
+    luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, aux);
   lua_unlock(L);
   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) {
   TValue *t;
-  int hres;
+  TValue aux;
   lua_lock(L);
   t = index2value(L, idx);
-  luaV_fastgeti(t, n, s2v(L->top.p), hres);
-  if (hres != HOK) {
+  luaV_fastgeti(t, n, s2v(L->top.p), aux);
+  if (isemptyV(aux)) {
     TValue key;
     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);
   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) {
-  if (hres != HOK)  /* avoid copying empty items to the stack */
+l_sinline int finishrawget (lua_State *L, TValue res) {
+  if (isemptyV(res))  /* avoid copying empty items to the stack */
     setnilvalue(s2v(L->top.p));
+  else
+    setobjV(L, s2v(L->top.p), res);
   api_incr_top(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) {
   Table *t;
+  TValue res;
   lua_lock(L);
   api_checkpop(L, 1);
   t = gettable(L, idx);
-  if (luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)) != HOK)
-    setnilvalue(s2v(L->top.p - 1));
-  lua_unlock(L);
-  return ttype(s2v(L->top.p - 1));
+  res = luaH_get(t, s2v(L->top.p - 1));
+  L->top.p--;  /* pop key */
+  return finishrawget(L, res);
 }
 
 
 LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
   Table *t;
-  int hres;
+  TValue aux;
   lua_lock(L);
   t = gettable(L, idx);
-  luaH_fastgeti(t, n, s2v(L->top.p), hres);
-  return finishrawget(L, hres);
+  luaH_fastgeti(t, n, s2v(L->top.p), aux);
+  return finishrawget(L, aux);
 }
 
 
@@ -779,7 +779,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
   lua_lock(L);
   t = gettable(L, idx);
   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) {
   TValue gt;
   lua_lock(L);  /* unlock done in 'auxsetstr' */
-  getGlobalTable(L, &gt);
+  gt = getGlobalTable(L);
   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 */
     if (f->nupvalues >= 1) {  /* does it have an upvalue? */
       /* get global table from registry */
-      TValue gt;
-      getGlobalTable(L, &gt);
+      TValue gt = getGlobalTable(L);
       /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
       setobj(L, f->upvals[0]->v.p, &gt);
       luaC_barrier(L, f->upvals[0], &gt);

+ 2 - 3
lcode.c

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

+ 2 - 2
ldump.c

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

+ 19 - 0
lobject.h

@@ -75,6 +75,7 @@ typedef struct TValue {
 
 /* raw type tag of a TValue */
 #define rawtt(o)	((o)->tt_)
+#define rawttV(o)	((o).tt_)
 
 /* tag with no variants (bits 0-3) */
 #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) */
 #define withvariant(t)	((t) & 0x3F)
 #define ttypetag(o)	withvariant(rawtt(o))
+#define ttypetagV(o)	withvariant(rawttV(o))
 
 /* type of a TValue */
 #define ttype(o)	(novariant(rawtt(o)))
+#define ttypeV(o)	(novariant(rawttV(o)))
 
 
 /* Macros to test type */
 #define checktag(o,t)		(rawtt(o) == (t))
+#define checktagV(o,t)		(rawttV(o) == (t))
 #define checktype(o,t)		(ttype(o) == (t))
+#define checktypeV(o,t)		(ttypeV(o) == (t))
 
 
 /* Macros for internal tests */
@@ -112,6 +117,7 @@ typedef struct TValue {
 
 /* set a value's tag */
 #define settt_(o,t)	((o)->tt_=(t))
+#define setttV_(o,t)	((o).tt_=(t))
 
 
 /* main macro to copy values (from 'obj2' to 'obj1') */
@@ -120,6 +126,11 @@ typedef struct TValue {
           io1->value_ = io2->value_; settt_(io1, io2->tt_); \
 	  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.
 ** (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) */
 #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 */
 #define ttisnil(v)		checktype((v), LUA_TNIL)
+#define ttisnilV(v)		checktypeV((v), LUA_TNIL)
 
 #define tagisempty(tag)		(novariant(tag) == LUA_TNIL)
 
@@ -217,6 +234,7 @@ typedef union {
 ** be accepted as empty.)
 */
 #define isempty(v)		ttisnil(v)
+#define isemptyV(v)		checktypeV((v), LUA_TNIL)
 
 
 /* macro defining a value corresponding to an absent key */
@@ -328,6 +346,7 @@ typedef struct GCObject {
 #define ttisnumber(o)		checktype((o), LUA_TNUMBER)
 #define ttisfloat(o)		checktag((o), LUA_VNUMFLT)
 #define ttisinteger(o)		checktag((o), LUA_VNUMINT)
+#define ttisintegerV(o)		checktagV((o), LUA_VNUMINT)
 
 #define nvalue(o)	check_exp(ttisnumber(o), \
 	(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))

+ 18 - 35
ltable.c

@@ -904,28 +904,14 @@ static int hashkeyisempty (Table *t, lua_Integer key) {
 }
 
 
-static int finishnodeget (const TValue *val, TValue *res) {
-  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) {
+TValue luaH_getint (Table *t, lua_Integer key) {
   if (keyinarray(t, key)) {
-    int tag = *getArrTag(t, key - 1);
-    if (!tagisempty(tag)) {
-      farr2val(t, key, tag, res);
-      return HOK;  /* success */
-    }
-    else
-      return ~cast_int(key);  /* empty slot in the array part */
+    TValue res;
+    arr2objV(t, key, res);
+    return res;
   }
-  else
-    return finishnodeget(getintfromhash(t, key), res);
+  else 
+    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) {
-  return finishnodeget(luaH_Hgetshortstr(t, key), res);
+TValue luaH_getshortstr (Table *t, TString *key) {
+  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) {
-  return finishnodeget(Hgetstr(t, key), res);
+TValue luaH_getstr (Table *t, TString *key) {
+  return *Hgetstr(t, key);
 }
 
 
@@ -981,34 +967,31 @@ TString *luaH_getstrkey (Table *t, TString *key) {
 /*
 ** main search function
 */
-int luaH_get (Table *t, const TValue *key, TValue *res) {
-  const TValue *slot;
+TValue luaH_get (Table *t, const TValue *key) {
   switch (ttypetag(key)) {
     case LUA_VSHRSTR:
-      slot = luaH_Hgetshortstr(t, tsvalue(key));
+      return *luaH_Hgetshortstr(t, tsvalue(key));
       break;
     case LUA_VNUMINT:
-      return luaH_getint(t, ivalue(key), res);
+      return luaH_getint(t, ivalue(key));
     case LUA_VNIL:
-      slot = &absentkey;
+      return absentkey;
       break;
     case LUA_VNUMFLT: {
       lua_Integer k;
       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... */
     }  /* FALLTHROUGH */
     default:
-      slot = getgeneric(t, key, 0);
-      break;
+      return *getgeneric(t, key, 0);
   }
-  return finishnodeget(slot, res);
 }
 
 
 static int finishnodeset (Table *t, const TValue *slot, TValue *val) {
   if (!ttisnil(slot)) {
-    setobj(((lua_State*)NULL), cast(TValue*, slot), val);
+    setobj(cast(lua_State*, NULL), cast(TValue*, slot), val);
     return HOK;  /* success */
   }
   else if (isabstkey(slot))
@@ -1022,7 +1005,7 @@ static int rawfinishnodeset (const TValue *slot, TValue *val) {
   if (isabstkey(slot))
     return 0;  /* no slot with that key */
   else {
-    setobj(((lua_State*)NULL), cast(TValue*, slot), val);
+    setobj(cast(lua_State*, NULL), cast(TValue*, slot), val);
     return 1;  /* success */
   }
 }

+ 13 - 16
ltable.h

@@ -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); \
-    if ((u - 1u < h->alimit)) { \
-      int tag = *getArrTag(h,(u)-1u); \
-      if (tagisempty(tag)) hres = HNOTFOUND; \
-      else { farr2val(h, u, tag, res); hres = HOK; }} \
-    else { hres = luaH_getint(h, u, res); }}
+    if ((u - 1u < h->alimit)) arr2objV(h,u,aux); \
+    else aux = luaH_getint(h, u); \
+    if (!isemptyV(aux)) setobjV(cast(lua_State*, NULL), res, aux); }
 
 
 #define luaH_fastseti(t,k,val,hres) \
@@ -64,15 +62,13 @@
     else { hres = luaH_psetint(h, u, val); }}
 
 
-/* results from get/pset */
+/* results from pset */
 #define HOK		0
 #define HNOTFOUND	1
 #define HNOTATABLE	2
 #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
 ** HOK, unless the original value is absent. In that case, if the key
 ** 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
 */
-#define arr2obj(h,k,val)  \
-  ((val)->tt_ = *getArrTag(h,(k)-1u), (val)->value_ = *getArrVal(h,(k)-1u))
+#define arr2objV(h,k,val)  \
+  ((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)  \
   (*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_)
 
 
-LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);
-LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res);
-LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res);
-LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res);
+LUAI_FUNC TValue luaH_get (Table *t, const TValue *key);
+LUAI_FUNC TValue luaH_getshortstr (Table *t, TString *key);
+LUAI_FUNC TValue luaH_getstr (Table *t, TString *key);
+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 TString *luaH_getstrkey (Table *t, TString *key);

+ 1 - 2
lundump.c

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

+ 28 - 26
lvm.c

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

+ 11 - 7
lvm.h

@@ -78,17 +78,19 @@ typedef enum {
 /*
 ** fast track for 'gettable'
 */
-#define luaV_fastget(t,k,res,f, hres) \
-  (hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, res)))
+#define luaV_fastget(t,k,res,f, aux) \
+  {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
 ** of 'luaH_getint'.
 */
-#define luaV_fastgeti(t,k,res,hres) \
-  if (!ttistable(t)) hres = HNOTATABLE; \
-  else { luaH_fastgeti(hvalue(t), k, res, hres); }
+#define luaV_fastgeti(t,k,res,aux) \
+  { if (!ttistable(t)) setnotableV(aux); \
+  else { luaH_fastgeti(hvalue(t), k, res, aux); } }
 
 
 #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,
                                 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,
-                                             StkId val, int aux);
+#define luaV_finishget(L,t,key,val,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,
                                              TValue *val, int aux);
 LUAI_FUNC void luaV_finishOp (lua_State *L);