aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c56
1 files changed, 30 insertions, 26 deletions
diff --git a/lgc.c b/lgc.c
index 0ae5aafd..f19ca70b 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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,
139void luaC_linkupval (lua_State *L, UpVal *uv) { 141void 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) {
549static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { 551static 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) {
597static Udata *udata2finalize (global_State *g) { 600static 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' */
644void luaC_separateudata (lua_State *L, int all) { 647void 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));