diff --git a/lgc.c b/lgc.c index c6f40a33..355c1003 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.160 2013/09/11 12:47:48 roberto Exp roberto $ +** $Id: lgc.c,v 2.161 2013/09/11 13:24:55 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -304,7 +304,7 @@ static void markbeingfnz (global_State *g) { ** thread.) */ static void remarkupvals (global_State *g) { - GCObject *thread = hvalue(&g->l_registry)->next; + GCObject *thread = g->mainthread->next; for (; thread != NULL; thread = gch(thread)->next) { lua_assert(!isblack(thread)); /* threads are never black */ if (!isgray(thread)) { /* dead thread? */ @@ -933,10 +933,9 @@ static void localmarkthread (lua_State *l) { ** a thread) */ static void localmark (global_State *g) { - GCObject *thread = hvalue(&g->l_registry)->next; + GCObject *thread = obj2gco(g->mainthread); for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ localmarkthread(gco2th(thread)); - localmarkthread(g->mainthread); } @@ -1057,12 +1056,14 @@ void luaC_freeallobjects (lua_State *L) { separatetobefnz(g, 1); /* separate all objects with finalizers */ lua_assert(g->finobj == NULL && g->localfin == NULL); callallpendingfinalizers(L, 0); + lua_assert(g->tobefnz == NULL); g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->localgc); sweepwholelist(L, &g->localfin); /* finalizers can create objs. with fins. */ sweepwholelist(L, &g->finobj); - sweepwholelist(L, &g->localgc); sweepwholelist(L, &g->allgc); + sweepwholelist(L, &g->mainthread->next); sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ lua_assert(g->strt.nuse == 0); } @@ -1163,11 +1164,13 @@ static lu_mem singlestep (lua_State *L) { return sweepstep(L, g, GCSsweeptobefnz, &g->tobefnz); } case GCSsweeptobefnz: { - return sweepstep(L, g, GCSsweepmainth, NULL); + return sweepstep(L, g, GCSsweepthreads, &g->mainthread->next); + } + case GCSsweepthreads: { + return sweepstep(L, g, GCSsweepend, NULL); } - case GCSsweepmainth: { /* sweep main thread */ - GCObject *mt = obj2gco(g->mainthread); - sweeplist(L, &mt, 1); + case GCSsweepend: { + makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ checkBuffer(L); g->gcstate = GCSpause; /* finish collection */ return GCSWEEPCOST; diff --git a/lgc.h b/lgc.h index f52c9ae7..7a449829 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.72 2013/09/11 12:26:14 roberto Exp roberto $ +** $Id: lgc.h,v 2.73 2013/09/11 12:47:48 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -43,12 +43,13 @@ #define GCSsweepfin 4 #define GCSsweepall 5 #define GCSsweeptobefnz 6 -#define GCSsweepmainth 7 -#define GCSpause 8 +#define GCSsweepthreads 7 +#define GCSsweepend 8 +#define GCSpause 9 #define issweepphase(g) \ - (GCSsweeplocal <= (g)->gcstate && (g)->gcstate <= GCSsweepmainth) + (GCSsweeplocal <= (g)->gcstate && (g)->gcstate <= GCSsweepend) /* diff --git a/lstate.c b/lstate.c index 414e27d2..f9d857fb 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.111 2013/09/05 19:31:49 roberto Exp roberto $ +** $Id: lstate.c,v 2.112 2013/09/11 12:26:14 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -165,14 +165,6 @@ static void init_registry (lua_State *L, global_State *g) { sethvalue(L, &g->l_registry, registry); luaH_resize(L, registry, LUA_RIDX_LAST, 0); nolocal(obj2gco(registry)); - /* registry is the first "regular" object created by a state; move it - from 'localgc' to 'allgc' so that it act as a "sentinel" there */ - lua_assert(g->allgc == NULL && - registry->next == NULL && - g->localgc == obj2gco(registry)); - g->allgc = g->localgc; - g->localgc = NULL; - l_setbit(registry->marked, LOCALMARK); /* mark that it is not in 'localgc' */ /* registry[LUA_RIDX_MAINTHREAD] = L */ setthvalue(L, &temp, L); /* temp = L */ luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); @@ -243,11 +235,11 @@ LUA_API lua_State *lua_newthread (lua_State *L) { luaC_checkGC(L); /* create new thread */ L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g) | bitmask(LOCALMARK) | bitmask(NOLOCALBIT); + L1->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); L1->tt = LUA_TTHREAD; - /* link it after 'l_registry' */ - L1->next = hvalue(&g->l_registry)->next; - hvalue(&g->l_registry)->next = obj2gco(L1); + /* link it on list of threads */ + L1->next = g->mainthread->next; + g->mainthread->next = obj2gco(L1); setthvalue(L, L->top, L1); api_incr_top(L); preinit_state(L1, g); @@ -283,7 +275,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { L->next = NULL; L->tt = LUA_TTHREAD; g->currentwhite = bitmask(WHITE0BIT); - L->marked = luaC_white(g) | bitmask(NOLOCALBIT); + L->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); g->gckind = KGC_NORMAL; preinit_state(L, g); g->frealloc = f; diff --git a/lstate.h b/lstate.h index 40a23643..fc8f775d 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.93 2013/09/03 15:37:10 roberto Exp roberto $ +** $Id: lstate.h,v 2.94 2013/09/05 19:31:49 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -16,20 +16,19 @@ /* -** Some notes about garbage-collected objects: All objects in Lua must -** be kept somehow accessible until being freed. +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed, so all objects always +** belong to one (and only one) of these lists, using field 'next' of +** the 'CommonHeader' for the link: ** -** Lua keeps most objects linked in list g->allgc. The link uses field -** 'next' of the CommonHeader. Threads (except the main one) ar kept -** at the end of the 'allgc' list, after the 'l_registry' (which is -** the first object to be added to the list). -** -** List 'fixedgc' keep objects that are not to be collected (currently +** mainthread->next: all threads; +** localgc: all local objects not marked for finalization; +** localfin: all local objects marked for finalization; +** allgc: all non local objects not marked for finalization; +** finobj: all non local objects marked for finalization; +** tobefnz: all objects ready to be finalized; +** fixedgc: all objects that are not to be collected (currently ** only small strings, such as reserved words). -** -** Live objects with finalizers are kept in the list g->finobj. The -** list g->tobefnz links all objects being finalized. In particular, an -** object has its FINALIZEDBIT set iff it is in one of these lists. */ diff --git a/ltests.c b/ltests.c index 1db957cc..0f6a23dd 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.156 2013/09/11 12:26:14 roberto Exp roberto $ +** $Id: ltests.c,v 2.157 2013/09/11 12:47:48 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -423,7 +423,6 @@ int lua_checkmemory (lua_State *L) { global_State *g = G(L); GCObject *o; int maybedead; - int isthread; if (keepinvariant(g)) { lua_assert(!iswhite(obj2gco(g->mainthread))); lua_assert(!iswhite(gcvalue(&g->l_registry))); @@ -443,14 +442,20 @@ int lua_checkmemory (lua_State *L) { /* check 'allgc' list */ checkgray(g, g->allgc); maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSsweepall); - isthread = 0; /* not traversing threads (yet) */ for (o = g->allgc; o != NULL; o = gch(o)->next) { - if (gch(o)->tt == LUA_TTHREAD) isthread = 1; /* now travesing threads... */ - else lua_assert(!isthread); /* ... and only threads */ checkobject(g, o, maybedead); lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); lua_assert(testbit(o->gch.marked, NOLOCALBIT)); } + /* check thread list */ + checkgray(g, obj2gco(g->mainthread)); + maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSsweepthreads); + for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { + checkobject(g, o, maybedead); + lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); + lua_assert(testbit(o->gch.marked, NOLOCALBIT)); + lua_assert(gch(o)->tt == LUA_TTHREAD); + } /* check 'localfin' list */ checkgray(g, g->localfin); for (o = g->localfin; o != NULL; o = gch(o)->next) { @@ -650,8 +655,8 @@ static int gc_local (lua_State *L) { static int gc_state (lua_State *L) { static const char *statenames[] = {"propagate", "atomic", - "sweeplocal", "sweeplocfin", "sweepfin", "sweepall", "sweeptobefnz", - "sweepmainth", "pause", ""}; + "sweeplocal", "sweeplocfin", "sweepfin", "sweepall", + "sweeptobefnz", "sweepthreads", "sweepend", "pause", ""}; int option = luaL_checkoption(L, 1, "", statenames); if (option == GCSpause + 1) { lua_pushstring(L, statenames[G(L)->gcstate]);