diff --git a/lgc.c b/lgc.c index 0ae5aafd..f19ca70b 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.68 2010/03/22 18:28:03 roberto Exp $ +** $Id: lgc.c,v 2.69 2010/03/23 20:16:06 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -33,8 +33,10 @@ #define maskcolors (~(bitmask(BLACKBIT)|WHITEBITS)) -#define makewhite(g,x) \ - (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) +#define makewhitew(w,x) \ + (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | (w))) + +#define makewhite(g,x) makewhitew(luaC_white(g), x) #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) @@ -127,7 +129,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, global_State *g = G(L); GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset); if (list == NULL) - list = &g->rootgc; /* standard list for collectable objects */ + list = &g->allgc; /* standard list for collectable objects */ gch(o)->marked = luaC_white(g); gch(o)->tt = tt; gch(o)->next = *list; @@ -139,8 +141,8 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, void luaC_linkupval (lua_State *L, UpVal *uv) { global_State *g = G(L); GCObject *o = obj2gco(uv); - gch(o)->next = g->rootgc; /* link upvalue into `rootgc' list */ - g->rootgc = o; + gch(o)->next = g->allgc; /* link upvalue into `allgc' list */ + g->allgc = o; if (isgray(o)) { if (g->gcstate == GCSpropagate) { gray2black(o); /* closed upvalues need barrier */ @@ -549,8 +551,9 @@ static void sweepthread (lua_State *L, lua_State *L1, int alive) { static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); - int deadmask = otherwhite(g); int gckind = g->gckind; + int deadmask = otherwhite(g); + int white = luaC_white(g); while ((curr = *p) != NULL && count-- > 0) { int alive = (gch(curr)->marked ^ WHITEBITS) & deadmask; if (gch(curr)->tt == LUA_TTHREAD) @@ -559,7 +562,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); /* in generational mode all live objects are kept black, which means they grow to old generation */ - if (gckind != KGC_GEN) makewhite(g, curr); + if (gckind != KGC_GEN) makewhitew(white, curr); p = &gch(curr)->next; } else { /* must erase `curr' */ @@ -597,8 +600,8 @@ static void checkSizes (lua_State *L) { static Udata *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ - gch(o)->next = g->rootgc; /* return it to `root' list */ - g->rootgc = o; + gch(o)->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; lua_assert(isfinalized(gch(o))); resetbit(gch(o)->marked, SEPARATED); /* mark it as such */ makewhite(g, o); @@ -643,7 +646,7 @@ static void GCTM (lua_State *L, int propagateerrors) { /* move 'dead' udata that need finalization to list 'tobefnz' */ void luaC_separateudata (lua_State *L, int all) { global_State *g = G(L); - GCObject **p = &g->mainthread->next; + GCObject **p = &g->udgc; GCObject *curr; GCObject **lastnext = &g->tobefnz; /* find last 'next' field in 'tobefnz' list (to insert elements in its end) */ @@ -655,7 +658,7 @@ void luaC_separateudata (lua_State *L, int all) { p = &gch(curr)->next; /* don't bother with it */ else { l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ - *p = gch(curr)->next; /* remove 'curr' from 'rootgc' list */ + *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ /* link 'curr' at the end of 'tobefnz' list */ gch(curr)->next = *lastnext; *lastnext = curr; @@ -671,13 +674,12 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { isfinalized(&u->uv) || /* ... or is finalized... */ gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalization? */ return; /* nothing to be done */ - else { /* move 'u' to 2nd part of root list */ + else { /* move 'u' to 'udgc' list */ GCObject **p; - for (p = &g->rootgc; *p != obj2gco(u); p = &gch(*p)->next) - lua_assert(*p != obj2gco(g->mainthread)); /* 'u' must be in this list */ + for (p = &g->allgc; *p != obj2gco(u); p = &gch(*p)->next) ; *p = u->uv.next; /* remove 'u' from root list */ - u->uv.next = g->mainthread->next; /* re-link it in list */ - g->mainthread->next = obj2gco(u); + u->uv.next = g->udgc; /* re-link it in list */ + g->udgc = obj2gco(u); l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ } } @@ -697,8 +699,9 @@ void luaC_freeallobjects (lua_State *L) { while (g->tobefnz) GCTM(L, 0); /* Call all pending finalizers */ /* following "white" makes all objects look dead */ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); - sweepwholelist(L, &g->rootgc); - lua_assert(g->rootgc == obj2gco(g->mainthread) && + sweepwholelist(L, &g->udgc); + sweepwholelist(L, &g->allgc); + lua_assert(g->allgc == obj2gco(g->mainthread) && g->mainthread->next == NULL); for (i = 0; i < g->strt.size; i++) /* free all string lists */ sweepwholelist(L, &g->strt.hash[i]); @@ -761,19 +764,21 @@ static l_mem singlestep (lua_State *L) { return GCSWEEPCOST; } else { /* nothing more to sweep */ - g->sweepgc = &g->rootgc; - g->gcstate = GCSsweep; /* sweep all other objects */ + g->sweepgc = &g->udgc; /* sweep all userdata */ + g->gcstate = GCSsweepudata; + checkSizes(L); return 0; } } + case GCSsweepudata: case GCSsweep: { if (*g->sweepgc) { g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); return GCSWEEPMAX*GCSWEEPCOST; } - else { /* nothing more to sweep */ - checkSizes(L); - g->gcstate = GCSfinalize; /* end sweep phase */ + else { /* go to next phase */ + g->sweepgc = &g->allgc; /* useless (but harmless) in GCSsweep case */ + g->gcstate = (g->gcstate == GCSsweep) ? GCSfinalize : GCSsweep; return 0; } } @@ -856,8 +861,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { g->gcstate = GCSsweepstring; } /* finish any pending sweep phase */ - luaC_runtilstate(L, ~bit2mask(GCSsweepstring, GCSsweep)); - lua_assert(g->gcstate == GCSpause || g->gcstate == GCSfinalize); + luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); g->gcstate = GCSpause; /* start a new collection */ /* run collector up to finalizers */ luaC_runtilstate(L, bitmask(GCSfinalize)); diff --git a/lgc.h b/lgc.h index aa969b38..c01a8cc8 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.26 2009/12/11 21:31:14 roberto Exp roberto $ +** $Id: lgc.h,v 2.27 2009/12/16 16:42:58 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -18,8 +18,9 @@ #define GCSpropagate 1 #define GCSatomic 2 #define GCSsweepstring 3 -#define GCSsweep 4 -#define GCSfinalize 5 +#define GCSsweepudata 4 +#define GCSsweep 5 +#define GCSfinalize 6 @@ -45,12 +46,10 @@ ** bit 1 - object is white (type 1) ** bit 2 - object is black ** bit 3 - for userdata: has been finalized -** bit 4 - for userdata: it's in 2nd part of rootgc list or in tobefnz +** bit 4 - for userdata: it's in 'udgc' list or in 'tobefnz' ** bit 5 - object is fixed (should not be collected) ** bit 6 - object is "super" fixed (only the main thread) */ - - #define WHITE0BIT 0 #define WHITE1BIT 1 #define BLACKBIT 2 @@ -58,6 +57,7 @@ #define SEPARATED 4 #define FIXEDBIT 5 #define SFIXEDBIT 6 + #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) diff --git a/lstate.c b/lstate.c index c2fe534a..200ddd69 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.70 2010/03/19 21:04:17 roberto Exp roberto $ +** $Id: lstate.c,v 2.71 2010/03/22 17:45:55 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -264,7 +264,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->panic = NULL; g->version = lua_version(NULL); g->gcstate = GCSpause; - g->rootgc = obj2gco(L); + g->allgc = obj2gco(L); + g->udgc = NULL; g->tobefnz = NULL; g->totalbytes = sizeof(LG); g->gcpause = LUAI_GCPAUSE; diff --git a/lstate.h b/lstate.h index ebf4e4af..45eccf8a 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.54 2010/03/13 15:55:42 roberto Exp roberto $ +** $Id: lstate.h,v 2.55 2010/03/22 18:28:03 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -19,7 +19,7 @@ ** Some notes about garbage-collected objects: All objects in Lua must ** be kept somehow accessible until being freed. ** -** Lua keeps most objects linked in list g->rootgc. The link uses field +** Lua keeps most objects linked in list g->allgc. The link uses field ** 'next' of the CommonHeader. ** ** Strings are kept in several lists headed by the array g->strt.hash. @@ -32,9 +32,7 @@ ** when traversing the respective threads, but the thread may already be ** dead, while the upvalue is still accessible through closures.) ** -** Userdata with finalizers are kept in the list g->rootgc, but after -** the mainthread, which should be otherwise the last element in the -** list, as it was the first one inserted there. +** Userdata with finalizers are kept in the list g->udgc. ** ** The list g->tobefnz links all userdata being finalized. @@ -124,7 +122,8 @@ typedef struct global_State { lu_byte gcstate; /* state of garbage collector */ lu_byte gckind; /* kind of GC running */ int sweepstrgc; /* position of sweep in `strt' */ - GCObject *rootgc; /* list of all collectable objects */ + GCObject *allgc; /* list of all collectable objects */ + GCObject *udgc; /* list of collectable userdata with finalizers */ GCObject **sweepgc; /* current position of sweep */ GCObject *gray; /* list of gray objects */ GCObject *grayagain; /* list of objects to be traversed atomically */ diff --git a/ltests.c b/ltests.c index 3d0fa117..123ff64e 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.86 2009/12/22 15:32:50 roberto Exp roberto $ +** $Id: ltests.c,v 2.87 2010/01/13 16:18:25 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -188,7 +188,7 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { static void printobj (global_State *g, GCObject *o) { int i = 0; GCObject *p; - for (p = g->rootgc; p != o && p != NULL; p = gch(p)->next) i++; + for (p = g->allgc; p != o && p != NULL; p = gch(p)->next) i++; if (p == NULL) i = -1; printf("%d:%s(%p)-%c(%02X)", i, typename(gch(o)->tt), (void *)o, isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); @@ -375,12 +375,12 @@ int lua_checkmemory (lua_State *L) { checkliveness(g, &g->l_registry); lua_assert(!isdead(g, obj2gco(g->l_gt))); checkstack(g, g->mainthread); - for (o = g->rootgc; o != obj2gco(g->mainthread); o = gch(o)->next) { + for (o = g->allgc; o != obj2gco(g->mainthread); o = gch(o)->next) { lua_assert(!testbits(o->gch.marked, bit2mask(SEPARATED, SFIXEDBIT))); checkobject(g, o); } lua_assert(testbit(o->gch.marked, SFIXEDBIT)); - for (o = gch(o)->next; o != NULL; o = gch(o)->next) { + for (o = g->udgc; o != NULL; o = gch(o)->next) { lua_assert(gch(o)->tt == LUA_TUSERDATA && !isdead(g, o) && testbit(o->gch.marked, SEPARATED));