aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c42
-rw-r--r--llex.c6
-rw-r--r--lobject.h98
-rw-r--r--ltable.c131
-rw-r--r--ltable.h18
-rw-r--r--ltests.c16
6 files changed, 201 insertions, 110 deletions
diff --git a/lgc.c b/lgc.c
index fa6cf799..36e34368 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.229 2017/05/26 19:14:29 roberto Exp roberto $ 2** $Id: lgc.c,v 2.230 2017/06/01 19:16:34 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -73,7 +73,9 @@
73 73
74#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) 74#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
75 75
76#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) 76#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
77
78#define checkdeadkey(n) lua_assert(!keyisdead(n) || ttisnil(gval(n)))
77 79
78 80
79#define checkconsistency(obj) \ 81#define checkconsistency(obj) \
@@ -83,6 +85,8 @@
83#define markvalue(g,o) { checkconsistency(o); \ 85#define markvalue(g,o) { checkconsistency(o); \
84 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } 86 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
85 87
88#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
89
86#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } 90#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
87 91
88/* 92/*
@@ -125,8 +129,8 @@ static lu_mem atomic (lua_State *L);
125*/ 129*/
126static void removeentry (Node *n) { 130static void removeentry (Node *n) {
127 lua_assert(ttisnil(gval(n))); 131 lua_assert(ttisnil(gval(n)));
128 if (valiswhite(gkey(n))) 132 if (keyiswhite(n))
129 setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ 133 setdeadkey(n); /* unused and unmarked key; remove it */
130} 134}
131 135
132 136
@@ -137,13 +141,13 @@ static void removeentry (Node *n) {
137** other objects: if really collected, cannot keep them; for objects 141** other objects: if really collected, cannot keep them; for objects
138** being finalized, keep them in keys, but not in values 142** being finalized, keep them in keys, but not in values
139*/ 143*/
140static int iscleared (global_State *g, const TValue *o) { 144static int iscleared (global_State *g, const GCObject *o) {
141 if (!iscollectable(o)) return 0; 145 if (o == NULL) return 0; /* non-collectable value */
142 else if (ttisstring(o)) { 146 else if (novariant(o->tt) == LUA_TSTRING) {
143 markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ 147 markobject(g, o); /* strings are 'values', so are never weak */
144 return 0; 148 return 0;
145 } 149 }
146 else return iswhite(gcvalue(o)); 150 else return iswhite(o);
147} 151}
148 152
149 153
@@ -391,9 +395,9 @@ static void traverseweakvalue (global_State *g, Table *h) {
391 if (ttisnil(gval(n))) /* entry is empty? */ 395 if (ttisnil(gval(n))) /* entry is empty? */
392 removeentry(n); /* remove it */ 396 removeentry(n); /* remove it */
393 else { 397 else {
394 lua_assert(!ttisnil(gkey(n))); 398 lua_assert(!keyisnil(n));
395 markvalue(g, gkey(n)); /* mark key */ 399 markkey(g, n);
396 if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ 400 if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */
397 hasclears = 1; /* table will have to be cleared */ 401 hasclears = 1; /* table will have to be cleared */
398 } 402 }
399 } 403 }
@@ -433,7 +437,7 @@ static int traverseephemeron (global_State *g, Table *h) {
433 checkdeadkey(n); 437 checkdeadkey(n);
434 if (ttisnil(gval(n))) /* entry is empty? */ 438 if (ttisnil(gval(n))) /* entry is empty? */
435 removeentry(n); /* remove it */ 439 removeentry(n); /* remove it */
436 else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ 440 else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
437 hasclears = 1; /* table must be cleared */ 441 hasclears = 1; /* table must be cleared */
438 if (valiswhite(gval(n))) /* value not marked yet? */ 442 if (valiswhite(gval(n))) /* value not marked yet? */
439 hasww = 1; /* white-white entry */ 443 hasww = 1; /* white-white entry */
@@ -468,9 +472,9 @@ static void traversestrongtable (global_State *g, Table *h) {
468 if (ttisnil(gval(n))) /* entry is empty? */ 472 if (ttisnil(gval(n))) /* entry is empty? */
469 removeentry(n); /* remove it */ 473 removeentry(n); /* remove it */
470 else { 474 else {
471 lua_assert(!ttisnil(gkey(n))); 475 lua_assert(!keyisnil(n));
472 markvalue(g, gkey(n)); /* mark key */ 476 markkey(g, n);
473 markvalue(g, gval(n)); /* mark value */ 477 markvalue(g, gval(n));
474 } 478 }
475 } 479 }
476 if (g->gckind == KGC_GEN) { 480 if (g->gckind == KGC_GEN) {
@@ -691,7 +695,7 @@ static void clearkeys (global_State *g, GCObject *l) {
691 Table *h = gco2t(l); 695 Table *h = gco2t(l);
692 Node *n, *limit = gnodelast(h); 696 Node *n, *limit = gnodelast(h);
693 for (n = gnode(h, 0); n < limit; n++) { 697 for (n = gnode(h, 0); n < limit; n++) {
694 if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { 698 if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) {
695 setnilvalue(gval(n)); /* remove value ... */ 699 setnilvalue(gval(n)); /* remove value ... */
696 removeentry(n); /* and remove entry from table */ 700 removeentry(n); /* and remove entry from table */
697 } 701 }
@@ -711,11 +715,11 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
711 unsigned int i; 715 unsigned int i;
712 for (i = 0; i < h->sizearray; i++) { 716 for (i = 0; i < h->sizearray; i++) {
713 TValue *o = &h->array[i]; 717 TValue *o = &h->array[i];
714 if (iscleared(g, o)) /* value was collected? */ 718 if (iscleared(g, gcvalueN(o))) /* value was collected? */
715 setnilvalue(o); /* remove value */ 719 setnilvalue(o); /* remove value */
716 } 720 }
717 for (n = gnode(h, 0); n < limit; n++) { 721 for (n = gnode(h, 0); n < limit; n++) {
718 if (iscleared(g, gval(n))) { 722 if (iscleared(g, gcvalueN(gval(n)))) {
719 setnilvalue(gval(n)); /* remove value ... */ 723 setnilvalue(gval(n)); /* remove value ... */
720 removeentry(n); /* and remove entry from table */ 724 removeentry(n); /* and remove entry from table */
721 } 725 }
diff --git a/llex.c b/llex.c
index 8f44cbef..d840a3ca 100644
--- a/llex.c
+++ b/llex.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp roberto $ 2** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp roberto $
3** Lexical Analyzer 3** Lexical Analyzer
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -132,12 +132,12 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
132 o = luaH_set(L, ls->h, L->top - 1); 132 o = luaH_set(L, ls->h, L->top - 1);
133 if (ttisnil(o)) { /* not in use yet? */ 133 if (ttisnil(o)) { /* not in use yet? */
134 /* boolean value does not need GC barrier; 134 /* boolean value does not need GC barrier;
135 table has no metatable, so it does not need to invalidate cache */ 135 table is not a metatable, so it does not need to invalidate cache */
136 setbvalue(o, 1); /* t[string] = true */ 136 setbvalue(o, 1); /* t[string] = true */
137 luaC_checkGC(L); 137 luaC_checkGC(L);
138 } 138 }
139 else { /* string already present */ 139 else { /* string already present */
140 ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ 140 ts = keystrval(nodefromval(o)); /* re-use value previously stored */
141 } 141 }
142 L->top--; /* remove string from stack */ 142 L->top--; /* remove string from stack */
143 return ts; 143 return ts;
diff --git a/lobject.h b/lobject.h
index 2bef659a..97afa143 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.120 2017/04/30 20:43:26 roberto Exp roberto $ 2** $Id: lobject.h,v 2.121 2017/06/01 20:24:05 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -122,6 +122,7 @@ typedef struct lua_TValue {
122 122
123 123
124#define val_(o) ((o)->value_) 124#define val_(o) ((o)->value_)
125#define valraw(o) (&val_(o))
125 126
126 127
127/* raw type tag of a TValue */ 128/* raw type tag of a TValue */
@@ -131,7 +132,8 @@ typedef struct lua_TValue {
131#define novariant(x) ((x) & 0x0F) 132#define novariant(x) ((x) & 0x0F)
132 133
133/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ 134/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
134#define ttype(o) (rttype(o) & 0x3F) 135#define ttyperaw(t) ((t) & 0x3F)
136#define ttype(o) ttyperaw(rttype(o))
135 137
136/* type tag of a TValue with no variants (bits 0-3) */ 138/* type tag of a TValue with no variants (bits 0-3) */
137#define ttnov(o) (novariant(rttype(o))) 139#define ttnov(o) (novariant(rttype(o)))
@@ -157,7 +159,19 @@ typedef struct lua_TValue {
157#define ttislcf(o) checktag((o), LUA_TLCF) 159#define ttislcf(o) checktag((o), LUA_TLCF)
158#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) 160#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA))
159#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) 161#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
160#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) 162
163
164/*
165** Macros to access unstructured values (may come both from
166** 'TValue's and table keys)
167*/
168#define ivalueraw(v) ((v).i)
169#define fltvalueraw(v) ((v).n)
170#define gcvalueraw(v) ((v).gc)
171#define pvalueraw(v) ((v).p)
172#define tsvalueraw(v) (gco2ts((v).gc))
173#define fvalueraw(v) ((v).f)
174#define bvalueraw(v) ((v).b)
161 175
162 176
163/* Macros to access values */ 177/* Macros to access values */
@@ -176,8 +190,6 @@ typedef struct lua_TValue {
176#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) 190#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
177#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) 191#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
178#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) 192#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
179/* a dead value may get the 'gc' field, but cannot access its contents */
180#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
181 193
182#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) 194#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
183 195
@@ -185,6 +197,12 @@ typedef struct lua_TValue {
185#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) 197#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
186 198
187 199
200/*
201** Protected access to objects in values
202*/
203#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
204
205
188/* Macros for internal tests */ 206/* Macros for internal tests */
189#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) 207#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)
190 208
@@ -253,8 +271,6 @@ typedef struct lua_TValue {
253 val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \ 271 val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
254 checkliveness(L,io); } 272 checkliveness(L,io); }
255 273
256#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
257
258 274
259 275
260#define setobj(L,obj1,obj2) \ 276#define setobj(L,obj1,obj2) \
@@ -485,26 +501,37 @@ typedef union Closure {
485** Tables 501** Tables
486*/ 502*/
487 503
488typedef union TKey { 504
489 struct { 505/*
490 TValuefields; 506** Nodes for Hash tables. A pack of two TValue's (key-value pairs)
491 int next; /* for chaining (offset for next node) */ 507** plus a 'next' field to link colliding entries. The distribuition
492 } nk; 508** of the key's fields ('key_tt' and 'key_val') not forming a proper
493 TValue tvk; 509** 'TValue' allows for a smaller size for 'Node' both in 4-byte
494} TKey; 510** and 8-byte alignments.
511*/
512typedef union Node {
513 struct NodeKey {
514 TValuefields; /* fields for value */
515 lu_byte key_tt; /* key type */
516 int next; /* for chaining */
517 Value key_val; /* key value */
518 } u;
519 TValue i_val; /* direct access to node's value as a proper 'TValue' */
520} Node;
495 521
496 522
497/* copy a value into a key without messing up field 'next' */ 523/* copy a value into a key */
498#define setnodekey(L,key,obj) \ 524#define setnodekey(L,node,obj) \
499 { TKey *k_=(key); const TValue *io_=(obj); \ 525 { Node *n_=(node); const TValue *io_=(obj); \
500 k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ 526 n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
501 (void)L; checkliveness(L,io_); } 527 (void)L; checkliveness(L,io_); }
502 528
503 529
504typedef struct Node { 530/* copy a value from a key */
505 TValue i_val; 531#define getnodekey(L,obj,node) \
506 TKey i_key; 532 { TValue *io_=(obj); const Node *n_=(node); \
507} Node; 533 io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
534 (void)L; checkliveness(L,io_); }
508 535
509 536
510typedef struct Table { 537typedef struct Table {
@@ -520,6 +547,33 @@ typedef struct Table {
520} Table; 547} Table;
521 548
522 549
550/*
551** Macros to manipulate keys inserted in nodes
552*/
553#define keytt(node) ((node)->u.key_tt)
554#define keyval(node) ((node)->u.key_val)
555
556#define keyisnil(node) (keytt(node) == LUA_TNIL)
557#define keyisinteger(node) (keytt(node) == LUA_TNUMINT)
558#define keyival(node) (keyval(node).i)
559#define keyisshrstr(node) (keytt(node) == ctb(LUA_TSHRSTR))
560#define keystrval(node) (gco2ts(keyval(node).gc))
561
562#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
563
564#define setnilkey(node) (keytt(node) = LUA_TNIL)
565#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
566
567/* a dead value may get the 'gc' field, but cannot access its contents */
568#define deadkey(n) \
569 check_exp(keytt(n) == LUA_TDEADKEY, cast(void *, keyval(n).gc))
570
571#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
572
573#define gckey(n) (keyval(n).gc)
574#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
575
576
523 577
524/* 578/*
525** 'module' operation for hashing (size is always a power of 2) 579** 'module' operation for hashing (size is always a power of 2)
diff --git a/ltable.c b/ltable.c
index 4ce33319..498eb121 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 2.121 2017/05/19 12:47:00 roberto Exp roberto $ 2** $Id: ltable.c,v 2.122 2017/05/19 12:57:10 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -75,8 +75,8 @@
75#define dummynode (&dummynode_) 75#define dummynode (&dummynode_)
76 76
77static const Node dummynode_ = { 77static const Node dummynode_ = {
78 {NILCONSTANT}, /* value */ 78 {{NULL}, LUA_TNIL, /* value's value and type */
79 {{NILCONSTANT, 0}} /* key */ 79 LUA_TNIL, 0, {NULL}} /* key type, next, and key value */
80}; 80};
81 81
82 82
@@ -111,43 +111,79 @@ static int l_hashfloat (lua_Number n) {
111 111
112 112
113/* 113/*
114** returns the 'main' position of an element in a table (that is, the index 114** returns the 'main' position of an element in a table (that is,
115** of its hash value) 115** the index of its hash value). The key comes broken (tag in 'ktt'
116** and value in 'vkl') so that we can call it on keys inserted into
117** nodes.
116*/ 118*/
117static Node *mainposition (const Table *t, const TValue *key) { 119static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
118 switch (ttype(key)) { 120 switch (ttyperaw(ktt)) {
119 case LUA_TNUMINT: 121 case LUA_TNUMINT:
120 return hashint(t, ivalue(key)); 122 return hashint(t, ivalueraw(*kvl));
121 case LUA_TNUMFLT: 123 case LUA_TNUMFLT:
122 return hashmod(t, l_hashfloat(fltvalue(key))); 124 return hashmod(t, l_hashfloat(fltvalueraw(*kvl)));
123 case LUA_TSHRSTR: 125 case LUA_TSHRSTR:
124 return hashstr(t, tsvalue(key)); 126 return hashstr(t, tsvalueraw(*kvl));
125 case LUA_TLNGSTR: 127 case LUA_TLNGSTR:
126 return hashpow2(t, luaS_hashlongstr(tsvalue(key))); 128 return hashpow2(t, luaS_hashlongstr(tsvalueraw(*kvl)));
127 case LUA_TBOOLEAN: 129 case LUA_TBOOLEAN:
128 return hashboolean(t, bvalue(key)); 130 return hashboolean(t, bvalueraw(*kvl));
129 case LUA_TLIGHTUSERDATA: 131 case LUA_TLIGHTUSERDATA:
130 return hashpointer(t, pvalue(key)); 132 return hashpointer(t, pvalueraw(*kvl));
131 case LUA_TLCF: 133 case LUA_TLCF:
132 return hashpointer(t, fvalue(key)); 134 return hashpointer(t, fvalueraw(*kvl));
133 default: 135 default:
134 lua_assert(!ttisdeadkey(key)); 136 return hashpointer(t, gcvalueraw(*kvl));
135 return hashpointer(t, gcvalue(key));
136 } 137 }
137} 138}
138 139
139 140
141static Node *mainpositionTV (const Table *t, const TValue *key) {
142 return mainposition(t, rttype(key), valraw(key));
143}
144
145
140/* 146/*
141** returns the index for 'key' if 'key' is an appropriate key to live in 147** Check whether key 'k1' is equal to the key in node 'n2'.
142** the array part of the table, 0 otherwise. 148** This equality is raw, so there are no metamethods. Floats
149** with integer values have been normalized, so integers cannot
150** be equal to floats. It is assumed that 'eqshrstr' is simply
151** pointer equality, so that short strings are handled in the
152** default case.
143*/ 153*/
144static unsigned int arrayindex (const TValue *key) { 154static int equalkey (const TValue *k1, const Node *n2) {
145 if (ttisinteger(key)) { 155 if (rttype(k1) != keytt(n2)) /* not the same variants? */
146 lua_Integer k = ivalue(key); 156 return 0; /* cannot be same key */
147 if (0 < k && (lua_Unsigned)k <= MAXASIZE) 157 switch (ttype(k1)) {
148 return cast(unsigned int, k); /* 'key' is an appropriate array index */ 158 case LUA_TNIL:
159 return 1;
160 case LUA_TNUMINT:
161 return (ivalue(k1) == keyival(n2));
162 case LUA_TNUMFLT:
163 return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
164 case LUA_TBOOLEAN:
165 return bvalue(k1) == bvalueraw(keyval(n2));
166 case LUA_TLIGHTUSERDATA:
167 return pvalue(k1) == pvalueraw(keyval(n2));
168 case LUA_TLCF:
169 return fvalue(k1) == fvalueraw(keyval(n2));
170 case LUA_TLNGSTR:
171 return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
172 default:
173 return gcvalue(k1) == gcvalueraw(keyval(n2));
149 } 174 }
150 return 0; /* 'key' did not match some condition */ 175}
176
177
178/*
179** returns the index for 'k' if 'k' is an appropriate key to live in
180** the array part of a table, 0 otherwise.
181*/
182static unsigned int arrayindex (lua_Integer k) {
183 if (0 < k && l_castS2U(k) <= MAXASIZE)
184 return cast(unsigned int, k); /* 'key' is an appropriate array index */
185 else
186 return 0;
151} 187}
152 188
153 189
@@ -159,17 +195,17 @@ static unsigned int arrayindex (const TValue *key) {
159static unsigned int findindex (lua_State *L, Table *t, StkId key) { 195static unsigned int findindex (lua_State *L, Table *t, StkId key) {
160 unsigned int i; 196 unsigned int i;
161 if (ttisnil(key)) return 0; /* first iteration */ 197 if (ttisnil(key)) return 0; /* first iteration */
162 i = arrayindex(key); 198 i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
163 if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ 199 if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */
164 return i; /* yes; that's the index */ 200 return i; /* yes; that's the index */
165 else { 201 else {
166 int nx; 202 int nx;
167 Node *n = mainposition(t, key); 203 Node *n = mainpositionTV(t, key);
168 for (;;) { /* check whether 'key' is somewhere in the chain */ 204 for (;;) { /* check whether 'key' is somewhere in the chain */
169 /* key may be dead already, but it is ok to use it in 'next' */ 205 /* key may be dead already, but it is ok to use it in 'next' */
170 if (luaV_rawequalobj(gkey(n), key) || 206 if (equalkey(key, n) ||
171 (ttisdeadkey(gkey(n)) && iscollectable(key) && 207 (keyisdead(n) && iscollectable(key) &&
172 deadvalue(gkey(n)) == gcvalue(key))) { 208 deadkey(n) == gcvalue(key))) {
173 i = cast_int(n - gnode(t, 0)); /* key index in hash table */ 209 i = cast_int(n - gnode(t, 0)); /* key index in hash table */
174 /* hash elements are numbered after array ones */ 210 /* hash elements are numbered after array ones */
175 return (i + 1) + t->sizearray; 211 return (i + 1) + t->sizearray;
@@ -194,8 +230,9 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
194 } 230 }
195 for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ 231 for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
196 if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ 232 if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
197 setobj2s(L, key, gkey(gnode(t, i))); 233 Node *n = gnode(t, i);
198 setobj2s(L, key+1, gval(gnode(t, i))); 234 getnodekey(L, key, n);
235 setobj2s(L, key + 1, gval(n));
199 return 1; 236 return 1;
200 } 237 }
201 } 238 }
@@ -239,7 +276,7 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
239} 276}
240 277
241 278
242static int countint (const TValue *key, unsigned int *nums) { 279static int countint (lua_Integer key, unsigned int *nums) {
243 unsigned int k = arrayindex(key); 280 unsigned int k = arrayindex(key);
244 if (k != 0) { /* is 'key' an appropriate array index? */ 281 if (k != 0) { /* is 'key' an appropriate array index? */
245 nums[luaO_ceillog2(k)]++; /* count as such */ 282 nums[luaO_ceillog2(k)]++; /* count as such */
@@ -288,7 +325,8 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
288 while (i--) { 325 while (i--) {
289 Node *n = &t->node[i]; 326 Node *n = &t->node[i];
290 if (!ttisnil(gval(n))) { 327 if (!ttisnil(gval(n))) {
291 ause += countint(gkey(n), nums); 328 if (keyisinteger(n))
329 ause += countint(keyival(n), nums);
292 totaluse++; 330 totaluse++;
293 } 331 }
294 } 332 }
@@ -322,7 +360,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
322 for (i = 0; i < (int)size; i++) { 360 for (i = 0; i < (int)size; i++) {
323 Node *n = gnode(t, i); 361 Node *n = gnode(t, i);
324 gnext(n) = 0; 362 gnext(n) = 0;
325 setnilvalue(wgkey(n)); 363 setnilkey(n);
326 setnilvalue(gval(n)); 364 setnilvalue(gval(n));
327 } 365 }
328 t->lsizenode = cast_byte(lsize); 366 t->lsizenode = cast_byte(lsize);
@@ -358,7 +396,8 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
358 if (!ttisnil(gval(old))) { 396 if (!ttisnil(gval(old))) {
359 /* doesn't need barrier/invalidate cache, as entry was 397 /* doesn't need barrier/invalidate cache, as entry was
360 already present in the table */ 398 already present in the table */
361 setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); 399 TValue k; getnodekey(L, &k, old);
400 setobjt2t(L, luaH_set(L, t, &k), gval(old));
362 } 401 }
363 } 402 }
364 if (oldhsize > 0) /* not the dummy node? */ 403 if (oldhsize > 0) /* not the dummy node? */
@@ -385,7 +424,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
385 totaluse = na; /* all those keys are integer keys */ 424 totaluse = na; /* all those keys are integer keys */
386 totaluse += numusehash(t, nums, &na); /* count keys in hash part */ 425 totaluse += numusehash(t, nums, &na); /* count keys in hash part */
387 /* count extra key */ 426 /* count extra key */
388 na += countint(ek, nums); 427 if (ttisinteger(ek))
428 na += countint(ivalue(ek), nums);
389 totaluse++; 429 totaluse++;
390 /* compute new size for array part */ 430 /* compute new size for array part */
391 asize = computesizes(nums, &na); 431 asize = computesizes(nums, &na);
@@ -424,7 +464,7 @@ static Node *getfreepos (Table *t) {
424 if (!isdummy(t)) { 464 if (!isdummy(t)) {
425 while (t->lastfree > t->node) { 465 while (t->lastfree > t->node) {
426 t->lastfree--; 466 t->lastfree--;
427 if (ttisnil(gkey(t->lastfree))) 467 if (keyisnil(t->lastfree))
428 return t->lastfree; 468 return t->lastfree;
429 } 469 }
430 } 470 }
@@ -453,7 +493,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
453 else if (luai_numisnan(fltvalue(key))) 493 else if (luai_numisnan(fltvalue(key)))
454 luaG_runerror(L, "table index is NaN"); 494 luaG_runerror(L, "table index is NaN");
455 } 495 }
456 mp = mainposition(t, key); 496 mp = mainpositionTV(t, key);
457 if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ 497 if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */
458 Node *othern; 498 Node *othern;
459 Node *f = getfreepos(t); /* get a free place */ 499 Node *f = getfreepos(t); /* get a free place */
@@ -463,7 +503,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
463 return luaH_set(L, t, key); /* insert key into grown table */ 503 return luaH_set(L, t, key); /* insert key into grown table */
464 } 504 }
465 lua_assert(!isdummy(t)); 505 lua_assert(!isdummy(t));
466 othern = mainposition(t, gkey(mp)); 506 othern = mainposition(t, keytt(mp), &keyval(mp));
467 if (othern != mp) { /* is colliding node out of its main position? */ 507 if (othern != mp) { /* is colliding node out of its main position? */
468 /* yes; move colliding node into free position */ 508 /* yes; move colliding node into free position */
469 while (othern + gnext(othern) != mp) /* find previous */ 509 while (othern + gnext(othern) != mp) /* find previous */
@@ -485,7 +525,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
485 mp = f; 525 mp = f;
486 } 526 }
487 } 527 }
488 setnodekey(L, &mp->i_key, key); 528 setnodekey(L, mp, key);
489 luaC_barrierback(L, t, key); 529 luaC_barrierback(L, t, key);
490 lua_assert(ttisnil(gval(mp))); 530 lua_assert(ttisnil(gval(mp)));
491 return gval(mp); 531 return gval(mp);
@@ -502,7 +542,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
502 else { 542 else {
503 Node *n = hashint(t, key); 543 Node *n = hashint(t, key);
504 for (;;) { /* check whether 'key' is somewhere in the chain */ 544 for (;;) { /* check whether 'key' is somewhere in the chain */
505 if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) 545 if (keyisinteger(n) && keyival(n) == key)
506 return gval(n); /* that's it */ 546 return gval(n); /* that's it */
507 else { 547 else {
508 int nx = gnext(n); 548 int nx = gnext(n);
@@ -522,8 +562,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
522 Node *n = hashstr(t, key); 562 Node *n = hashstr(t, key);
523 lua_assert(key->tt == LUA_TSHRSTR); 563 lua_assert(key->tt == LUA_TSHRSTR);
524 for (;;) { /* check whether 'key' is somewhere in the chain */ 564 for (;;) { /* check whether 'key' is somewhere in the chain */
525 const TValue *k = gkey(n); 565 if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
526 if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
527 return gval(n); /* that's it */ 566 return gval(n); /* that's it */
528 else { 567 else {
529 int nx = gnext(n); 568 int nx = gnext(n);
@@ -540,9 +579,9 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
540** which may be in array part, nor for floats with integral values.) 579** which may be in array part, nor for floats with integral values.)
541*/ 580*/
542static const TValue *getgeneric (Table *t, const TValue *key) { 581static const TValue *getgeneric (Table *t, const TValue *key) {
543 Node *n = mainposition(t, key); 582 Node *n = mainpositionTV(t, key);
544 for (;;) { /* check whether 'key' is somewhere in the chain */ 583 for (;;) { /* check whether 'key' is somewhere in the chain */
545 if (luaV_rawequalobj(gkey(n), key)) 584 if (equalkey(key, n))
546 return gval(n); /* that's it */ 585 return gval(n); /* that's it */
547 else { 586 else {
548 int nx = gnext(n); 587 int nx = gnext(n);
@@ -683,7 +722,7 @@ lua_Unsigned luaH_getn (Table *t) {
683#if defined(LUA_DEBUG) 722#if defined(LUA_DEBUG)
684 723
685Node *luaH_mainposition (const Table *t, const TValue *key) { 724Node *luaH_mainposition (const Table *t, const TValue *key) {
686 return mainposition(t, key); 725 return mainpositionTV(t, key);
687} 726}
688 727
689int luaH_isdummy (const Table *t) { return isdummy(t); } 728int luaH_isdummy (const Table *t) { return isdummy(t); }
diff --git a/ltable.h b/ltable.h
index ee22cf62..88f90636 100644
--- a/ltable.h
+++ b/ltable.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.h,v 2.23 2016/12/22 13:08:50 roberto Exp roberto $ 2** $Id: ltable.h,v 2.24 2017/05/19 12:48:15 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -12,18 +12,9 @@
12 12
13#define gnode(t,i) (&(t)->node[i]) 13#define gnode(t,i) (&(t)->node[i])
14#define gval(n) (&(n)->i_val) 14#define gval(n) (&(n)->i_val)
15#define gnext(n) ((n)->i_key.nk.next) 15#define gnext(n) ((n)->u.next)
16 16
17 17
18/* 'const' to avoid wrong writings that can mess up field 'next' */
19#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk))
20
21/*
22** writable version of 'gkey'; allows updates to individual fields,
23** but not to the whole (which has incompatible type)
24*/
25#define wgkey(n) (&(n)->i_key.nk)
26
27#define invalidateTMcache(t) ((t)->flags = 0) 18#define invalidateTMcache(t) ((t)->flags = 0)
28 19
29 20
@@ -35,9 +26,8 @@
35#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) 26#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
36 27
37 28
38/* returns the key, given the value of a table entry */ 29/* returns the Node, given the value of a table entry */
39#define keyfromval(v) \ 30#define nodefromval(v) cast(Node *, (v))
40 (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
41 31
42 32
43LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); 33LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
diff --git a/ltests.c b/ltests.c
index fc233c7f..a9c93132 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.217 2017/05/04 13:32:01 roberto Exp $ 2** $Id: ltests.c,v 2.218 2017/05/31 18:54:58 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -253,8 +253,10 @@ static void checktable (global_State *g, Table *h) {
253 checkvalref(g, hgc, &h->array[i]); 253 checkvalref(g, hgc, &h->array[i]);
254 for (n = gnode(h, 0); n < limit; n++) { 254 for (n = gnode(h, 0); n < limit; n++) {
255 if (!ttisnil(gval(n))) { 255 if (!ttisnil(gval(n))) {
256 lua_assert(!ttisnil(gkey(n))); 256 TValue k;
257 checkvalref(g, hgc, gkey(n)); 257 getnodekey(g->mainthread, &k, n);
258 lua_assert(!keyisnil(n));
259 checkvalref(g, hgc, &k);
258 checkvalref(g, hgc, gval(n)); 260 checkvalref(g, hgc, gval(n));
259 } 261 }
260 } 262 }
@@ -802,10 +804,12 @@ static int table_query (lua_State *L) {
802 lua_pushnil(L); 804 lua_pushnil(L);
803 } 805 }
804 else if ((i -= t->sizearray) < sizenode(t)) { 806 else if ((i -= t->sizearray) < sizenode(t)) {
807 TValue k;
808 getnodekey(L, &k, gnode(t, i));
805 if (!ttisnil(gval(gnode(t, i))) || 809 if (!ttisnil(gval(gnode(t, i))) ||
806 ttisnil(gkey(gnode(t, i))) || 810 ttisnil(&k) ||
807 ttisnumber(gkey(gnode(t, i)))) { 811 ttisnumber(&k)) {
808 pushobject(L, gkey(gnode(t, i))); 812 pushobject(L, &k);
809 } 813 }
810 else 814 else
811 lua_pushliteral(L, "<undef>"); 815 lua_pushliteral(L, "<undef>");