diff options
-rw-r--r-- | lgc.c | 55 |
1 files changed, 42 insertions, 13 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.87 2010/05/04 18:09:06 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 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 | */ |
@@ -170,6 +170,7 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | |||
170 | lua_assert(!isblack(o)); /* open upvalues are never black */ | 170 | lua_assert(!isblack(o)); /* open upvalues are never black */ |
171 | if (isgray(o)) { | 171 | if (isgray(o)) { |
172 | if (keepinvariant(g)) { | 172 | if (keepinvariant(g)) { |
173 | resetbit(o->gch.marked, OLDBIT); | ||
173 | gray2black(o); /* it is being visited now */ | 174 | gray2black(o); /* it is being visited now */ |
174 | markvalue(g, uv->v); | 175 | markvalue(g, uv->v); |
175 | } | 176 | } |
@@ -300,7 +301,8 @@ static void remarkupvals (global_State *g) { | |||
300 | 301 | ||
301 | 302 | ||
302 | /* | 303 | /* |
303 | ** mark root set | 304 | ** mark root set and reset all gray lists, to start a new |
305 | ** incremental (or full) collection | ||
304 | */ | 306 | */ |
305 | static void markroot (lua_State *L) { | 307 | static void markroot (lua_State *L) { |
306 | global_State *g = G(L); | 308 | global_State *g = G(L); |
@@ -655,12 +657,12 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
655 | 657 | ||
656 | static void checkSizes (lua_State *L) { | 658 | static void checkSizes (lua_State *L) { |
657 | global_State *g = G(L); | 659 | global_State *g = G(L); |
658 | int hs = g->strt.size / 2; /* half the size of the string table */ | 660 | if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ |
659 | if (g->gcstate == KGC_EMERGENCY) return; | 661 | int hs = g->strt.size / 2; /* half the size of the string table */ |
660 | if (g->strt.nuse < cast(lu_int32, hs)) { /* using less than half its size? */ | 662 | if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ |
661 | luaS_resize(L, hs); /* halve its size */ | 663 | luaS_resize(L, hs); /* halve its size */ |
664 | luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ | ||
662 | } | 665 | } |
663 | luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ | ||
664 | } | 666 | } |
665 | 667 | ||
666 | 668 | ||
@@ -668,6 +670,7 @@ static Udata *udata2finalize (global_State *g) { | |||
668 | GCObject *o = g->tobefnz; /* get first element */ | 670 | GCObject *o = g->tobefnz; /* get first element */ |
669 | Udata *u = rawgco2u(o); | 671 | Udata *u = rawgco2u(o); |
670 | lua_assert(isfinalized(&u->uv)); | 672 | lua_assert(isfinalized(&u->uv)); |
673 | lua_assert(!testbit(u->uv.marked, OLDBIT)); | ||
671 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ | 674 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ |
672 | u->uv.next = g->allgc; /* return it to 'allgc' list */ | 675 | u->uv.next = g->allgc; /* return it to 'allgc' list */ |
673 | g->allgc = o; | 676 | g->allgc = o; |
@@ -769,6 +772,33 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
769 | ** ======================================================= | 772 | ** ======================================================= |
770 | */ | 773 | */ |
771 | 774 | ||
775 | |||
776 | #define sweepphases \ | ||
777 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) | ||
778 | |||
779 | /* | ||
780 | ** change GC mode | ||
781 | */ | ||
782 | void luaC_changemode (lua_State *L, int mode) { | ||
783 | global_State *g = G(L); | ||
784 | if (mode == g->gckind) return; /* nothing to change */ | ||
785 | if (mode == KGC_GEN) { /* change to generational mode */ | ||
786 | /* make sure gray lists are consistent */ | ||
787 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
788 | g->lastmajormem = g->totalbytes; | ||
789 | g->gckind = KGC_GEN; | ||
790 | } | ||
791 | else { /* change to incremental mode */ | ||
792 | /* sweep all objects to turn them back to white | ||
793 | (as white has not changed, nothing extra will be collected) */ | ||
794 | g->sweepstrgc = 0; | ||
795 | g->gcstate = GCSsweepstring; | ||
796 | g->gckind = KGC_NORMAL; | ||
797 | luaC_runtilstate(L, ~sweepphases); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | |||
772 | /* | 802 | /* |
773 | ** call all pending finalizers */ | 803 | ** call all pending finalizers */ |
774 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | 804 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { |
@@ -817,7 +847,8 @@ static void atomic (lua_State *L) { | |||
817 | cleartable(g->weak); | 847 | cleartable(g->weak); |
818 | cleartable(g->ephemeron); | 848 | cleartable(g->ephemeron); |
819 | cleartable(g->allweak); | 849 | cleartable(g->allweak); |
820 | lua_checkmemory(L); | 850 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
851 | g->gcstate = GCSsweepstring; | ||
821 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 852 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
822 | } | 853 | } |
823 | 854 | ||
@@ -837,8 +868,6 @@ static l_mem singlestep (lua_State *L) { | |||
837 | else { /* no more `gray' objects */ | 868 | else { /* no more `gray' objects */ |
838 | g->gcstate = GCSatomic; /* finish mark phase */ | 869 | g->gcstate = GCSatomic; /* finish mark phase */ |
839 | atomic(L); | 870 | atomic(L); |
840 | g->sweepstrgc = 0; /* prepare to sweep strings */ | ||
841 | g->gcstate = GCSsweepstring; | ||
842 | return GCATOMICCOST; | 871 | return GCATOMICCOST; |
843 | } | 872 | } |
844 | } | 873 | } |
@@ -933,7 +962,7 @@ void luaC_step (lua_State *L) { | |||
933 | 962 | ||
934 | 963 | ||
935 | /* | 964 | /* |
936 | ** performs a full GC cycle; if "isememrgency", does not call | 965 | ** performs a full GC cycle; if "isemergency", does not call |
937 | ** finalizers (which could change stack positions) | 966 | ** finalizers (which could change stack positions) |
938 | */ | 967 | */ |
939 | void luaC_fullgc (lua_State *L, int isemergency) { | 968 | void luaC_fullgc (lua_State *L, int isemergency) { |
@@ -942,14 +971,14 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
942 | lua_assert(origkind != KGC_EMERGENCY); | 971 | lua_assert(origkind != KGC_EMERGENCY); |
943 | if (!isemergency) /* do not run finalizers during emergency GC */ | 972 | if (!isemergency) /* do not run finalizers during emergency GC */ |
944 | callallpendingfinalizers(L, 1); | 973 | callallpendingfinalizers(L, 1); |
945 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; | 974 | if (keepinvariant(g)) { /* marking phase? */ |
946 | if (g->gcstate == GCSpropagate) { /* marking phase? */ | ||
947 | /* must sweep all objects to turn them back to white | 975 | /* must sweep all objects to turn them back to white |
948 | (as white has not changed, nothing will be collected) */ | 976 | (as white has not changed, nothing will be collected) */ |
949 | g->sweepstrgc = 0; | 977 | g->sweepstrgc = 0; |
950 | g->gcstate = GCSsweepstring; | 978 | g->gcstate = GCSsweepstring; |
951 | } | 979 | } |
952 | /* finish any pending sweep phase */ | 980 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; |
981 | /* finish any pending sweep phase to start a new cycle */ | ||
953 | luaC_runtilstate(L, bitmask(GCSpause)); | 982 | luaC_runtilstate(L, bitmask(GCSpause)); |
954 | /* run entire collector */ | 983 | /* run entire collector */ |
955 | luaC_runtilstate(L, ~bitmask(GCSpause)); | 984 | luaC_runtilstate(L, ~bitmask(GCSpause)); |