aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-03-23 17:16:06 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-03-23 17:16:06 -0300
commit5cb128ea540b33dbc6be659d5dfc3c64c57d78d9 (patch)
treeb2a739045db5249776dfaf2abaf6bab7ca54eea1
parent74123e96869bdb55d3967036e2bc0c6f9e0550d6 (diff)
downloadlua-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.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/lgc.c b/lgc.c
index c245e3a9..0ae5aafd 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
581static void checkSizes (lua_State *L) { 583static 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