no more 'DEADKEY'. Table traversals do not need to consider dead keys;

if the key is dead, it cannot be given to 'next'. Instead, we now
use a 'table' tag without the collectable bit, which makes it
a unique tag good enough to reserve space.
This commit is contained in:
Roberto Ierusalimschy
2017-06-12 11:21:44 -03:00
parent d13a3fb070
commit 73ec04fcf3
5 changed files with 49 additions and 66 deletions

21
lgc.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.230 2017/06/01 19:16:34 roberto Exp roberto $
** $Id: lgc.c,v 2.231 2017/06/09 16:48:44 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -75,8 +75,6 @@
#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
#define checkdeadkey(n) lua_assert(!keyisdead(n) || ttisnil(gval(n)))
#define checkconsistency(obj) \
lua_longassert(!iscollectable(obj) || righttt(obj))
@@ -119,13 +117,11 @@ static lu_mem atomic (lua_State *L);
/*
** If key is not marked, mark its entry as dead. This allows key to be
** collected, but keeps its entry in the table. A dead node is needed
** when Lua looks up for a key (it may be part of a chain) and when
** traversing a weak table (key might be removed from the table during
** traversal). Other places never manipulate dead keys, because its
** associated nil value is enough to signal that the entry is logically
** empty.
** If key is not marked, mark its entry as dead. This allows the
** collection of the key, but keeps its entry in the table (its removal
** could break a chain). Other places never manipulate dead keys,
** because its associated nil value is enough to signal that the entry
** is logically empty.
*/
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
@@ -203,7 +199,7 @@ LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p) {
lua_assert(g->gckind != KGC_GEN || isold(p));
if (getage(p) == G_OLD1) /* still need to be visited? */
linkgclist(p, g->grayagain); /* link it in 'grayagain' */
else
else
linkgclist(p, g->protogray); /* link it in 'protogray' */
black2gray(p); /* make prototype gray (to avoid other barriers) */
}
@@ -391,7 +387,6 @@ static void traverseweakvalue (global_State *g, Table *h) {
worth traversing it now just to check) */
int hasclears = (h->sizearray > 0);
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {
@@ -434,7 +429,6 @@ static int traverseephemeron (global_State *g, Table *h) {
}
/* traverse hash part */
for (n = gnode(h, 0); n < limit; n++) {
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
@@ -468,7 +462,6 @@ static void traversestrongtable (global_State *g, Table *h) {
for (i = 0; i < h->sizearray; i++) /* traverse array part */
markvalue(g, &h->array[i]);
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {