From 621ef9f7675829234e75b0b3e73afc7a1a74aa16 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 19 Jan 2005 13:54:26 -0200 Subject: better control over GC collors of upvalues --- lfunc.c | 12 +++++++++--- lgc.h | 3 ++- ltests.c | 17 +++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/lfunc.c b/lfunc.c index 3171c5ec..65d70cfb 100644 --- a/lfunc.c +++ b/lfunc.c @@ -56,7 +56,11 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { UpVal *uv; while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { lua_assert(p->v != &p->u.value); - if (p->v == level) return p; + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(G(L), obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } pp = &p->next; } uv = luaM_new(L, UpVal); /* not found: create a new one */ @@ -65,8 +69,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { uv->v = level; /* current value lives in the stack */ uv->next = *pp; /* chain it in the proper position */ *pp = obj2gco(uv); - lua_assert(g->uvhead.u.l.next->u.l.prev == &g->uvhead && - g->uvhead.u.l.prev->u.l.next == &g->uvhead); uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ uv->u.l.next = g->uvhead.u.l.next; uv->u.l.next->u.l.prev = uv; @@ -102,6 +104,10 @@ void luaF_close (lua_State *L, StkId level) { else { unlinkupval(uv); setobj(L, &uv->u.value, uv->v); + if (isgray(o)) { + gray2black(o); /* closed upvalues are never gray */ + luaC_barrier(L, uv, uv->v); + } uv->v = &uv->u.value; /* now current value lives here */ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ } diff --git a/lgc.h b/lgc.h index f8a18782..bec5a728 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.8 2004/08/30 13:44:44 roberto Exp roberto $ +** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -66,6 +66,7 @@ #define isdead(g,v) ((v)->gch.marked & otherwhite(g)) #define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) +#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) diff --git a/ltests.c b/ltests.c index e99b432f..8686fa73 100644 --- a/ltests.c +++ b/ltests.c @@ -272,7 +272,13 @@ static void checkclosure (global_State *g, Closure *cl) { static void checkstack (global_State *g, lua_State *L1) { StkId o; CallInfo *ci; + GCObject *uvo; lua_assert(!isdead(g, obj2gco(L1))); + for (uvo = L1->openupval; uvo != NULL; uvo = uvo->gch.next) { + UpVal *uv = gco2uv(uvo); + lua_assert(uv->v != &uv->u.value); /* must be open */ + lua_assert(!isblack(uvo)); /* open upvalues cannot be black */ + } checkliveness(g, gt(L1)); if (L1->base_ci) { for (ci = L1->base_ci; ci <= L1->ci; ci++) @@ -300,6 +306,7 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marke case LUA_TUPVAL: { UpVal *uv = gco2uv(o); lua_assert(uv->v == &uv->u.value); /* must be closed */ + lua_assert(!isgray(o)); /* closed upvalues are never gray */ checkvalref(g, o, uv->v); break; } @@ -333,14 +340,20 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marke int lua_checkmemory (lua_State *L) { global_State *g = G(L); GCObject *o; + UpVal *uv; checkstack(g, g->mainthread); for (o = g->rootgc; o != obj2gco(g->mainthread); o = o->gch.next) checkobject(g, o); - checkobject(g, obj2gco(g->mainthread)); - for (o = g->mainthread->next; o != NULL; o = o->gch.next) { + for (o = o->gch.next; o != NULL; o = o->gch.next) { lua_assert(o->gch.tt == LUA_TUSERDATA); checkobject(g, o); } + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + lua_assert(uv->v != &uv->u.value); /* must be open */ + lua_assert(!isblack(obj2gco(uv))); /* open upvalues are never black */ + checkvalref(g, obj2gco(uv), uv->v); + } return 0; } -- cgit v1.2.3-55-g6feb