diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 56 |
1 files changed, 30 insertions, 26 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.68 2010/03/22 18:28:03 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.69 2010/03/23 20:16:06 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 | */ |
@@ -33,8 +33,10 @@ | |||
33 | 33 | ||
34 | #define maskcolors (~(bitmask(BLACKBIT)|WHITEBITS)) | 34 | #define maskcolors (~(bitmask(BLACKBIT)|WHITEBITS)) |
35 | 35 | ||
36 | #define makewhite(g,x) \ | 36 | #define makewhitew(w,x) \ |
37 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) | 37 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | (w))) |
38 | |||
39 | #define makewhite(g,x) makewhitew(luaC_white(g), x) | ||
38 | 40 | ||
39 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) | 41 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) |
40 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) | 42 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) |
@@ -127,7 +129,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, | |||
127 | global_State *g = G(L); | 129 | global_State *g = G(L); |
128 | GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset); | 130 | GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset); |
129 | if (list == NULL) | 131 | if (list == NULL) |
130 | list = &g->rootgc; /* standard list for collectable objects */ | 132 | list = &g->allgc; /* standard list for collectable objects */ |
131 | gch(o)->marked = luaC_white(g); | 133 | gch(o)->marked = luaC_white(g); |
132 | gch(o)->tt = tt; | 134 | gch(o)->tt = tt; |
133 | gch(o)->next = *list; | 135 | gch(o)->next = *list; |
@@ -139,8 +141,8 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, | |||
139 | void luaC_linkupval (lua_State *L, UpVal *uv) { | 141 | void luaC_linkupval (lua_State *L, UpVal *uv) { |
140 | global_State *g = G(L); | 142 | global_State *g = G(L); |
141 | GCObject *o = obj2gco(uv); | 143 | GCObject *o = obj2gco(uv); |
142 | gch(o)->next = g->rootgc; /* link upvalue into `rootgc' list */ | 144 | gch(o)->next = g->allgc; /* link upvalue into `allgc' list */ |
143 | g->rootgc = o; | 145 | g->allgc = o; |
144 | if (isgray(o)) { | 146 | if (isgray(o)) { |
145 | if (g->gcstate == GCSpropagate) { | 147 | if (g->gcstate == GCSpropagate) { |
146 | gray2black(o); /* closed upvalues need barrier */ | 148 | gray2black(o); /* closed upvalues need barrier */ |
@@ -549,8 +551,9 @@ static void sweepthread (lua_State *L, lua_State *L1, int alive) { | |||
549 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 551 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
550 | GCObject *curr; | 552 | GCObject *curr; |
551 | global_State *g = G(L); | 553 | global_State *g = G(L); |
552 | int deadmask = otherwhite(g); | ||
553 | int gckind = g->gckind; | 554 | int gckind = g->gckind; |
555 | int deadmask = otherwhite(g); | ||
556 | int white = luaC_white(g); | ||
554 | while ((curr = *p) != NULL && count-- > 0) { | 557 | while ((curr = *p) != NULL && count-- > 0) { |
555 | int alive = (gch(curr)->marked ^ WHITEBITS) & deadmask; | 558 | int alive = (gch(curr)->marked ^ WHITEBITS) & deadmask; |
556 | if (gch(curr)->tt == LUA_TTHREAD) | 559 | if (gch(curr)->tt == LUA_TTHREAD) |
@@ -559,7 +562,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
559 | lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); | 562 | lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); |
560 | /* in generational mode all live objects are kept black, which | 563 | /* in generational mode all live objects are kept black, which |
561 | means they grow to old generation */ | 564 | means they grow to old generation */ |
562 | if (gckind != KGC_GEN) makewhite(g, curr); | 565 | if (gckind != KGC_GEN) makewhitew(white, curr); |
563 | p = &gch(curr)->next; | 566 | p = &gch(curr)->next; |
564 | } | 567 | } |
565 | else { /* must erase `curr' */ | 568 | else { /* must erase `curr' */ |
@@ -597,8 +600,8 @@ static void checkSizes (lua_State *L) { | |||
597 | static Udata *udata2finalize (global_State *g) { | 600 | static Udata *udata2finalize (global_State *g) { |
598 | GCObject *o = g->tobefnz; /* get first element */ | 601 | GCObject *o = g->tobefnz; /* get first element */ |
599 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ | 602 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
600 | gch(o)->next = g->rootgc; /* return it to `root' list */ | 603 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
601 | g->rootgc = o; | 604 | g->allgc = o; |
602 | lua_assert(isfinalized(gch(o))); | 605 | lua_assert(isfinalized(gch(o))); |
603 | resetbit(gch(o)->marked, SEPARATED); /* mark it as such */ | 606 | resetbit(gch(o)->marked, SEPARATED); /* mark it as such */ |
604 | makewhite(g, o); | 607 | makewhite(g, o); |
@@ -643,7 +646,7 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
643 | /* move 'dead' udata that need finalization to list 'tobefnz' */ | 646 | /* move 'dead' udata that need finalization to list 'tobefnz' */ |
644 | void luaC_separateudata (lua_State *L, int all) { | 647 | void luaC_separateudata (lua_State *L, int all) { |
645 | global_State *g = G(L); | 648 | global_State *g = G(L); |
646 | GCObject **p = &g->mainthread->next; | 649 | GCObject **p = &g->udgc; |
647 | GCObject *curr; | 650 | GCObject *curr; |
648 | GCObject **lastnext = &g->tobefnz; | 651 | GCObject **lastnext = &g->tobefnz; |
649 | /* find last 'next' field in 'tobefnz' list (to insert elements in its end) */ | 652 | /* find last 'next' field in 'tobefnz' list (to insert elements in its end) */ |
@@ -655,7 +658,7 @@ void luaC_separateudata (lua_State *L, int all) { | |||
655 | p = &gch(curr)->next; /* don't bother with it */ | 658 | p = &gch(curr)->next; /* don't bother with it */ |
656 | else { | 659 | else { |
657 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 660 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
658 | *p = gch(curr)->next; /* remove 'curr' from 'rootgc' list */ | 661 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ |
659 | /* link 'curr' at the end of 'tobefnz' list */ | 662 | /* link 'curr' at the end of 'tobefnz' list */ |
660 | gch(curr)->next = *lastnext; | 663 | gch(curr)->next = *lastnext; |
661 | *lastnext = curr; | 664 | *lastnext = curr; |
@@ -671,13 +674,12 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
671 | isfinalized(&u->uv) || /* ... or is finalized... */ | 674 | isfinalized(&u->uv) || /* ... or is finalized... */ |
672 | gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalization? */ | 675 | gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalization? */ |
673 | return; /* nothing to be done */ | 676 | return; /* nothing to be done */ |
674 | else { /* move 'u' to 2nd part of root list */ | 677 | else { /* move 'u' to 'udgc' list */ |
675 | GCObject **p; | 678 | GCObject **p; |
676 | for (p = &g->rootgc; *p != obj2gco(u); p = &gch(*p)->next) | 679 | for (p = &g->allgc; *p != obj2gco(u); p = &gch(*p)->next) ; |
677 | lua_assert(*p != obj2gco(g->mainthread)); /* 'u' must be in this list */ | ||
678 | *p = u->uv.next; /* remove 'u' from root list */ | 680 | *p = u->uv.next; /* remove 'u' from root list */ |
679 | u->uv.next = g->mainthread->next; /* re-link it in list */ | 681 | u->uv.next = g->udgc; /* re-link it in list */ |
680 | g->mainthread->next = obj2gco(u); | 682 | g->udgc = obj2gco(u); |
681 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ | 683 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ |
682 | } | 684 | } |
683 | } | 685 | } |
@@ -697,8 +699,9 @@ void luaC_freeallobjects (lua_State *L) { | |||
697 | while (g->tobefnz) GCTM(L, 0); /* Call all pending finalizers */ | 699 | while (g->tobefnz) GCTM(L, 0); /* Call all pending finalizers */ |
698 | /* following "white" makes all objects look dead */ | 700 | /* following "white" makes all objects look dead */ |
699 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); | 701 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); |
700 | sweepwholelist(L, &g->rootgc); | 702 | sweepwholelist(L, &g->udgc); |
701 | lua_assert(g->rootgc == obj2gco(g->mainthread) && | 703 | sweepwholelist(L, &g->allgc); |
704 | lua_assert(g->allgc == obj2gco(g->mainthread) && | ||
702 | g->mainthread->next == NULL); | 705 | g->mainthread->next == NULL); |
703 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | 706 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ |
704 | sweepwholelist(L, &g->strt.hash[i]); | 707 | sweepwholelist(L, &g->strt.hash[i]); |
@@ -761,19 +764,21 @@ static l_mem singlestep (lua_State *L) { | |||
761 | return GCSWEEPCOST; | 764 | return GCSWEEPCOST; |
762 | } | 765 | } |
763 | else { /* nothing more to sweep */ | 766 | else { /* nothing more to sweep */ |
764 | g->sweepgc = &g->rootgc; | 767 | g->sweepgc = &g->udgc; /* sweep all userdata */ |
765 | g->gcstate = GCSsweep; /* sweep all other objects */ | 768 | g->gcstate = GCSsweepudata; |
769 | checkSizes(L); | ||
766 | return 0; | 770 | return 0; |
767 | } | 771 | } |
768 | } | 772 | } |
773 | case GCSsweepudata: | ||
769 | case GCSsweep: { | 774 | case GCSsweep: { |
770 | if (*g->sweepgc) { | 775 | if (*g->sweepgc) { |
771 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 776 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
772 | return GCSWEEPMAX*GCSWEEPCOST; | 777 | return GCSWEEPMAX*GCSWEEPCOST; |
773 | } | 778 | } |
774 | else { /* nothing more to sweep */ | 779 | else { /* go to next phase */ |
775 | checkSizes(L); | 780 | g->sweepgc = &g->allgc; /* useless (but harmless) in GCSsweep case */ |
776 | g->gcstate = GCSfinalize; /* end sweep phase */ | 781 | g->gcstate = (g->gcstate == GCSsweep) ? GCSfinalize : GCSsweep; |
777 | return 0; | 782 | return 0; |
778 | } | 783 | } |
779 | } | 784 | } |
@@ -856,8 +861,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
856 | g->gcstate = GCSsweepstring; | 861 | g->gcstate = GCSsweepstring; |
857 | } | 862 | } |
858 | /* finish any pending sweep phase */ | 863 | /* finish any pending sweep phase */ |
859 | luaC_runtilstate(L, ~bit2mask(GCSsweepstring, GCSsweep)); | 864 | luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); |
860 | lua_assert(g->gcstate == GCSpause || g->gcstate == GCSfinalize); | ||
861 | g->gcstate = GCSpause; /* start a new collection */ | 865 | g->gcstate = GCSpause; /* start a new collection */ |
862 | /* run collector up to finalizers */ | 866 | /* run collector up to finalizers */ |
863 | luaC_runtilstate(L, bitmask(GCSfinalize)); | 867 | luaC_runtilstate(L, bitmask(GCSfinalize)); |