diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 53 |
1 files changed, 28 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.83 2010/04/30 18:37:14 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.84 2010/05/03 11:55:40 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 | */ |
@@ -27,7 +27,7 @@ | |||
27 | #define GCSTEPSIZE 1024 | 27 | #define GCSTEPSIZE 1024 |
28 | #define GCSWEEPMAX 40 | 28 | #define GCSWEEPMAX 40 |
29 | #define GCSWEEPCOST 1 | 29 | #define GCSWEEPCOST 1 |
30 | #define GCFINALIZECOST 50 | 30 | #define GCFINALIZENUM 4 |
31 | #define GCROOTCOST 10 | 31 | #define GCROOTCOST 10 |
32 | #define GCATOMICCOST 1000 | 32 | #define GCATOMICCOST 1000 |
33 | 33 | ||
@@ -115,8 +115,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
115 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 115 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
116 | global_State *g = G(L); | 116 | global_State *g = G(L); |
117 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 117 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
118 | lua_assert(g->gckind == KGC_GEN || | 118 | lua_assert(g->gckind == KGC_GEN || g->gcstate != GCSpause); |
119 | (g->gcstate != GCSfinalize && g->gcstate != GCSpause)); | ||
120 | lua_assert(gch(o)->tt != LUA_TTABLE); | 119 | lua_assert(gch(o)->tt != LUA_TTABLE); |
121 | if (keepinvariant(g)) /* must keep invariant? */ | 120 | if (keepinvariant(g)) /* must keep invariant? */ |
122 | reallymarkobject(g, v); /* restore invariant */ | 121 | reallymarkobject(g, v); /* restore invariant */ |
@@ -643,6 +642,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
643 | static void checkSizes (lua_State *L) { | 642 | static void checkSizes (lua_State *L) { |
644 | global_State *g = G(L); | 643 | global_State *g = G(L); |
645 | int hs = g->strt.size / 2; /* half the size of the string table */ | 644 | int hs = g->strt.size / 2; /* half the size of the string table */ |
645 | if (g->gcstate == KGC_EMERGENCY) return; | ||
646 | if (g->strt.nuse < cast(lu_int32, hs)) { /* using less than half its size? */ | 646 | if (g->strt.nuse < cast(lu_int32, hs)) { /* using less than half its size? */ |
647 | luaS_resize(L, hs); /* halve its size */ | 647 | luaS_resize(L, hs); /* halve its size */ |
648 | } | 648 | } |
@@ -755,10 +755,18 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
755 | ** ======================================================= | 755 | ** ======================================================= |
756 | */ | 756 | */ |
757 | 757 | ||
758 | /* | ||
759 | ** call all pending finalizers */ | ||
760 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | ||
761 | global_State *g = G(L); | ||
762 | while (g->tobefnz) GCTM(L, propagateerrors); | ||
763 | } | ||
764 | |||
765 | |||
758 | void luaC_freeallobjects (lua_State *L) { | 766 | void luaC_freeallobjects (lua_State *L) { |
759 | global_State *g = G(L); | 767 | global_State *g = G(L); |
760 | int i; | 768 | int i; |
761 | while (g->tobefnz) GCTM(L, 0); /* Call all pending finalizers */ | 769 | callallpendingfinalizers(L, 0); |
762 | /* following "white" makes all objects look dead */ | 770 | /* following "white" makes all objects look dead */ |
763 | g->currentwhite = WHITEBITS; | 771 | g->currentwhite = WHITEBITS; |
764 | sweepwholelist(L, &g->udgc); | 772 | sweepwholelist(L, &g->udgc); |
@@ -795,7 +803,7 @@ static void atomic (lua_State *L) { | |||
795 | cleartable(g->weak); | 803 | cleartable(g->weak); |
796 | cleartable(g->ephemeron); | 804 | cleartable(g->ephemeron); |
797 | cleartable(g->allweak); | 805 | cleartable(g->allweak); |
798 | lua_checkmemory(L); | 806 | /*lua_checkmemory(L);*/ |
799 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 807 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
800 | } | 808 | } |
801 | 809 | ||
@@ -850,19 +858,9 @@ static l_mem singlestep (lua_State *L) { | |||
850 | else { | 858 | else { |
851 | /* sweep main thread */ | 859 | /* sweep main thread */ |
852 | sweeplist(L, cast(GCObject **, &g->mainthread), 1); | 860 | sweeplist(L, cast(GCObject **, &g->mainthread), 1); |
853 | g->gcstate = GCSfinalize; /* go to next phase */ | ||
854 | return GCSWEEPCOST; | ||
855 | } | ||
856 | } | ||
857 | case GCSfinalize: { | ||
858 | if (g->tobefnz) { | ||
859 | GCTM(L, 1); | ||
860 | return GCFINALIZECOST; | ||
861 | } | ||
862 | else { | ||
863 | checkSizes(L); | 861 | checkSizes(L); |
864 | g->gcstate = GCSpause; /* end collection */ | 862 | g->gcstate = GCSpause; /* finish collection */ |
865 | return 0; | 863 | return GCSWEEPCOST; |
866 | } | 864 | } |
867 | } | 865 | } |
868 | default: lua_assert(0); return 0; | 866 | default: lua_assert(0); return 0; |
@@ -913,8 +911,11 @@ static void step (lua_State *L) { | |||
913 | 911 | ||
914 | 912 | ||
915 | void luaC_step (lua_State *L) { | 913 | void luaC_step (lua_State *L) { |
914 | int i; | ||
916 | if (G(L)->gckind == KGC_GEN) generationalcollection(L); | 915 | if (G(L)->gckind == KGC_GEN) generationalcollection(L); |
917 | else step(L); | 916 | else step(L); |
917 | for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++) | ||
918 | GCTM(L, 1); /* Call a few pending finalizers */ | ||
918 | } | 919 | } |
919 | 920 | ||
920 | 921 | ||
@@ -926,6 +927,8 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
926 | global_State *g = G(L); | 927 | global_State *g = G(L); |
927 | int origkind = g->gckind; | 928 | int origkind = g->gckind; |
928 | lua_assert(origkind == KGC_NORMAL || origkind == KGC_GEN); | 929 | lua_assert(origkind == KGC_NORMAL || origkind == KGC_GEN); |
930 | if (!isemergency) /* do not run finalizers during emergency GC */ | ||
931 | callallpendingfinalizers(L, 1); | ||
929 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; | 932 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; |
930 | if (g->gcstate == GCSpropagate) { /* marking phase? */ | 933 | if (g->gcstate == GCSpropagate) { /* marking phase? */ |
931 | /* must sweep all objects to turn them back to white | 934 | /* must sweep all objects to turn them back to white |
@@ -934,16 +937,16 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
934 | g->gcstate = GCSsweepstring; | 937 | g->gcstate = GCSsweepstring; |
935 | } | 938 | } |
936 | /* finish any pending sweep phase */ | 939 | /* finish any pending sweep phase */ |
937 | luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); | 940 | luaC_runtilstate(L, bitmask(GCSpause)); |
938 | g->gcstate = GCSpause; /* start a new collection */ | 941 | /* run entire collector */ |
939 | /* run collector up to finalizers */ | 942 | luaC_runtilstate(L, ~bitmask(GCSpause)); |
940 | luaC_runtilstate(L, bitmask(GCSfinalize)); | 943 | luaC_runtilstate(L, bitmask(GCSpause)); |
941 | g->gckind = origkind; | 944 | g->gckind = origkind; |
942 | if (!isemergency) /* do not run finalizers during emergency GC */ | 945 | if (!isemergency) /* do not run finalizers during emergency GC */ |
943 | luaC_runtilstate(L, bitmask(GCSpause)); | 946 | callallpendingfinalizers(L, 1); |
944 | if (origkind == KGC_GEN) { /* generational mode? */ | 947 | if (origkind == KGC_GEN) { /* generational mode? */ |
945 | g->gcstate = GCSpause; /* collector must be always in... */ | 948 | /* collector must be always in propagate phase */ |
946 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ | 949 | luaC_runtilstate(L, bitmask(GCSpropagate)); |
947 | } | 950 | } |
948 | g->GCdebt = stddebt(g); | 951 | g->GCdebt = stddebt(g); |
949 | } | 952 | } |