diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-03-23 17:16:06 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-03-23 17:16:06 -0300 |
commit | 5cb128ea540b33dbc6be659d5dfc3c64c57d78d9 (patch) | |
tree | b2a739045db5249776dfaf2abaf6bab7ca54eea1 | |
parent | 74123e96869bdb55d3967036e2bc0c6f9e0550d6 (diff) | |
download | lua-5cb128ea540b33dbc6be659d5dfc3c64c57d78d9.tar.gz lua-5cb128ea540b33dbc6be659d5dfc3c64c57d78d9.tar.bz2 lua-5cb128ea540b33dbc6be659d5dfc3c64c57d78d9.zip |
BUG: emergency collector might resize 'strt' (string table) when
creating a new string
+ atomic and markroot steps has some cost
+ full collection must leave collector in proper state when mode
is generational
-rw-r--r-- | lgc.c | 38 |
1 files changed, 27 insertions, 11 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.67 2009/12/22 15:32:50 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.68 2010/03/22 18:28:03 roberto Exp $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -27,6 +27,8 @@ | |||
27 | #define GCSWEEPMAX 40 | 27 | #define GCSWEEPMAX 40 |
28 | #define GCSWEEPCOST 10 | 28 | #define GCSWEEPCOST 10 |
29 | #define GCFINALIZECOST 100 | 29 | #define GCFINALIZECOST 100 |
30 | #define GCROOTCOST 10 | ||
31 | #define GCATOMICCOST 1000 | ||
30 | 32 | ||
31 | 33 | ||
32 | #define maskcolors (~(bitmask(BLACKBIT)|WHITEBITS)) | 34 | #define maskcolors (~(bitmask(BLACKBIT)|WHITEBITS)) |
@@ -580,6 +582,8 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
580 | 582 | ||
581 | static void checkSizes (lua_State *L) { | 583 | static void checkSizes (lua_State *L) { |
582 | global_State *g = G(L); | 584 | global_State *g = G(L); |
585 | if (g->gckind == KGC_EMERGENCY) | ||
586 | return; /* do not move buffers during emergency collection */ | ||
583 | if (g->strt.nuse < cast(lu_int32, g->strt.size)) { | 587 | if (g->strt.nuse < cast(lu_int32, g->strt.size)) { |
584 | /* string-table size could be the smaller power of 2 larger than 'nuse' */ | 588 | /* string-table size could be the smaller power of 2 larger than 'nuse' */ |
585 | int size = 1 << luaO_ceillog2(g->strt.nuse); | 589 | int size = 1 << luaO_ceillog2(g->strt.nuse); |
@@ -739,7 +743,7 @@ static l_mem singlestep (lua_State *L) { | |||
739 | case GCSpause: { | 743 | case GCSpause: { |
740 | markroot(L); /* start a new collection */ | 744 | markroot(L); /* start a new collection */ |
741 | g->gcstate = GCSpropagate; | 745 | g->gcstate = GCSpropagate; |
742 | return 0; | 746 | return GCROOTCOST; |
743 | } | 747 | } |
744 | case GCSpropagate: { | 748 | case GCSpropagate: { |
745 | if (g->gray) | 749 | if (g->gray) |
@@ -748,22 +752,30 @@ static l_mem singlestep (lua_State *L) { | |||
748 | g->gcstate = GCSatomic; /* finish mark phase */ | 752 | g->gcstate = GCSatomic; /* finish mark phase */ |
749 | atomic(L); | 753 | atomic(L); |
750 | g->gcstate = GCSsweepstring; | 754 | g->gcstate = GCSsweepstring; |
751 | return 0; | 755 | return GCATOMICCOST; |
752 | } | 756 | } |
753 | } | 757 | } |
754 | case GCSsweepstring: { | 758 | case GCSsweepstring: { |
755 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); | 759 | if (g->sweepstrgc < g->strt.size) { |
756 | if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ | 760 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); |
761 | return GCSWEEPCOST; | ||
762 | } | ||
763 | else { /* nothing more to sweep */ | ||
757 | g->sweepgc = &g->rootgc; | 764 | g->sweepgc = &g->rootgc; |
758 | g->gcstate = GCSsweep; /* sweep all other objects */ | 765 | g->gcstate = GCSsweep; /* sweep all other objects */ |
766 | return 0; | ||
759 | } | 767 | } |
760 | return GCSWEEPCOST; | ||
761 | } | 768 | } |
762 | case GCSsweep: { | 769 | case GCSsweep: { |
763 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 770 | if (*g->sweepgc) { |
764 | if (*g->sweepgc == NULL) /* nothing more to sweep? */ | 771 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
772 | return GCSWEEPMAX*GCSWEEPCOST; | ||
773 | } | ||
774 | else { /* nothing more to sweep */ | ||
775 | checkSizes(L); | ||
765 | g->gcstate = GCSfinalize; /* end sweep phase */ | 776 | g->gcstate = GCSfinalize; /* end sweep phase */ |
766 | return GCSWEEPMAX*GCSWEEPCOST; | 777 | return 0; |
778 | } | ||
767 | } | 779 | } |
768 | case GCSfinalize: { | 780 | case GCSfinalize: { |
769 | if (g->tobefnz) { | 781 | if (g->tobefnz) { |
@@ -771,7 +783,6 @@ static l_mem singlestep (lua_State *L) { | |||
771 | return GCFINALIZECOST; | 783 | return GCFINALIZECOST; |
772 | } | 784 | } |
773 | else { | 785 | else { |
774 | checkSizes(L); | ||
775 | g->gcstate = GCSpause; /* end collection */ | 786 | g->gcstate = GCSpause; /* end collection */ |
776 | return 0; | 787 | return 0; |
777 | } | 788 | } |
@@ -840,18 +851,23 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
840 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; | 851 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; |
841 | if (g->gcstate == GCSpropagate) { /* marking phase? */ | 852 | if (g->gcstate == GCSpropagate) { /* marking phase? */ |
842 | /* must sweep all objects to turn them back to white | 853 | /* must sweep all objects to turn them back to white |
843 | (as white does not change, nothing will be collected) */ | 854 | (as white has not changed, nothing will be collected) */ |
844 | g->sweepstrgc = 0; | 855 | g->sweepstrgc = 0; |
845 | g->gcstate = GCSsweepstring; | 856 | g->gcstate = GCSsweepstring; |
846 | } | 857 | } |
847 | /* finish any pending sweep phase */ | 858 | /* finish any pending sweep phase */ |
848 | luaC_runtilstate(L, ~bit2mask(GCSsweepstring, GCSsweep)); | 859 | luaC_runtilstate(L, ~bit2mask(GCSsweepstring, GCSsweep)); |
860 | lua_assert(g->gcstate == GCSpause || g->gcstate == GCSfinalize); | ||
849 | g->gcstate = GCSpause; /* start a new collection */ | 861 | g->gcstate = GCSpause; /* start a new collection */ |
850 | /* run collector up to finalizers */ | 862 | /* run collector up to finalizers */ |
851 | luaC_runtilstate(L, bitmask(GCSfinalize)); | 863 | luaC_runtilstate(L, bitmask(GCSfinalize)); |
852 | g->gckind = origkind; | 864 | g->gckind = origkind; |
853 | if (!isemergency) /* do not run finalizers during emergency GC */ | 865 | if (!isemergency) /* do not run finalizers during emergency GC */ |
854 | luaC_runtilstate(L, bitmask(GCSpause)); | 866 | luaC_runtilstate(L, bitmask(GCSpause)); |
867 | if (origkind == KGC_GEN) { /* generational mode? */ | ||
868 | g->gckind = GCSpause; /* collector must be always in... */ | ||
869 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ | ||
870 | } | ||
855 | g->GCthreshold = (g->totalbytes/100) * g->gcpause; | 871 | g->GCthreshold = (g->totalbytes/100) * g->gcpause; |
856 | } | 872 | } |
857 | 873 | ||