No longer let the GC replace dead keys with the LJ_TDEADKEY tag.

Important: this changes the semantics of the write barrier!
Carefully read the big comment block in lj_obj.h
This helps HREFK key slot specialization and allows safely hoisting
HREF/HREFK across GC steps, too (fix for a barely reproducible bug).
Dead keys are only removed during a table resize (as before).
This commit is contained in:
Mike Pall
2010-04-21 01:45:58 +02:00
parent d8cb69ed07
commit ab45481199
13 changed files with 65 additions and 43 deletions

View File

@@ -192,7 +192,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
Node *kn = &knode[i];
Node *n = &node[i];
Node *next = nextnode(kn);
/* Don't use copyTV here, since it asserts on a copy of a DEADKEY. */
/* Don't use copyTV here, since it asserts on a copy of a dead key. */
n->val = kn->val; n->key = kn->key;
setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
}
@@ -448,7 +448,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
n->key.u64 = key->u64;
if (LJ_UNLIKELY(tvismzero(&n->key)))
n->key.u64 = 0;
lj_gc_barriert(L, t, key);
lj_gc_anybarriert(L, t);
lua_assert(tvisnil(&n->val));
return &n->val;
}
@@ -517,9 +517,7 @@ static uint32_t keyindex(lua_State *L, GCtab *t, cTValue *key)
if (!tvisnil(key)) {
Node *n = hashkey(t, key);
do {
if (lj_obj_equal(&n->key, key) ||
(itype(&n->key) == LJ_TDEADKEY && tvisgcv(key) &&
gcV(&n->key) == gcV(key)))
if (lj_obj_equal(&n->key, key))
return t->asize + (uint32_t)(n - noderef(t->node));
/* Hash key indexes: [t->asize..t->asize+t->nmask] */
} while ((n = nextnode(n)));