From 4df8800a01c7e44800ce59339c66b9257cd75c2a Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 10 Feb 2005 11:25:02 -0200 Subject: cleaner way to free all objects --- lfunc.c | 6 +++--- lgc.c | 54 +++++++++++++++++++++++------------------------------- lgc.h | 14 +++++++++----- lstate.c | 9 +++++---- 4 files changed, 40 insertions(+), 43 deletions(-) diff --git a/lfunc.c b/lfunc.c index 65d70cfb..d69f75dd 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 2.5 2004/11/24 19:20:21 roberto Exp $ +** $Id: lfunc.c,v 2.7 2005/01/19 15:54:26 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -57,7 +57,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { lua_assert(p->v != &p->u.value); if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(G(L), obj2gco(p))) /* is it dead? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ changewhite(obj2gco(p)); /* ressurect it */ return p; } @@ -106,7 +106,7 @@ void luaF_close (lua_State *L, StkId level) { setobj(L, &uv->u.value, uv->v); if (isgray(o)) { gray2black(o); /* closed upvalues are never gray */ - luaC_barrier(L, uv, uv->v); + luaC_barrier(L, uv, &uv->u.value); } uv->v = &uv->u.value; /* now current value lives here */ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ diff --git a/lgc.c b/lgc.c index d40b174c..27198217 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.21 2005/01/14 14:19:42 roberto Exp $ +** $Id: lgc.c,v 2.22 2005/01/18 17:18:09 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -29,13 +29,11 @@ #define GCFINALIZECOST 100 -#define FIXEDMASK bitmask(FIXEDBIT) - #define maskmarks \ - cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) + cast(lu_byte, ~(bitmask(BLACKBIT)|WHITEBITS)) #define makewhite(g,x) \ - ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite) + ((x)->gch.marked = ((x)->gch.marked & maskmarks) | luaC_white(g)) #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) @@ -60,6 +58,8 @@ reallymarkobject(g, obj2gco(t)); } +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpace) + static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); @@ -400,24 +400,23 @@ static void freeobj (lua_State *L, GCObject *o) { -#define sweepwholelist(L,p) sweeplist(L,p,LUA_MAXINT32) +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); - int whitebit = otherwhite(g); - int deadmask = whitebit | FIXEDMASK; + int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { - if ((curr->gch.marked ^ whitebit) & deadmask) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); - makewhite(g, curr); - if (curr->gch.tt == LUA_TTHREAD) - sweepwholelist(L, &gco2th(curr)->openupval); + makewhite(g, curr); /* make it white (for next cycle) */ p = &curr->gch.next; } - else { - lua_assert(isdead(g, curr)); + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); *p = curr->gch.next; if (curr == g->rootgc) /* is the first element of the list? */ g->rootgc = curr->gch.next; /* adjust first */ @@ -428,21 +427,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { } - -static void freelist (lua_State *L, GCObject **p) { - while (*p) { - GCObject *curr = *p; - *p = (*p)->gch.next; - if (curr != obj2gco(L)) - freeobj(L, curr); - } -} - - static void checkSizes (lua_State *L) { global_State *g = G(L); /* check size of string hash */ - if (g->strt.nuse < cast(lu_int32, G(L)->strt.size/4) && + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && g->strt.size > MINSTRTABSIZE*2) luaS_resize(L, g->strt.size/2); /* table is too big */ /* check size of buffer */ @@ -487,9 +475,10 @@ void luaC_callGCTM (lua_State *L) { void luaC_freeall (lua_State *L) { global_State *g = G(L); int i; - freelist(L, &g->rootgc); + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); for (i = 0; i < g->strt.size; i++) /* free all string lists */ - freelist(L, &G(L)->strt.hash[i]); + sweepwholelist(L, &g->strt.hash[i]); } @@ -604,6 +593,8 @@ static l_mem singlestep (lua_State *L) { void luaC_step (lua_State *L) { global_State *g = G(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; do { lim -= singlestep(L); @@ -620,7 +611,7 @@ void luaC_step (lua_State *L) { } else { lua_assert(g->totalbytes >= g->estimate); - g->GCthreshold = (g->estimate/100) * g->gcpace; + setthreshold(g); } } @@ -637,6 +628,7 @@ void luaC_fullgc (lua_State *L) { g->weak = NULL; g->gcstate = GCSsweepstring; } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); /* finish any pending sweep phase */ while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); @@ -646,7 +638,7 @@ void luaC_fullgc (lua_State *L) { while (g->gcstate != GCSpause) { singlestep(L); } - g->GCthreshold = 2*g->estimate; + setthreshold(g); } diff --git a/lgc.h b/lgc.h index bec5a728..c3039ee4 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $ +** $Id: lgc.h,v 2.10 2005/01/19 15:54:26 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -47,8 +47,10 @@ ** bit 3 - for tables: has weak keys ** bit 4 - for tables: has weak values ** 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 @@ -56,21 +58,23 @@ #define KEYWEAKBIT 3 #define VALUEWEAKBIT 4 #define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isgray(x) (!isblack(x) && !iswhite(x)) -#define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g)) +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) -#define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -#define luaC_white(g) cast(lu_byte, (g)->currentwhite) +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \ diff --git a/lstate.c b/lstate.c index 7596a55d..48d383f1 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.22 2005/01/14 14:19:42 roberto Exp $ +** $Id: lstate.c,v 2.23 2005/01/18 17:18:09 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -114,7 +114,7 @@ static void close_state (lua_State *L) { global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_freeall(L); /* collect all objects */ - lua_assert(g->rootgc == NULL); + lua_assert(g->rootgc == obj2gco(L)); lua_assert(g->strt.nuse == 0); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); luaZ_freebuffer(L, &g->buff); @@ -156,8 +156,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g = &((LG *)L)->g; L->next = NULL; L->tt = LUA_TTHREAD; - L->marked = g->currentwhite = bitmask(WHITE0BIT); - setbit(L->marked, FIXEDBIT); + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); preinit_state(L, g); g->realloc = f; g->ud = ud; -- cgit v1.2.3-55-g6feb