commit b6f87491afe32140563fe3c546b8812c28a63410
parent 4bb30f461b146e1d189ee301472953e948699acf
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 9 Jun 2017 13:48:17 -0300
in hash nodes, keys are stored in separate pieces to avoid wasting
space with alignments
Diffstat:
M | lgc.c | | | 42 | +++++++++++++++++++++++------------------- |
M | llex.c | | | 6 | +++--- |
M | lobject.h | | | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
M | ltable.c | | | 131 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
M | ltable.h | | | 18 | ++++-------------- |
M | ltests.c | | | 16 | ++++++++++------ |
6 files changed, 201 insertions(+), 110 deletions(-)
diff --git a/lgc.c b/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.229 2017/05/26 19:14:29 roberto Exp roberto $
+** $Id: lgc.c,v 2.230 2017/06/01 19:16:34 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -73,7 +73,9 @@
#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
-#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n)))
+#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
+
+#define checkdeadkey(n) lua_assert(!keyisdead(n) || ttisnil(gval(n)))
#define checkconsistency(obj) \
@@ -83,6 +85,8 @@
#define markvalue(g,o) { checkconsistency(o); \
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
+#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
+
#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
/*
@@ -125,8 +129,8 @@ static lu_mem atomic (lua_State *L);
*/
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
- if (valiswhite(gkey(n)))
- setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */
+ if (keyiswhite(n))
+ setdeadkey(n); /* unused and unmarked key; remove it */
}
@@ -137,13 +141,13 @@ static void removeentry (Node *n) {
** other objects: if really collected, cannot keep them; for objects
** being finalized, keep them in keys, but not in values
*/
-static int iscleared (global_State *g, const TValue *o) {
- if (!iscollectable(o)) return 0;
- else if (ttisstring(o)) {
- markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */
+static int iscleared (global_State *g, const GCObject *o) {
+ if (o == NULL) return 0; /* non-collectable value */
+ else if (novariant(o->tt) == LUA_TSTRING) {
+ markobject(g, o); /* strings are 'values', so are never weak */
return 0;
}
- else return iswhite(gcvalue(o));
+ else return iswhite(o);
}
@@ -391,9 +395,9 @@ static void traverseweakvalue (global_State *g, Table *h) {
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {
- lua_assert(!ttisnil(gkey(n)));
- markvalue(g, gkey(n)); /* mark key */
- if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */
+ lua_assert(!keyisnil(n));
+ markkey(g, n);
+ if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */
hasclears = 1; /* table will have to be cleared */
}
}
@@ -433,7 +437,7 @@ static int traverseephemeron (global_State *g, Table *h) {
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
- else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */
+ else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
hasclears = 1; /* table must be cleared */
if (valiswhite(gval(n))) /* value not marked yet? */
hasww = 1; /* white-white entry */
@@ -468,9 +472,9 @@ static void traversestrongtable (global_State *g, Table *h) {
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {
- lua_assert(!ttisnil(gkey(n)));
- markvalue(g, gkey(n)); /* mark key */
- markvalue(g, gval(n)); /* mark value */
+ lua_assert(!keyisnil(n));
+ markkey(g, n);
+ markvalue(g, gval(n));
}
}
if (g->gckind == KGC_GEN) {
@@ -691,7 +695,7 @@ static void clearkeys (global_State *g, GCObject *l) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
for (n = gnode(h, 0); n < limit; n++) {
- if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
+ if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
@@ -711,11 +715,11 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
unsigned int i;
for (i = 0; i < h->sizearray; i++) {
TValue *o = &h->array[i];
- if (iscleared(g, o)) /* value was collected? */
+ if (iscleared(g, gcvalueN(o))) /* value was collected? */
setnilvalue(o); /* remove value */
}
for (n = gnode(h, 0); n < limit; n++) {
- if (iscleared(g, gval(n))) {
+ if (iscleared(g, gcvalueN(gval(n)))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
diff --git a/llex.c b/llex.c
@@ -1,5 +1,5 @@
/*
-** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp roberto $
+** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -132,12 +132,12 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
o = luaH_set(L, ls->h, L->top - 1);
if (ttisnil(o)) { /* not in use yet? */
/* boolean value does not need GC barrier;
- table has no metatable, so it does not need to invalidate cache */
+ table is not a metatable, so it does not need to invalidate cache */
setbvalue(o, 1); /* t[string] = true */
luaC_checkGC(L);
}
else { /* string already present */
- ts = tsvalue(keyfromval(o)); /* re-use value previously stored */
+ ts = keystrval(nodefromval(o)); /* re-use value previously stored */
}
L->top--; /* remove string from stack */
return ts;
diff --git a/lobject.h b/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.120 2017/04/30 20:43:26 roberto Exp roberto $
+** $Id: lobject.h,v 2.121 2017/06/01 20:24:05 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -122,6 +122,7 @@ typedef struct lua_TValue {
#define val_(o) ((o)->value_)
+#define valraw(o) (&val_(o))
/* raw type tag of a TValue */
@@ -131,7 +132,8 @@ typedef struct lua_TValue {
#define novariant(x) ((x) & 0x0F)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
-#define ttype(o) (rttype(o) & 0x3F)
+#define ttyperaw(t) ((t) & 0x3F)
+#define ttype(o) ttyperaw(rttype(o))
/* type tag of a TValue with no variants (bits 0-3) */
#define ttnov(o) (novariant(rttype(o)))
@@ -157,7 +159,19 @@ typedef struct lua_TValue {
#define ttislcf(o) checktag((o), LUA_TLCF)
#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
-#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
+
+
+/*
+** Macros to access unstructured values (may come both from
+** 'TValue's and table keys)
+*/
+#define ivalueraw(v) ((v).i)
+#define fltvalueraw(v) ((v).n)
+#define gcvalueraw(v) ((v).gc)
+#define pvalueraw(v) ((v).p)
+#define tsvalueraw(v) (gco2ts((v).gc))
+#define fvalueraw(v) ((v).f)
+#define bvalueraw(v) ((v).b)
/* Macros to access values */
@@ -176,8 +190,6 @@ typedef struct lua_TValue {
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
-/* a dead value may get the 'gc' field, but cannot access its contents */
-#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
@@ -185,6 +197,12 @@ typedef struct lua_TValue {
#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
+/*
+** Protected access to objects in values
+*/
+#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
+
+
/* Macros for internal tests */
#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)
@@ -253,8 +271,6 @@ typedef struct lua_TValue {
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(L,io); }
-#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
-
#define setobj(L,obj1,obj2) \
@@ -485,26 +501,37 @@ typedef union Closure {
** Tables
*/
-typedef union TKey {
- struct {
- TValuefields;
- int next; /* for chaining (offset for next node) */
- } nk;
- TValue tvk;
-} TKey;
+
+/*
+** Nodes for Hash tables. A pack of two TValue's (key-value pairs)
+** plus a 'next' field to link colliding entries. The distribuition
+** of the key's fields ('key_tt' and 'key_val') not forming a proper
+** 'TValue' allows for a smaller size for 'Node' both in 4-byte
+** and 8-byte alignments.
+*/
+typedef union Node {
+ struct NodeKey {
+ TValuefields; /* fields for value */
+ lu_byte key_tt; /* key type */
+ int next; /* for chaining */
+ Value key_val; /* key value */
+ } u;
+ TValue i_val; /* direct access to node's value as a proper 'TValue' */
+} Node;
-/* copy a value into a key without messing up field 'next' */
-#define setnodekey(L,key,obj) \
- { TKey *k_=(key); const TValue *io_=(obj); \
- k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
+/* copy a value into a key */
+#define setnodekey(L,node,obj) \
+ { Node *n_=(node); const TValue *io_=(obj); \
+ n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
(void)L; checkliveness(L,io_); }
-typedef struct Node {
- TValue i_val;
- TKey i_key;
-} Node;
+/* copy a value from a key */
+#define getnodekey(L,obj,node) \
+ { TValue *io_=(obj); const Node *n_=(node); \
+ io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
+ (void)L; checkliveness(L,io_); }
typedef struct Table {
@@ -520,6 +547,33 @@ typedef struct Table {
} Table;
+/*
+** Macros to manipulate keys inserted in nodes
+*/
+#define keytt(node) ((node)->u.key_tt)
+#define keyval(node) ((node)->u.key_val)
+
+#define keyisnil(node) (keytt(node) == LUA_TNIL)
+#define keyisinteger(node) (keytt(node) == LUA_TNUMINT)
+#define keyival(node) (keyval(node).i)
+#define keyisshrstr(node) (keytt(node) == ctb(LUA_TSHRSTR))
+#define keystrval(node) (gco2ts(keyval(node).gc))
+
+#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
+
+#define setnilkey(node) (keytt(node) = LUA_TNIL)
+#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
+
+/* a dead value may get the 'gc' field, but cannot access its contents */
+#define deadkey(n) \
+ check_exp(keytt(n) == LUA_TDEADKEY, cast(void *, keyval(n).gc))
+
+#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
+
+#define gckey(n) (keyval(n).gc)
+#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
+
+
/*
** 'module' operation for hashing (size is always a power of 2)
diff --git a/ltable.c b/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 2.121 2017/05/19 12:47:00 roberto Exp roberto $
+** $Id: ltable.c,v 2.122 2017/05/19 12:57:10 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -75,8 +75,8 @@
#define dummynode (&dummynode_)
static const Node dummynode_ = {
- {NILCONSTANT}, /* value */
- {{NILCONSTANT, 0}} /* key */
+ {{NULL}, LUA_TNIL, /* value's value and type */
+ LUA_TNIL, 0, {NULL}} /* key type, next, and key value */
};
@@ -111,43 +111,79 @@ static int l_hashfloat (lua_Number n) {
/*
-** returns the 'main' position of an element in a table (that is, the index
-** of its hash value)
+** returns the 'main' position of an element in a table (that is,
+** the index of its hash value). The key comes broken (tag in 'ktt'
+** and value in 'vkl') so that we can call it on keys inserted into
+** nodes.
*/
-static Node *mainposition (const Table *t, const TValue *key) {
- switch (ttype(key)) {
+static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
+ switch (ttyperaw(ktt)) {
case LUA_TNUMINT:
- return hashint(t, ivalue(key));
+ return hashint(t, ivalueraw(*kvl));
case LUA_TNUMFLT:
- return hashmod(t, l_hashfloat(fltvalue(key)));
+ return hashmod(t, l_hashfloat(fltvalueraw(*kvl)));
case LUA_TSHRSTR:
- return hashstr(t, tsvalue(key));
+ return hashstr(t, tsvalueraw(*kvl));
case LUA_TLNGSTR:
- return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
+ return hashpow2(t, luaS_hashlongstr(tsvalueraw(*kvl)));
case LUA_TBOOLEAN:
- return hashboolean(t, bvalue(key));
+ return hashboolean(t, bvalueraw(*kvl));
case LUA_TLIGHTUSERDATA:
- return hashpointer(t, pvalue(key));
+ return hashpointer(t, pvalueraw(*kvl));
case LUA_TLCF:
- return hashpointer(t, fvalue(key));
+ return hashpointer(t, fvalueraw(*kvl));
default:
- lua_assert(!ttisdeadkey(key));
- return hashpointer(t, gcvalue(key));
+ return hashpointer(t, gcvalueraw(*kvl));
}
}
+static Node *mainpositionTV (const Table *t, const TValue *key) {
+ return mainposition(t, rttype(key), valraw(key));
+}
+
+
/*
-** returns the index for 'key' if 'key' is an appropriate key to live in
-** the array part of the table, 0 otherwise.
+** Check whether key 'k1' is equal to the key in node 'n2'.
+** This equality is raw, so there are no metamethods. Floats
+** with integer values have been normalized, so integers cannot
+** be equal to floats. It is assumed that 'eqshrstr' is simply
+** pointer equality, so that short strings are handled in the
+** default case.
*/
-static unsigned int arrayindex (const TValue *key) {
- if (ttisinteger(key)) {
- lua_Integer k = ivalue(key);
- if (0 < k && (lua_Unsigned)k <= MAXASIZE)
- return cast(unsigned int, k); /* 'key' is an appropriate array index */
+static int equalkey (const TValue *k1, const Node *n2) {
+ if (rttype(k1) != keytt(n2)) /* not the same variants? */
+ return 0; /* cannot be same key */
+ switch (ttype(k1)) {
+ case LUA_TNIL:
+ return 1;
+ case LUA_TNUMINT:
+ return (ivalue(k1) == keyival(n2));
+ case LUA_TNUMFLT:
+ return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
+ case LUA_TBOOLEAN:
+ return bvalue(k1) == bvalueraw(keyval(n2));
+ case LUA_TLIGHTUSERDATA:
+ return pvalue(k1) == pvalueraw(keyval(n2));
+ case LUA_TLCF:
+ return fvalue(k1) == fvalueraw(keyval(n2));
+ case LUA_TLNGSTR:
+ return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
+ default:
+ return gcvalue(k1) == gcvalueraw(keyval(n2));
}
- return 0; /* 'key' did not match some condition */
+}
+
+
+/*
+** returns the index for 'k' if 'k' is an appropriate key to live in
+** the array part of a table, 0 otherwise.
+*/
+static unsigned int arrayindex (lua_Integer k) {
+ if (0 < k && l_castS2U(k) <= MAXASIZE)
+ return cast(unsigned int, k); /* 'key' is an appropriate array index */
+ else
+ return 0;
}
@@ -159,17 +195,17 @@ static unsigned int arrayindex (const TValue *key) {
static unsigned int findindex (lua_State *L, Table *t, StkId key) {
unsigned int i;
if (ttisnil(key)) return 0; /* first iteration */
- i = arrayindex(key);
+ i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */
return i; /* yes; that's the index */
else {
int nx;
- Node *n = mainposition(t, key);
+ Node *n = mainpositionTV(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
/* key may be dead already, but it is ok to use it in 'next' */
- if (luaV_rawequalobj(gkey(n), key) ||
- (ttisdeadkey(gkey(n)) && iscollectable(key) &&
- deadvalue(gkey(n)) == gcvalue(key))) {
+ if (equalkey(key, n) ||
+ (keyisdead(n) && iscollectable(key) &&
+ deadkey(n) == gcvalue(key))) {
i = cast_int(n - gnode(t, 0)); /* key index in hash table */
/* hash elements are numbered after array ones */
return (i + 1) + t->sizearray;
@@ -194,8 +230,9 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
}
for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
- setobj2s(L, key, gkey(gnode(t, i)));
- setobj2s(L, key+1, gval(gnode(t, i)));
+ Node *n = gnode(t, i);
+ getnodekey(L, key, n);
+ setobj2s(L, key + 1, gval(n));
return 1;
}
}
@@ -239,7 +276,7 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
}
-static int countint (const TValue *key, unsigned int *nums) {
+static int countint (lua_Integer key, unsigned int *nums) {
unsigned int k = arrayindex(key);
if (k != 0) { /* is 'key' an appropriate array index? */
nums[luaO_ceillog2(k)]++; /* count as such */
@@ -288,7 +325,8 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
while (i--) {
Node *n = &t->node[i];
if (!ttisnil(gval(n))) {
- ause += countint(gkey(n), nums);
+ if (keyisinteger(n))
+ ause += countint(keyival(n), nums);
totaluse++;
}
}
@@ -322,7 +360,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
for (i = 0; i < (int)size; i++) {
Node *n = gnode(t, i);
gnext(n) = 0;
- setnilvalue(wgkey(n));
+ setnilkey(n);
setnilvalue(gval(n));
}
t->lsizenode = cast_byte(lsize);
@@ -358,7 +396,8 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
if (!ttisnil(gval(old))) {
/* doesn't need barrier/invalidate cache, as entry was
already present in the table */
- setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
+ TValue k; getnodekey(L, &k, old);
+ setobjt2t(L, luaH_set(L, t, &k), gval(old));
}
}
if (oldhsize > 0) /* not the dummy node? */
@@ -385,7 +424,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
totaluse = na; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &na); /* count keys in hash part */
/* count extra key */
- na += countint(ek, nums);
+ if (ttisinteger(ek))
+ na += countint(ivalue(ek), nums);
totaluse++;
/* compute new size for array part */
asize = computesizes(nums, &na);
@@ -424,7 +464,7 @@ static Node *getfreepos (Table *t) {
if (!isdummy(t)) {
while (t->lastfree > t->node) {
t->lastfree--;
- if (ttisnil(gkey(t->lastfree)))
+ if (keyisnil(t->lastfree))
return t->lastfree;
}
}
@@ -453,7 +493,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
else if (luai_numisnan(fltvalue(key)))
luaG_runerror(L, "table index is NaN");
}
- mp = mainposition(t, key);
+ mp = mainpositionTV(t, key);
if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */
Node *othern;
Node *f = getfreepos(t); /* get a free place */
@@ -463,7 +503,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
return luaH_set(L, t, key); /* insert key into grown table */
}
lua_assert(!isdummy(t));
- othern = mainposition(t, gkey(mp));
+ othern = mainposition(t, keytt(mp), &keyval(mp));
if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
while (othern + gnext(othern) != mp) /* find previous */
@@ -485,7 +525,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
mp = f;
}
}
- setnodekey(L, &mp->i_key, key);
+ setnodekey(L, mp, key);
luaC_barrierback(L, t, key);
lua_assert(ttisnil(gval(mp)));
return gval(mp);
@@ -502,7 +542,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
else {
Node *n = hashint(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
- if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
+ if (keyisinteger(n) && keyival(n) == key)
return gval(n); /* that's it */
else {
int nx = gnext(n);
@@ -522,8 +562,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
lua_assert(key->tt == LUA_TSHRSTR);
for (;;) { /* check whether 'key' is somewhere in the chain */
- const TValue *k = gkey(n);
- if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
+ if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
return gval(n); /* that's it */
else {
int nx = gnext(n);
@@ -540,9 +579,9 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
** which may be in array part, nor for floats with integral values.)
*/
static const TValue *getgeneric (Table *t, const TValue *key) {
- Node *n = mainposition(t, key);
+ Node *n = mainpositionTV(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
- if (luaV_rawequalobj(gkey(n), key))
+ if (equalkey(key, n))
return gval(n); /* that's it */
else {
int nx = gnext(n);
@@ -683,7 +722,7 @@ lua_Unsigned luaH_getn (Table *t) {
#if defined(LUA_DEBUG)
Node *luaH_mainposition (const Table *t, const TValue *key) {
- return mainposition(t, key);
+ return mainpositionTV(t, key);
}
int luaH_isdummy (const Table *t) { return isdummy(t); }
diff --git a/ltable.h b/ltable.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.h,v 2.23 2016/12/22 13:08:50 roberto Exp roberto $
+** $Id: ltable.h,v 2.24 2017/05/19 12:48:15 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -12,18 +12,9 @@
#define gnode(t,i) (&(t)->node[i])
#define gval(n) (&(n)->i_val)
-#define gnext(n) ((n)->i_key.nk.next)
+#define gnext(n) ((n)->u.next)
-/* 'const' to avoid wrong writings that can mess up field 'next' */
-#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk))
-
-/*
-** writable version of 'gkey'; allows updates to individual fields,
-** but not to the whole (which has incompatible type)
-*/
-#define wgkey(n) (&(n)->i_key.nk)
-
#define invalidateTMcache(t) ((t)->flags = 0)
@@ -35,9 +26,8 @@
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
-/* returns the key, given the value of a table entry */
-#define keyfromval(v) \
- (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
+/* returns the Node, given the value of a table entry */
+#define nodefromval(v) cast(Node *, (v))
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
diff --git a/ltests.c b/ltests.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltests.c,v 2.217 2017/05/04 13:32:01 roberto Exp $
+** $Id: ltests.c,v 2.218 2017/05/31 18:54:58 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -253,8 +253,10 @@ static void checktable (global_State *g, Table *h) {
checkvalref(g, hgc, &h->array[i]);
for (n = gnode(h, 0); n < limit; n++) {
if (!ttisnil(gval(n))) {
- lua_assert(!ttisnil(gkey(n)));
- checkvalref(g, hgc, gkey(n));
+ TValue k;
+ getnodekey(g->mainthread, &k, n);
+ lua_assert(!keyisnil(n));
+ checkvalref(g, hgc, &k);
checkvalref(g, hgc, gval(n));
}
}
@@ -802,10 +804,12 @@ static int table_query (lua_State *L) {
lua_pushnil(L);
}
else if ((i -= t->sizearray) < sizenode(t)) {
+ TValue k;
+ getnodekey(L, &k, gnode(t, i));
if (!ttisnil(gval(gnode(t, i))) ||
- ttisnil(gkey(gnode(t, i))) ||
- ttisnumber(gkey(gnode(t, i)))) {
- pushobject(L, gkey(gnode(t, i)));
+ ttisnil(&k) ||
+ ttisnumber(&k)) {
+ pushobject(L, &k);
}
else
lua_pushliteral(L, "<undef>");