diff --git a/lgc.c b/lgc.c index 0ef4a679..a06af829 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.167 2013/12/13 15:17:00 roberto Exp roberto $ +** $Id: lgc.c,v 2.168 2013/12/13 15:42:08 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -770,16 +770,16 @@ static GCObject *udata2finalize (global_State *g) { lua_assert(tofinalize(o)); g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ if (islocal(o)) { - lua_assert(!testbit(gch(o)->marked, LOCALMARK)); gch(o)->next = g->localgc; /* return it to 'localgc' list */ g->localgc = o; + resetbit(gch(o)->marked, LOCALMARK); } else { /* return it to 'allgc' list */ gch(o)->next = g->allgc; g->allgc = o; l_setbit(gch(o)->marked, LOCALMARK); } - resetbit(gch(o)->marked, FINALIZEDBIT); /* object is back in 'allgc' */ + resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ if (issweepphase(g)) makewhite(g, o); /* "sweep" object */ return o; @@ -848,8 +848,9 @@ static GCObject **findlast (GCObject **p) { ** move all unreachable objects (or 'all' objects) that need ** finalization from list 'p' to list 'tobefnz' (to be finalized) */ -static void separatetobefnz_aux (global_State *g, GCObject **p, int all) { +static void separatetobefnz (global_State *g, int all) { GCObject *curr; + GCObject **p = &g->finobj; GCObject **lastnext = findlast(&g->tobefnz); while ((curr = *p) != NULL) { /* traverse all finalizable objects */ lua_assert(tofinalize(curr)); @@ -865,15 +866,9 @@ static void separatetobefnz_aux (global_State *g, GCObject **p, int all) { } -static void separatetobefnz (global_State *g, int all) { - separatetobefnz_aux(g, &g->localfin, all); - separatetobefnz_aux(g, &g->finobj, all); -} - - /* ** if object 'o' has a finalizer, remove it from 'allgc' list (must -** search the list to find it) and link it in 'localfin' or 'finobj' list. +** search the list to find it) and link it in 'finobj' list. */ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { global_State *g = G(L); @@ -890,9 +885,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; for (; *p != o; p = &gch(*p)->next) { /* empty */ } *p = o->gch.next; /* remove 'o' from its list */ - p = (testbit(o->gch.marked, LOCALMARK)) ? &g->finobj : &g->localfin; - o->gch.next = *p; /* link it in a "fin" list */ - *p = o; + o->gch.next = g->finobj; /* link it in "fin" list */ + g->finobj = o; l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ if (issweepphase(g)) makewhite(g, o); /* "sweep" object */ @@ -966,20 +960,15 @@ static void localsweep (lua_State *L, global_State *g) { } -static void separatelocal (global_State *g, int all) { - GCObject **p = &g->localfin; +static void separatelocal (global_State *g) { + GCObject **p = &g->finobj; GCObject **lastnext = findlast(&g->tobefnz); while (*p != NULL) { GCObject *curr = *p; - if (!islocal(curr)) { /* is 'curr' no more local? */ - *p = curr->gch.next; /* remove 'curr' from list */ - curr->gch.next = g->finobj; /* link 'curr' in 'finobj' list */ - g->finobj = curr; - /* mark it as out of local list */ - l_setbit(curr->gch.marked, LOCALMARK); - } + if (!islocal(curr)) /* is 'curr' no more local? */ + p = &curr->gch.next; /* go to next element */ else { /* still local */ - if (testbit(curr->gch.marked, LOCALMARK) && !all) { /* locally alive? */ + if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */ resetbit(curr->gch.marked, LOCALMARK); p = &curr->gch.next; /* go to next element */ } @@ -999,7 +988,7 @@ static void luaC_localcollection (lua_State *L) { lua_assert(g->gcstate == GCSpause); localmark(g); localsweep(L, g); - separatelocal(g, 0); + separatelocal(g); callallpendingfinalizers(L, 1); } @@ -1050,13 +1039,12 @@ static int entersweep (lua_State *L) { void luaC_freeallobjects (lua_State *L) { global_State *g = G(L); separatetobefnz(g, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL && g->localfin == NULL); + lua_assert(g->finobj == 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->allgc); sweepwholelist(L, &g->mainthread->next); @@ -1155,12 +1143,9 @@ static lu_mem singlestep (lua_State *L) { return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); } case GCSswpthreads: { /* sweep threads */ - return sweepstep(L, g, GCSswplocalfin, &g->localfin); - } - case GCSswplocalfin: { /* sweep local objects with finalizers */ return sweepstep(L, g, GCSswpfinobj, &g->finobj); } - case GCSswpfinobj: { /* sweep non-local objects with finalizers */ + case GCSswpfinobj: { /* sweep objects with finalizers */ return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); } case GCSswptobefnz: { /* sweep objects to be finalized */ diff --git a/lgc.h b/lgc.h index 88bd556a..43cfb851 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.75 2013/09/11 14:47:08 roberto Exp roberto $ +** $Id: lgc.h,v 2.76 2013/09/11 20:15:31 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -39,13 +39,12 @@ #define GCSpropagate 0 #define GCSatomic 1 #define GCSswplocalgc 2 -#define GCSswpallgc 4 -#define GCSswpthreads 3 -#define GCSswplocalfin 5 -#define GCSswpfinobj 6 -#define GCSswptobefnz 7 -#define GCSswpend 8 -#define GCSpause 9 +#define GCSswpallgc 3 +#define GCSswpthreads 4 +#define GCSswpfinobj 5 +#define GCSswptobefnz 6 +#define GCSswpend 7 +#define GCSpause 8 #define issweepphase(g) \ diff --git a/lstate.c b/lstate.c index fafef92e..2f21f98e 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.115 2013/09/17 15:40:06 roberto Exp roberto $ +** $Id: lstate.c,v 2.116 2013/11/08 17:34:22 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -320,7 +320,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->panic = NULL; g->version = NULL; g->gcstate = GCSpause; - g->localgc = g->localfin = g->allgc = g->finobj = NULL; + g->localgc = g->allgc = g->finobj = NULL; g->tobefnz = NULL; g->fixedgc = NULL; g->sweepgc = NULL; diff --git a/lstate.h b/lstate.h index e32f8b4f..49b5d24e 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.96 2013/09/13 16:21:52 roberto Exp roberto $ +** $Id: lstate.h,v 2.97 2013/09/17 15:40:06 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -23,9 +23,8 @@ ** ** 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; +** finobj: all 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). @@ -119,7 +118,6 @@ typedef struct global_State { lu_byte gcrunning; /* true if GC is running */ GCObject *allgc; /* list of all collectable objects */ GCObject *localgc; /* list of local objects */ - GCObject *localfin; /* list of local objects with finalizers */ GCObject **sweepgc; /* current position of sweep in list */ GCObject *finobj; /* list of collectable objects with finalizers */ GCObject *gray; /* list of gray objects */ diff --git a/ltests.c b/ltests.c index d062d167..6923cef5 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.161 2013/12/18 14:12:03 roberto Exp roberto $ +** $Id: ltests.c,v 2.162 2013/12/30 20:47:58 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -338,7 +338,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { lua_assert(maybedead); else { lua_assert(g->gcstate != GCSpause || iswhite(o)); - lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK)); switch (gch(o)->tt) { case LUA_TUSERDATA: { Table *mt = gco2u(o)->metatable; @@ -456,19 +455,12 @@ int lua_checkmemory (lua_State *L) { 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) { - checkobject(g, o, 0); - lua_assert(tofinalize(o) && !testbit(o->gch.marked, LOCALMARK)); - lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); - } /* check 'finobj' list */ checkgray(g, g->finobj); for (o = g->finobj; o != NULL; o = gch(o)->next) { checkobject(g, o, 0); - lua_assert(tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); - lua_assert(testbit(o->gch.marked, NOLOCALBIT)); + lua_assert(tofinalize(o)); + lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK)); lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); } /* check 'tobefnz' list */ @@ -655,10 +647,13 @@ static int gc_local (lua_State *L) { static int gc_state (lua_State *L) { static const char *statenames[] = {"propagate", "atomic", - "sweeplocalgc", "sweepallgc", "sweepthreads", "sweeplocalfin", - "sweepfinobj", "sweeptobefnz", "sweepend", "pause", ""}; - int option = luaL_checkoption(L, 1, "", statenames); - if (option == GCSpause + 1) { + "sweeplocalgc", "sweepallgc", "sweepthreads", "sweepfinobj", + "sweeptobefnz", "sweepend", "pause", ""}; + static const int states[] = {GCSpropagate, GCSatomic, + GCSswplocalgc, GCSswpallgc, GCSswpthreads, GCSswpfinobj, + GCSswptobefnz, GCSswpend, GCSpause, -1}; + int option = states[luaL_checkoption(L, 1, "", statenames)]; + if (option == -1) { lua_pushstring(L, statenames[G(L)->gcstate]); return 1; }