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

@@ -189,6 +189,7 @@ static BCReg const_gc(FuncState *fs, GCobj *gc, int itype)
lua_State *L = fs->L;
TValue o, *val;
setgcV(L, &o, &gc->gch, itype);
/* NOBARRIER: the key is new or kept alive. */
val = lj_tab_set(L, fs->kt, &o);
if (tvisnum(val))
return val->u32.lo;
@@ -206,6 +207,7 @@ static BCReg const_str(FuncState *fs, ExpDesc *e)
/* Anchor string constant to avoid GC. */
GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t len)
{
/* NOBARRIER: the key is new or kept alive. */
lua_State *L = ls->L;
GCstr *s = lj_str_new(L, str, len);
TValue *tv = lj_tab_setstr(L, ls->fs->kt, s);
@@ -1202,6 +1204,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
lua_assert(ls->fs != NULL || ls->token == TK_eof);
/* Re-anchor last string token to avoid GC. */
if (ls->token == TK_name || ls->token == TK_string) {
/* NOBARRIER: the key is new or kept alive. */
TValue *tv = lj_tab_setstr(ls->L, ls->fs->kt, strV(&ls->tokenval));
if (tvisnil(tv)) setboolV(tv, 1);
}
@@ -1346,8 +1349,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
vcall = 0;
expr_kvalue(&k, &key);
expr_kvalue(lj_tab_set(fs->L, t, &k), &val);
if (val.k == VKSTR)
lj_gc_objbarriert(fs->L, t, val.u.sval);
lj_gc_anybarriert(fs->L, t);
} else {
if (val.k != VCALL) { expr_toanyreg(fs, &val); vcall = 0; }
if (expr_isk(&key)) expr_index(fs, e, &key);