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:
@@ -186,13 +186,10 @@ static int gc_traverse_tab(global_State *g, GCtab *t)
|
||||
MSize i, hmask = t->hmask;
|
||||
for (i = 0; i <= hmask; i++) {
|
||||
Node *n = &node[i];
|
||||
lua_assert(itype(&n->key) != LJ_TDEADKEY || tvisnil(&n->val));
|
||||
if (!tvisnil(&n->val)) { /* Mark non-empty slot. */
|
||||
lua_assert(!tvisnil(&n->key));
|
||||
if (!(weak & LJ_GC_WEAKKEY)) gc_marktv(g, &n->key);
|
||||
if (!(weak & LJ_GC_WEAKVAL)) gc_marktv(g, &n->val);
|
||||
} else if (tvisgcv(&n->key)) { /* Leave GC key in, but mark as dead. */
|
||||
setitype(&n->key, LJ_TDEADKEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,11 +421,8 @@ static void gc_clearweak(GCobj *o)
|
||||
Node *n = &node[i];
|
||||
/* Clear hash slot when key or value is about to be collected. */
|
||||
if (!tvisnil(&n->val) && (gc_mayclear(&n->key, 0) ||
|
||||
gc_mayclear(&n->val, 1))) {
|
||||
gc_mayclear(&n->val, 1)))
|
||||
setnilV(&n->val);
|
||||
if (tvisgcv(&n->key)) /* Leave GC key in, but mark as dead. */
|
||||
setitype(&n->key, LJ_TDEADKEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
o = gcref(t->gclist);
|
||||
|
||||
Reference in New Issue
Block a user