aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-05-06 15:18:07 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-05-06 15:18:07 -0300
commit25951e0ea56874731d2bddf3982b1be64bfc79f0 (patch)
treec850a1367a225ac64a3e3f10f6496adba0e1d8fd
parenta4f20e3c8b08ad55f40dfe53ace80cbcf67c0f46 (diff)
downloadlua-25951e0ea56874731d2bddf3982b1be64bfc79f0.tar.gz
lua-25951e0ea56874731d2bddf3982b1be64bfc79f0.tar.bz2
lua-25951e0ea56874731d2bddf3982b1be64bfc79f0.zip
some cleaning in 'sweeplist' (threads do not need to be traversed
if they are going to be collected + use of bit masks to unify differences in generational and incremental modes)
-rw-r--r--lgc.c57
1 files changed, 29 insertions, 28 deletions
diff --git a/lgc.c b/lgc.c
index e51b2b0d..422a49d7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 roberto Exp roberto $ 2** $Id: lgc.c,v 2.89 2010/05/05 18:58:36 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -279,7 +279,6 @@ static void markmt (global_State *g) {
279static void markbeingfnz (global_State *g) { 279static void markbeingfnz (global_State *g) {
280 GCObject *o; 280 GCObject *o;
281 for (o = g->tobefnz; o != NULL; o = gch(o)->next) { 281 for (o = g->tobefnz; o != NULL; o = gch(o)->next) {
282 lua_assert(testbit(gch(o)->marked, SEPARATED));
283 makewhite(g, o); 282 makewhite(g, o);
284 reallymarkobject(g, o); 283 reallymarkobject(g, o);
285 } 284 }
@@ -293,7 +292,6 @@ static void markbeingfnz (global_State *g) {
293static void remarkupvals (global_State *g) { 292static void remarkupvals (global_State *g) {
294 UpVal *uv; 293 UpVal *uv;
295 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { 294 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
296 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
297 if (isgray(obj2gco(uv))) 295 if (isgray(obj2gco(uv)))
298 markvalue(g, uv->v); 296 markvalue(g, uv->v);
299 } 297 }
@@ -591,56 +589,59 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
591** sweep the (open) upvalues of a thread and resize its stack and 589** sweep the (open) upvalues of a thread and resize its stack and
592** list of call-info structures. 590** list of call-info structures.
593*/ 591*/
594static void sweepthread (lua_State *L, lua_State *L1, int alive) { 592static void sweepthread (lua_State *L, lua_State *L1) {
595 if (L1->stack == NULL) return; /* stack not completely built yet */ 593 if (L1->stack == NULL) return; /* stack not completely built yet */
596 sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ 594 sweepwholelist(L, &L1->openupval); /* sweep open upvalues */
597 luaE_freeCI(L1); /* free extra CallInfo slots */ 595 luaE_freeCI(L1); /* free extra CallInfo slots */
598 /* should not change the stack during an emergency gc cycle */ 596 /* should not change the stack during an emergency gc cycle */
599 if (alive && G(L)->gckind != KGC_EMERGENCY) 597 if (G(L)->gckind != KGC_EMERGENCY)
600 luaD_shrinkstack(L1); 598 luaD_shrinkstack(L1);
601} 599}
602 600
603 601
604/* 602/*
605** sweep a list of GCObjects, erasing dead objects, where a dead (not 603** sweep at most 'count' elements from a list of GCObjects erasing dead
606** alive) object is one marked with the "old" (non current) white and 604** objects, where a dead (not alive) object is one marked with the "old"
607** not fixed. 605** (non current) white and not fixed.
608** In non-generational mode, change all non-dead objects back to white, 606** In non-generational mode, change all non-dead objects back to white,
609** preparing for next collection cycle. 607** preparing for next collection cycle.
610** In generational mode, keep black objects black, and also mark them 608** In generational mode, keep black objects black, and also mark them as
611** as old; stop when hitting an old object, as all objects after that 609** old; stop when hitting an old object, as all objects after that
612** one will be old too. 610** one will be old too.
613** When object is a thread, sweep its list of open upvalues too. 611** When object is a thread, sweep its list of open upvalues too.
614*/ 612*/
615static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { 613static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
616 global_State *g = G(L); 614 global_State *g = G(L);
617 int gckind = g->gckind;
618 int deadmask = otherwhite(g); 615 int deadmask = otherwhite(g);
619 int white = luaC_white(g); 616 int toclear, toset; /* bits to clear and to set in all live objects */
620 GCObject *curr; 617 if (g->gckind == KGC_GEN) { /* generational mode? */
621 while ((curr = *p) != NULL && count-- > 0) { 618 toclear = ~0; /* clear nothing */
619 toset = OLDBIT; /* set the old bit of all surviving objects */
620 }
621 else { /* normal mode */
622 toclear = maskcolors; /* clear all color bits */
623 toset = luaC_white(g); /* make object white */
624 }
625 while (*p != NULL && count-- > 0) {
626 GCObject *curr = *p;
622 int marked = gch(curr)->marked; 627 int marked = gch(curr)->marked;
623 int alive = (marked ^ WHITEBITS) & deadmask; 628 if (!((marked ^ WHITEBITS) & deadmask)) { /* is 'curr' dead? */
624 if (gch(curr)->tt == LUA_TTHREAD)
625 sweepthread(L, gco2th(curr), alive);
626 if (!alive) {
627 lua_assert(isdead(g, curr) || deadmask == 0); 629 lua_assert(isdead(g, curr) || deadmask == 0);
628 *p = gch(curr)->next; /* remove 'curr' from list */ 630 *p = gch(curr)->next; /* remove 'curr' from list */
629 freeobj(L, curr); /* erase 'curr' */ 631 freeobj(L, curr); /* erase 'curr' */
630 } 632 }
631 else { 633 else {
632 lua_assert(!isdead(g, curr) || testbit(marked, FIXEDBIT)); 634 lua_assert(!isdead(g, curr) || testbit(marked, FIXEDBIT));
633 if (gckind == KGC_GEN) { /* generational mode? */ 635 if (gch(curr)->tt == LUA_TTHREAD)
634 if (testbit(marked, OLDBIT)) { /* old generation? */ 636 sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */
635 static GCObject *nullp = NULL; 637 if (testbit(marked, OLDBIT)) { /* old generation? */
636 return &nullp; /* stop sweeping this list */ 638 static GCObject *nullp = NULL;
637 } 639 lua_assert(g->gckind == KGC_GEN); /* can happen only in gen. mode */
638 else /* mark as old */ 640 return &nullp; /* stop sweeping this list */
639 gch(curr)->marked = cast_byte(marked | bitmask(OLDBIT));
640 } 641 }
641 else /* not generational; makewhite */ 642 /* update marks */
642 gch(curr)->marked = cast_byte((marked & maskcolors) | white); 643 gch(curr)->marked = cast_byte((marked & toclear) | toset);
643 p = &gch(curr)->next; 644 p = &gch(curr)->next; /* go to next element */
644 } 645 }
645 } 646 }
646 return p; 647 return p;