فهرست منبع

Encoding of table indices (hres) must use C indices

As the encoding of array indices is (~index), 0 is encoded as -1 and
INT_MAX is encoded as INT_MIN.
Roberto Ierusalimschy 1 سال پیش
والد
کامیت
94b503d95e
4فایلهای تغییر یافته به همراه30 افزوده شده و 24 حذف شده
  1. 6 6
      ltable.c
  2. 21 15
      ltable.h
  3. 2 2
      ltests.c
  4. 1 1
      lvm.c

+ 6 - 6
ltable.c

@@ -384,7 +384,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
     int tag = *getArrTag(t, i);
     if (!tagisempty(tag)) {  /* a non-empty entry? */
       setivalue(s2v(key), i + 1);
-      farr2val(t, i + 1, tag, s2v(key + 1));
+      farr2val(t, i, tag, s2v(key + 1));
       return 1;
     }
   }
@@ -692,7 +692,7 @@ static void reinsertOldSlice (lua_State *L, Table *t, unsigned oldasize,
     int tag = *getArrTag(t, i);
     if (!tagisempty(tag)) {  /* a non-empty entry? */
       TValue aux;
-      farr2val(t, i + 1, tag, &aux);  /* copy entry into 'aux' */
+      farr2val(t, i, tag, &aux);  /* copy entry into 'aux' */
       luaH_setint(L, t, i + 1, &aux);  /* re-insert it into the table */
     }
   }
@@ -937,7 +937,7 @@ int luaH_getint (Table *t, lua_Integer key, TValue *res) {
   if (keyinarray(t, key)) {
     int tag = *getArrTag(t, key - 1);
     if (!tagisempty(tag))
-      farr2val(t, key, tag, res);
+      farr2val(t, key - 1, tag, res);
     return tag;
   }
   else
@@ -1048,11 +1048,11 @@ int luaH_psetint (Table *t, lua_Integer key, TValue *val) {
   if (keyinarray(t, key)) {
     lu_byte *tag = getArrTag(t, key - 1);
     if (!tagisempty(*tag) || checknoTM(t->metatable, TM_NEWINDEX)) {
-      fval2arr(t, key, tag, val);
+      fval2arr(t, key - 1, tag, val);
       return HOK;  /* success */
     }
     else
-      return ~cast_int(key);  /* empty slot in the array part */
+      return ~cast_int(key - 1);  /* empty slot in the array part */
   }
   else
     return finishnodeset(t, getintfromhash(t, key), val);
@@ -1126,7 +1126,7 @@ void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) {
 */
 void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
   if (keyinarray(t, key))
-    obj2arr(t, key, value);
+    obj2arr(t, key - 1, value);
   else {
     int ok = rawfinishnodeset(getintfromhash(t, key), value);
     if (!ok) {

+ 21 - 15
ltable.h

@@ -47,20 +47,20 @@
 
 
 #define luaH_fastgeti(t,k,res,tag) \
-  { Table *h = t; lua_Unsigned u = l_castS2U(k); \
-    if ((u - 1u < h->alimit)) { \
-      tag = *getArrTag(h,(u)-1u); \
+  { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \
+    if ((u < h->alimit)) { \
+      tag = *getArrTag(h, u); \
       if (!tagisempty(tag)) { farr2val(h, u, tag, res); }} \
-    else { tag = luaH_getint(h, u, res); }}
+    else { tag = luaH_getint(h, (k), res); }}
 
 
 #define luaH_fastseti(t,k,val,hres) \
-  { Table *h = t; lua_Unsigned u = l_castS2U(k); \
-    if ((u - 1u < h->alimit)) { \
-      lu_byte *tag = getArrTag(h,(u)-1u); \
+  { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \
+    if ((u < h->alimit)) { \
+      lu_byte *tag = getArrTag(h, u); \
       if (tagisempty(*tag)) hres = ~cast_int(u); \
       else { fval2arr(h, u, tag, val); hres = HOK; }} \
-    else { hres = luaH_psetint(h, u, val); }}
+    else { hres = luaH_psetint(h, k, val); }}
 
 
 /* results from pset */
@@ -82,6 +82,12 @@
 ** in the array part, the encoding is (~array index), a negative value.
 ** The value HNOTATABLE is used by the fast macros to signal that the
 ** value being indexed is not a table.
+** (The size for the array part is limited by the maximum power of two
+** that fits in an unsigned integer; that is INT_MAX+1. So, the C-index
+** ranges from 0, which encodes to -1, to INT_MAX, which encodes to
+** INT_MIN. The size of the hash part is limited by the maximum power of
+** two that fits in a signed integer; that is (INT_MAX+1)/2. So, it is
+** safe to add HFIRSTNODE to any index there.)
 */
 
 
@@ -102,21 +108,21 @@
 ** and 'getArrVal'.
 */
 
-/* Computes the address of the tag for the abstract index 'k' */
+/* Computes the address of the tag for the abstract C-index 'k' */
 #define getArrTag(t,k)	(cast(lu_byte*, (t)->array) + (k))
 
-/* Computes the address of the value for the abstract index 'k' */
+/* Computes the address of the value for the abstract C-index 'k' */
 #define getArrVal(t,k)	((t)->array - 1 - (k))
 
 
 /*
-** Move TValues to/from arrays, using Lua indices
+** Move TValues to/from arrays, using C indices
 */
 #define arr2obj(h,k,val)  \
-  ((val)->tt_ = *getArrTag(h,(k)-1u), (val)->value_ = *getArrVal(h,(k)-1u))
+  ((val)->tt_ = *getArrTag(h,(k)), (val)->value_ = *getArrVal(h,(k)))
 
 #define obj2arr(h,k,val)  \
-  (*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
+  (*getArrTag(h,(k)) = (val)->tt_, *getArrVal(h,(k)) = (val)->value_)
 
 
 /*
@@ -125,10 +131,10 @@
 ** precomputed tag value or address as an extra argument.
 */
 #define farr2val(h,k,tag,res)  \
-  ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,(k)-1u))
+  ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,(k)))
 
 #define fval2arr(h,k,tag,val)  \
-  (*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
+  (*tag = (val)->tt_, *getArrVal(h,(k)) = (val)->value_)
 
 
 LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);

+ 2 - 2
ltests.c

@@ -365,7 +365,7 @@ static void checktable (global_State *g, Table *h) {
   checkobjrefN(g, hgc, h->metatable);
   for (i = 0; i < asize; i++) {
     TValue aux;
-    arr2obj(h, i + 1, &aux);
+    arr2obj(h, i, &aux);
     checkvalref(g, hgc, &aux);
   }
   for (n = gnode(h, 0); n < limit; n++) {
@@ -1010,7 +1010,7 @@ static int table_query (lua_State *L) {
   }
   else if (cast_uint(i) < asize) {
     lua_pushinteger(L, i);
-    arr2obj(t, i + 1, s2v(L->top.p));
+    arr2obj(t, i, s2v(L->top.p));
     api_incr_top(L);
     lua_pushnil(L);
   }

+ 1 - 1
lvm.c

@@ -1857,7 +1857,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           luaH_resizearray(L, h, last);  /* preallocate it at once */
         for (; n > 0; n--) {
           TValue *val = s2v(ra + n);
-          obj2arr(h, last, val);
+          obj2arr(h, last - 1, val);
           last--;
           luaC_barrierback(L, obj2gco(h), val);
         }