diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-05-07 15:19:36 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-05-07 15:19:36 -0300 |
commit | 0fac33da9eba15464c186c8645d81920c245e944 (patch) | |
tree | 14e15105ff33d342a22f4c3eb723a58f5461bd98 /lgc.c | |
parent | 8e1bdda66a7eba39a39d27dffe6412e7d37ad09c (diff) | |
download | lua-0fac33da9eba15464c186c8645d81920c245e944.tar.gz lua-0fac33da9eba15464c186c8645d81920c245e944.tar.bz2 lua-0fac33da9eba15464c186c8645d81920c245e944.zip |
bug: incremental sweep was not cleaning old bits (as it stopped in the
first old object) + bug: moving udata to 'udgc' list might put old
object in front a new one + some new macros + generational mode may
be in 'pause' state (it just skips 'markroot')
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 56 |
1 files changed, 28 insertions, 28 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.89 2010/05/05 18:58:36 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.90 2010/05/06 18:18:07 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 | */ |
@@ -130,7 +130,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
131 | global_State *g = G(L); | 131 | global_State *g = G(L); |
132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
133 | lua_assert(g->gckind == KGC_GEN || g->gcstate != GCSpause); | 133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); |
134 | lua_assert(gch(o)->tt != LUA_TTABLE); | 134 | lua_assert(gch(o)->tt != LUA_TTABLE); |
135 | if (keepinvariant(g)) /* must keep invariant? */ | 135 | if (keepinvariant(g)) /* must keep invariant? */ |
136 | reallymarkobject(g, v); /* restore invariant */ | 136 | reallymarkobject(g, v); /* restore invariant */ |
@@ -149,15 +149,9 @@ void luaC_barrierback (lua_State *L, Table *t) { | |||
149 | global_State *g = G(L); | 149 | global_State *g = G(L); |
150 | GCObject *o = obj2gco(t); | 150 | GCObject *o = obj2gco(t); |
151 | lua_assert(isblack(o) && !isdead(g, o)); | 151 | lua_assert(isblack(o) && !isdead(g, o)); |
152 | if (keepinvariant(g)) { | 152 | black2gray(o); /* make table gray (again) */ |
153 | black2gray(o); /* make table gray (again) */ | 153 | t->gclist = g->grayagain; |
154 | t->gclist = g->grayagain; | 154 | g->grayagain = o; |
155 | g->grayagain = o; | ||
156 | } | ||
157 | else { /* sweep phase */ | ||
158 | lua_assert(issweepphase(g)); | ||
159 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | ||
160 | } | ||
161 | } | 155 | } |
162 | 156 | ||
163 | 157 | ||
@@ -612,31 +606,31 @@ static void sweepthread (lua_State *L, lua_State *L1) { | |||
612 | */ | 606 | */ |
613 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 607 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
614 | global_State *g = G(L); | 608 | global_State *g = G(L); |
615 | int deadmask = otherwhite(g); | 609 | int ow = otherwhite(g); |
616 | int toclear, toset; /* bits to clear and to set in all live objects */ | 610 | int toclear, toset; /* bits to clear and to set in all live objects */ |
617 | if (g->gckind == KGC_GEN) { /* generational mode? */ | 611 | int tostop; /* stop sweep when this is true */ |
612 | if (isgenerational(g)) { /* generational mode? */ | ||
618 | toclear = ~0; /* clear nothing */ | 613 | toclear = ~0; /* clear nothing */ |
619 | toset = OLDBIT; /* set the old bit of all surviving objects */ | 614 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ |
615 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ | ||
620 | } | 616 | } |
621 | else { /* normal mode */ | 617 | else { /* normal mode */ |
622 | toclear = maskcolors; /* clear all color bits */ | 618 | toclear = maskcolors; /* clear all color bits + old bit */ |
623 | toset = luaC_white(g); /* make object white */ | 619 | toset = luaC_white(g); /* make object white */ |
620 | tostop = 0; /* do not stop */ | ||
624 | } | 621 | } |
625 | while (*p != NULL && count-- > 0) { | 622 | while (*p != NULL && count-- > 0) { |
626 | GCObject *curr = *p; | 623 | GCObject *curr = *p; |
627 | int marked = gch(curr)->marked; | 624 | int marked = gch(curr)->marked; |
628 | if (!((marked ^ WHITEBITS) & deadmask)) { /* is 'curr' dead? */ | 625 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ |
629 | lua_assert(isdead(g, curr) || deadmask == 0); | ||
630 | *p = gch(curr)->next; /* remove 'curr' from list */ | 626 | *p = gch(curr)->next; /* remove 'curr' from list */ |
631 | freeobj(L, curr); /* erase 'curr' */ | 627 | freeobj(L, curr); /* erase 'curr' */ |
632 | } | 628 | } |
633 | else { | 629 | else { |
634 | lua_assert(!isdead(g, curr) || testbit(marked, FIXEDBIT)); | ||
635 | if (gch(curr)->tt == LUA_TTHREAD) | 630 | if (gch(curr)->tt == LUA_TTHREAD) |
636 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 631 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
637 | if (testbit(marked, OLDBIT)) { /* old generation? */ | 632 | if (testbits(marked, tostop)) { |
638 | static GCObject *nullp = NULL; | 633 | static GCObject *nullp = NULL; |
639 | lua_assert(g->gckind == KGC_GEN); /* can happen only in gen. mode */ | ||
640 | return &nullp; /* stop sweeping this list */ | 634 | return &nullp; /* stop sweeping this list */ |
641 | } | 635 | } |
642 | /* update marks */ | 636 | /* update marks */ |
@@ -671,7 +665,7 @@ static Udata *udata2finalize (global_State *g) { | |||
671 | GCObject *o = g->tobefnz; /* get first element */ | 665 | GCObject *o = g->tobefnz; /* get first element */ |
672 | Udata *u = rawgco2u(o); | 666 | Udata *u = rawgco2u(o); |
673 | lua_assert(isfinalized(&u->uv)); | 667 | lua_assert(isfinalized(&u->uv)); |
674 | lua_assert(!testbit(u->uv.marked, OLDBIT)); | 668 | lua_assert(!isold(o)); |
675 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ | 669 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ |
676 | u->uv.next = g->allgc; /* return it to 'allgc' list */ | 670 | u->uv.next = g->allgc; /* return it to 'allgc' list */ |
677 | g->allgc = o; | 671 | g->allgc = o; |
@@ -725,7 +719,7 @@ void luaC_separateudata (lua_State *L, int all) { | |||
725 | GCObject **p = &g->udgc; | 719 | GCObject **p = &g->udgc; |
726 | GCObject *curr; | 720 | GCObject *curr; |
727 | GCObject **lastnext = &g->tobefnz; | 721 | GCObject **lastnext = &g->tobefnz; |
728 | /* find last 'next' field in 'tobefnz' list (to insert elements in its end) */ | 722 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ |
729 | while (*lastnext != NULL) | 723 | while (*lastnext != NULL) |
730 | lastnext = &gch(*lastnext)->next; | 724 | lastnext = &gch(*lastnext)->next; |
731 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ | 725 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
@@ -735,6 +729,7 @@ void luaC_separateudata (lua_State *L, int all) { | |||
735 | p = &gch(curr)->next; /* don't bother with it */ | 729 | p = &gch(curr)->next; /* don't bother with it */ |
736 | else { | 730 | else { |
737 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 731 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
732 | resetbit(gch(curr)->marked, OLDBIT); /* may be old when 'all' */ | ||
738 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ | 733 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ |
739 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ | 734 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
740 | *lastnext = curr; | 735 | *lastnext = curr; |
@@ -761,6 +756,7 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
761 | u->uv.next = g->udgc; /* link it in list 'udgc' */ | 756 | u->uv.next = g->udgc; /* link it in list 'udgc' */ |
762 | g->udgc = obj2gco(u); | 757 | g->udgc = obj2gco(u); |
763 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ | 758 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ |
759 | resetbit(u->uv.marked, OLDBIT); | ||
764 | } | 760 | } |
765 | } | 761 | } |
766 | 762 | ||
@@ -814,6 +810,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
814 | callallpendingfinalizers(L, 0); | 810 | callallpendingfinalizers(L, 0); |
815 | /* following "white" makes all objects look dead */ | 811 | /* following "white" makes all objects look dead */ |
816 | g->currentwhite = WHITEBITS; | 812 | g->currentwhite = WHITEBITS; |
813 | g->gckind = KGC_NORMAL; | ||
817 | sweepwholelist(L, &g->udgc); | 814 | sweepwholelist(L, &g->udgc); |
818 | lua_assert(g->udgc == NULL); | 815 | lua_assert(g->udgc == NULL); |
819 | sweepwholelist(L, &g->allgc); | 816 | sweepwholelist(L, &g->allgc); |
@@ -851,6 +848,7 @@ static void atomic (lua_State *L) { | |||
851 | g->sweepstrgc = 0; /* prepare to sweep strings */ | 848 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
852 | g->gcstate = GCSsweepstring; | 849 | g->gcstate = GCSsweepstring; |
853 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 850 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
851 | /*lua_checkmemory(L);*/ | ||
854 | } | 852 | } |
855 | 853 | ||
856 | 854 | ||
@@ -859,7 +857,11 @@ static l_mem singlestep (lua_State *L) { | |||
859 | /*lua_checkmemory(L);*/ | 857 | /*lua_checkmemory(L);*/ |
860 | switch (g->gcstate) { | 858 | switch (g->gcstate) { |
861 | case GCSpause: { | 859 | case GCSpause: { |
862 | markroot(L); /* start a new collection */ | 860 | if (!isgenerational(g)) |
861 | markroot(L); /* start a new collection */ | ||
862 | else /* root still marked */ | ||
863 | lua_assert(!iswhite(obj2gco(g->mainthread)) | ||
864 | && !iswhite(gcvalue(&g->l_registry))); | ||
863 | g->gcstate = GCSpropagate; | 865 | g->gcstate = GCSpropagate; |
864 | return GCROOTCOST; | 866 | return GCROOTCOST; |
865 | } | 867 | } |
@@ -925,14 +927,12 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
925 | 927 | ||
926 | static void generationalcollection (lua_State *L) { | 928 | static void generationalcollection (lua_State *L) { |
927 | global_State *g = G(L); | 929 | global_State *g = G(L); |
928 | lua_assert(g->gcstate == GCSpropagate); | ||
929 | if (g->lastmajormem == 0) { /* signal for another major collection? */ | 930 | if (g->lastmajormem == 0) { /* signal for another major collection? */ |
930 | luaC_fullgc(L, 0); /* perform a full regular collection */ | 931 | luaC_fullgc(L, 0); /* perform a full regular collection */ |
931 | g->lastmajormem = g->totalbytes; /* update control */ | 932 | g->lastmajormem = g->totalbytes; /* update control */ |
932 | } | 933 | } |
933 | else { | 934 | else { |
934 | luaC_runtilstate(L, bitmask(GCSpause)); | 935 | luaC_runtilstate(L, bitmask(GCSpause)); /* run collection */ |
935 | g->gcstate = GCSpropagate; /* do not run 'markroot' */ | ||
936 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) | 936 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) |
937 | g->lastmajormem = 0; /* signal for a major collection */ | 937 | g->lastmajormem = 0; /* signal for a major collection */ |
938 | } | 938 | } |
@@ -955,7 +955,7 @@ static void step (lua_State *L) { | |||
955 | 955 | ||
956 | void luaC_step (lua_State *L) { | 956 | void luaC_step (lua_State *L) { |
957 | int i; | 957 | int i; |
958 | if (G(L)->gckind == KGC_GEN) generationalcollection(L); | 958 | if (isgenerational(G(L))) generationalcollection(L); |
959 | else step(L); | 959 | else step(L); |
960 | for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++) | 960 | for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++) |
961 | GCTM(L, 1); /* Call a few pending finalizers */ | 961 | GCTM(L, 1); /* Call a few pending finalizers */ |
@@ -984,11 +984,11 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
984 | /* run entire collector */ | 984 | /* run entire collector */ |
985 | luaC_runtilstate(L, ~bitmask(GCSpause)); | 985 | luaC_runtilstate(L, ~bitmask(GCSpause)); |
986 | luaC_runtilstate(L, bitmask(GCSpause)); | 986 | luaC_runtilstate(L, bitmask(GCSpause)); |
987 | g->gckind = origkind; | ||
988 | if (origkind == KGC_GEN) { /* generational mode? */ | 987 | if (origkind == KGC_GEN) { /* generational mode? */ |
989 | /* generational mode must always start in propagate phase */ | 988 | /* generational mode must always start in propagate phase */ |
990 | luaC_runtilstate(L, bitmask(GCSpropagate)); | 989 | luaC_runtilstate(L, bitmask(GCSpropagate)); |
991 | } | 990 | } |
991 | g->gckind = origkind; | ||
992 | g->GCdebt = stddebt(g); | 992 | g->GCdebt = stddebt(g); |
993 | if (!isemergency) /* do not run finalizers during emergency GC */ | 993 | if (!isemergency) /* do not run finalizers during emergency GC */ |
994 | callallpendingfinalizers(L, 1); | 994 | callallpendingfinalizers(L, 1); |