From d2ea5b00b7c1832d2889fe0cb6bbf4b82e7a9f98 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 5 May 2010 15:58:36 -0300 Subject: [PATCH] new function 'luaC_changemode' + bug: objects entering the 'allgc' list must have their OLDBIT cleared (upvalues being cleared) + bug: in 'checkSizes', KGC_EMERGENCY is stored in 'gckind' field, not in 'gcstate' + current white changes when entering sweep phase (so there are dead objects only in that phase) --- lgc.c | 55 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/lgc.c b/lgc.c index bb21b74c..e51b2b0d 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.87 2010/05/04 18:09:06 roberto Exp roberto $ +** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -170,6 +170,7 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { lua_assert(!isblack(o)); /* open upvalues are never black */ if (isgray(o)) { if (keepinvariant(g)) { + resetbit(o->gch.marked, OLDBIT); gray2black(o); /* it is being visited now */ markvalue(g, uv->v); } @@ -300,7 +301,8 @@ static void remarkupvals (global_State *g) { /* -** mark root set +** mark root set and reset all gray lists, to start a new +** incremental (or full) collection */ static void markroot (lua_State *L) { global_State *g = G(L); @@ -655,12 +657,12 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { static void checkSizes (lua_State *L) { global_State *g = G(L); - int hs = g->strt.size / 2; /* half the size of the string table */ - if (g->gcstate == KGC_EMERGENCY) return; - if (g->strt.nuse < cast(lu_int32, hs)) { /* using less than half its size? */ + if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ + int hs = g->strt.size / 2; /* half the size of the string table */ + if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ luaS_resize(L, hs); /* halve its size */ + luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ } - luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ } @@ -668,6 +670,7 @@ static Udata *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ Udata *u = rawgco2u(o); lua_assert(isfinalized(&u->uv)); + lua_assert(!testbit(u->uv.marked, OLDBIT)); g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ u->uv.next = g->allgc; /* return it to 'allgc' list */ g->allgc = o; @@ -769,6 +772,33 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { ** ======================================================= */ + +#define sweepphases \ + (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) + +/* +** change GC mode +*/ +void luaC_changemode (lua_State *L, int mode) { + global_State *g = G(L); + if (mode == g->gckind) return; /* nothing to change */ + if (mode == KGC_GEN) { /* change to generational mode */ + /* make sure gray lists are consistent */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + g->lastmajormem = g->totalbytes; + g->gckind = KGC_GEN; + } + else { /* change to incremental mode */ + /* sweep all objects to turn them back to white + (as white has not changed, nothing extra will be collected) */ + g->sweepstrgc = 0; + g->gcstate = GCSsweepstring; + g->gckind = KGC_NORMAL; + luaC_runtilstate(L, ~sweepphases); + } +} + + /* ** call all pending finalizers */ static void callallpendingfinalizers (lua_State *L, int propagateerrors) { @@ -817,7 +847,8 @@ static void atomic (lua_State *L) { cleartable(g->weak); cleartable(g->ephemeron); cleartable(g->allweak); - lua_checkmemory(L); + g->sweepstrgc = 0; /* prepare to sweep strings */ + g->gcstate = GCSsweepstring; g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ } @@ -837,8 +868,6 @@ static l_mem singlestep (lua_State *L) { else { /* no more `gray' objects */ g->gcstate = GCSatomic; /* finish mark phase */ atomic(L); - g->sweepstrgc = 0; /* prepare to sweep strings */ - g->gcstate = GCSsweepstring; return GCATOMICCOST; } } @@ -933,7 +962,7 @@ void luaC_step (lua_State *L) { /* -** performs a full GC cycle; if "isememrgency", does not call +** performs a full GC cycle; if "isemergency", does not call ** finalizers (which could change stack positions) */ void luaC_fullgc (lua_State *L, int isemergency) { @@ -942,14 +971,14 @@ void luaC_fullgc (lua_State *L, int isemergency) { lua_assert(origkind != KGC_EMERGENCY); if (!isemergency) /* do not run finalizers during emergency GC */ callallpendingfinalizers(L, 1); - g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; - if (g->gcstate == GCSpropagate) { /* marking phase? */ + if (keepinvariant(g)) { /* marking phase? */ /* must sweep all objects to turn them back to white (as white has not changed, nothing will be collected) */ g->sweepstrgc = 0; g->gcstate = GCSsweepstring; } - /* finish any pending sweep phase */ + g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; + /* finish any pending sweep phase to start a new cycle */ luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collector */ luaC_runtilstate(L, ~bitmask(GCSpause));