diff --git a/lgc.c b/lgc.c index e51b2b0d..422a49d7 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 roberto Exp roberto $ +** $Id: lgc.c,v 2.89 2010/05/05 18:58:36 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -279,7 +279,6 @@ static void markmt (global_State *g) { static void markbeingfnz (global_State *g) { GCObject *o; for (o = g->tobefnz; o != NULL; o = gch(o)->next) { - lua_assert(testbit(gch(o)->marked, SEPARATED)); makewhite(g, o); reallymarkobject(g, o); } @@ -293,7 +292,6 @@ static void markbeingfnz (global_State *g) { static void remarkupvals (global_State *g) { UpVal *uv; for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); if (isgray(obj2gco(uv))) markvalue(g, uv->v); } @@ -591,56 +589,59 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); ** sweep the (open) upvalues of a thread and resize its stack and ** list of call-info structures. */ -static void sweepthread (lua_State *L, lua_State *L1, int alive) { +static void sweepthread (lua_State *L, lua_State *L1) { if (L1->stack == NULL) return; /* stack not completely built yet */ sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ luaE_freeCI(L1); /* free extra CallInfo slots */ /* should not change the stack during an emergency gc cycle */ - if (alive && G(L)->gckind != KGC_EMERGENCY) + if (G(L)->gckind != KGC_EMERGENCY) luaD_shrinkstack(L1); } /* -** sweep a list of GCObjects, erasing dead objects, where a dead (not -** alive) object is one marked with the "old" (non current) white and -** not fixed. +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead (not alive) object is one marked with the "old" +** (non current) white and not fixed. ** In non-generational mode, change all non-dead objects back to white, ** preparing for next collection cycle. -** In generational mode, keep black objects black, and also mark them -** as old; stop when hitting an old object, as all objects after that +** In generational mode, keep black objects black, and also mark them as +** old; stop when hitting an old object, as all objects after that ** one will be old too. ** When object is a thread, sweep its list of open upvalues too. */ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { global_State *g = G(L); - int gckind = g->gckind; int deadmask = otherwhite(g); - int white = luaC_white(g); - GCObject *curr; - while ((curr = *p) != NULL && count-- > 0) { + int toclear, toset; /* bits to clear and to set in all live objects */ + if (g->gckind == KGC_GEN) { /* generational mode? */ + toclear = ~0; /* clear nothing */ + toset = OLDBIT; /* set the old bit of all surviving objects */ + } + else { /* normal mode */ + toclear = maskcolors; /* clear all color bits */ + toset = luaC_white(g); /* make object white */ + } + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; int marked = gch(curr)->marked; - int alive = (marked ^ WHITEBITS) & deadmask; - if (gch(curr)->tt == LUA_TTHREAD) - sweepthread(L, gco2th(curr), alive); - if (!alive) { + if (!((marked ^ WHITEBITS) & deadmask)) { /* is 'curr' dead? */ lua_assert(isdead(g, curr) || deadmask == 0); *p = gch(curr)->next; /* remove 'curr' from list */ freeobj(L, curr); /* erase 'curr' */ } else { lua_assert(!isdead(g, curr) || testbit(marked, FIXEDBIT)); - if (gckind == KGC_GEN) { /* generational mode? */ - if (testbit(marked, OLDBIT)) { /* old generation? */ - static GCObject *nullp = NULL; - return &nullp; /* stop sweeping this list */ - } - else /* mark as old */ - gch(curr)->marked = cast_byte(marked | bitmask(OLDBIT)); + if (gch(curr)->tt == LUA_TTHREAD) + sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ + if (testbit(marked, OLDBIT)) { /* old generation? */ + static GCObject *nullp = NULL; + lua_assert(g->gckind == KGC_GEN); /* can happen only in gen. mode */ + return &nullp; /* stop sweeping this list */ } - else /* not generational; makewhite */ - gch(curr)->marked = cast_byte((marked & maskcolors) | white); - p = &gch(curr)->next; + /* update marks */ + gch(curr)->marked = cast_byte((marked & toclear) | toset); + p = &gch(curr)->next; /* go to next element */ } } return p;