diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-05-06 15:18:07 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-05-06 15:18:07 -0300 |
commit | 25951e0ea56874731d2bddf3982b1be64bfc79f0 (patch) | |
tree | c850a1367a225ac64a3e3f10f6496adba0e1d8fd /lgc.c | |
parent | a4f20e3c8b08ad55f40dfe53ace80cbcf67c0f46 (diff) | |
download | lua-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)
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 57 |
1 files changed, 29 insertions, 28 deletions
@@ -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) { | |||
279 | static void markbeingfnz (global_State *g) { | 279 | static 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) { | |||
293 | static void remarkupvals (global_State *g) { | 292 | static 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 | */ |
594 | static void sweepthread (lua_State *L, lua_State *L1, int alive) { | 592 | static 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 | */ |
615 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 613 | static 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; |