diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-05-22 14:32:25 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-05-22 14:32:25 -0300 |
commit | b36b4b521f53e5ff2e18fff3c194d28f9a840868 (patch) | |
tree | f8a96d20fcb95efcd07fcb7218d088406c3020dc | |
parent | 398811a3131cb025ca61d1a0839e3f99ba632ae9 (diff) | |
download | lua-b36b4b521f53e5ff2e18fff3c194d28f9a840868.tar.gz lua-b36b4b521f53e5ff2e18fff3c194d28f9a840868.tar.bz2 lua-b36b4b521f53e5ff2e18fff3c194d28f9a840868.zip |
try to avoid sweeping new objects created with new white (and
therefore not collectable in the current cycle)
-rw-r--r-- | lgc.c | 62 | ||||
-rw-r--r-- | lstate.c | 3 | ||||
-rw-r--r-- | lstate.h | 5 |
3 files changed, 43 insertions, 27 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.123 2012/05/20 20:36:44 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.124 2012/05/21 13:18:10 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 | */ |
@@ -49,6 +49,7 @@ | |||
49 | #define workrate(x,mul) \ | 49 | #define workrate(x,mul) \ |
50 | ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80) | 50 | ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80) |
51 | 51 | ||
52 | |||
52 | /* | 53 | /* |
53 | ** standard negative debt for GC; a reasonable "time" to wait before | 54 | ** standard negative debt for GC; a reasonable "time" to wait before |
54 | ** starting a new cycle | 55 | ** starting a new cycle |
@@ -738,19 +739,16 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
738 | freeobj(L, curr); /* erase 'curr' */ | 739 | freeobj(L, curr); /* erase 'curr' */ |
739 | } | 740 | } |
740 | else { | 741 | else { |
742 | if (testbits(marked, tostop)) | ||
743 | return NULL; /* stop sweeping this list */ | ||
741 | if (gch(curr)->tt == LUA_TTHREAD) | 744 | if (gch(curr)->tt == LUA_TTHREAD) |
742 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 745 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
743 | if (testbits(marked, tostop)) { | ||
744 | static GCObject *nullp = NULL; | ||
745 | p = &nullp; /* stop sweeping this list */ | ||
746 | break; | ||
747 | } | ||
748 | /* update marks */ | 746 | /* update marks */ |
749 | gch(curr)->marked = cast_byte((marked & toclear) | toset); | 747 | gch(curr)->marked = cast_byte((marked & toclear) | toset); |
750 | p = &gch(curr)->next; /* go to next element */ | 748 | p = &gch(curr)->next; /* go to next element */ |
751 | } | 749 | } |
752 | } | 750 | } |
753 | return p; | 751 | return (*p == NULL) ? NULL : p; |
754 | } | 752 | } |
755 | 753 | ||
756 | /* }====================================================== */ | 754 | /* }====================================================== */ |
@@ -865,7 +863,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
865 | GCObject **p; | 863 | GCObject **p; |
866 | GCheader *ho = gch(o); | 864 | GCheader *ho = gch(o); |
867 | /* avoid removing current sweep object */ | 865 | /* avoid removing current sweep object */ |
868 | if (g->gcstate == GCSsweep && g->sweepgc == &ho->next) { | 866 | if (g->sweepgc == &ho->next) { |
869 | /* step to next object in the list */ | 867 | /* step to next object in the list */ |
870 | g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next; | 868 | g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next; |
871 | } | 869 | } |
@@ -892,6 +890,24 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
892 | #define sweepphases \ | 890 | #define sweepphases \ |
893 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) | 891 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) |
894 | 892 | ||
893 | |||
894 | /* | ||
895 | ** enter first sweep phase (strings) and prepare pointers for other | ||
896 | ** sweep phases. The calls to 'sweeplist' attempt to make pointers | ||
897 | ** point to an object inside the list (instead of to the header), so | ||
898 | ** that the real sweep do not need to skip objects created between "now" | ||
899 | ** and the start of the real sweep. | ||
900 | */ | ||
901 | static void entersweep (lua_State *L) { | ||
902 | global_State *g = G(L); | ||
903 | g->gcstate = GCSsweepstring; | ||
904 | lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); | ||
905 | g->sweepstrgc = 0; /* prepare to sweep strings, ... */ | ||
906 | g->sweepfin = sweeplist(L, &g->finobj, 1); /* finalizable objects, ... */ | ||
907 | g->sweepgc = sweeplist(L, &g->allgc, 1); /* and regular objects */ | ||
908 | } | ||
909 | |||
910 | |||
895 | /* | 911 | /* |
896 | ** change GC mode | 912 | ** change GC mode |
897 | */ | 913 | */ |
@@ -907,9 +923,8 @@ void luaC_changemode (lua_State *L, int mode) { | |||
907 | else { /* change to incremental mode */ | 923 | else { /* change to incremental mode */ |
908 | /* sweep all objects to turn them back to white | 924 | /* sweep all objects to turn them back to white |
909 | (as white has not changed, nothing extra will be collected) */ | 925 | (as white has not changed, nothing extra will be collected) */ |
910 | g->sweepstrgc = 0; | ||
911 | g->gcstate = GCSsweepstring; | ||
912 | g->gckind = KGC_NORMAL; | 926 | g->gckind = KGC_NORMAL; |
927 | entersweep(L); | ||
913 | luaC_runtilstate(L, ~sweepphases); | 928 | luaC_runtilstate(L, ~sweepphases); |
914 | } | 929 | } |
915 | } | 930 | } |
@@ -972,9 +987,8 @@ static void atomic (lua_State *L) { | |||
972 | /* clear values from resurrected weak tables */ | 987 | /* clear values from resurrected weak tables */ |
973 | clearvalues(g, g->weak, origweak); | 988 | clearvalues(g, g->weak, origweak); |
974 | clearvalues(g, g->allweak, origall); | 989 | clearvalues(g, g->allweak, origall); |
975 | g->sweepstrgc = 0; /* prepare to sweep strings */ | ||
976 | g->gcstate = GCSsweepstring; | ||
977 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 990 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
991 | entersweep(L); /* prepare to sweep strings */ | ||
978 | /*lua_checkmemory(L);*/ | 992 | /*lua_checkmemory(L);*/ |
979 | } | 993 | } |
980 | 994 | ||
@@ -1010,25 +1024,22 @@ static lu_mem singlestep (lua_State *L) { | |||
1010 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) | 1024 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) |
1011 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); | 1025 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); |
1012 | g->sweepstrgc += i; | 1026 | g->sweepstrgc += i; |
1013 | if (g->sweepstrgc >= g->strt.size) { /* no more strings to sweep? */ | 1027 | if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ |
1014 | g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */ | ||
1015 | g->gcstate = GCSsweepudata; | 1028 | g->gcstate = GCSsweepudata; |
1016 | } | ||
1017 | return i * GCSWEEPCOST; | 1029 | return i * GCSWEEPCOST; |
1018 | } | 1030 | } |
1019 | case GCSsweepudata: { | 1031 | case GCSsweepudata: { |
1020 | if (*g->sweepgc) { | 1032 | if (g->sweepfin) { |
1021 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 1033 | g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); |
1022 | return GCSWEEPMAX*GCSWEEPCOST; | 1034 | return GCSWEEPMAX*GCSWEEPCOST; |
1023 | } | 1035 | } |
1024 | else { | 1036 | else { |
1025 | g->sweepgc = &g->allgc; /* go to next phase */ | ||
1026 | g->gcstate = GCSsweep; | 1037 | g->gcstate = GCSsweep; |
1027 | return 0; | 1038 | return 0; |
1028 | } | 1039 | } |
1029 | } | 1040 | } |
1030 | case GCSsweep: { | 1041 | case GCSsweep: { |
1031 | if (*g->sweepgc) { | 1042 | if (g->sweepgc) { |
1032 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 1043 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
1033 | return GCSWEEPMAX*GCSWEEPCOST; | 1044 | return GCSWEEPMAX*GCSWEEPCOST; |
1034 | } | 1045 | } |
@@ -1121,16 +1132,19 @@ void luaC_step (lua_State *L) { | |||
1121 | void luaC_fullgc (lua_State *L, int isemergency) { | 1132 | void luaC_fullgc (lua_State *L, int isemergency) { |
1122 | global_State *g = G(L); | 1133 | global_State *g = G(L); |
1123 | int origkind = g->gckind; | 1134 | int origkind = g->gckind; |
1135 | int someblack = keepinvariant(g); | ||
1124 | lua_assert(origkind != KGC_EMERGENCY); | 1136 | lua_assert(origkind != KGC_EMERGENCY); |
1125 | if (!isemergency) /* do not run finalizers during emergency GC */ | 1137 | if (isemergency) /* do not run finalizers during emergency GC */ |
1138 | g->gckind = KGC_EMERGENCY; | ||
1139 | else { | ||
1140 | g->gckind = KGC_NORMAL; | ||
1126 | callallpendingfinalizers(L, 1); | 1141 | callallpendingfinalizers(L, 1); |
1127 | if (keepinvariant(g)) { /* marking phase? */ | 1142 | } |
1143 | if (someblack) { /* may there be some black objects? */ | ||
1128 | /* must sweep all objects to turn them back to white | 1144 | /* must sweep all objects to turn them back to white |
1129 | (as white has not changed, nothing will be collected) */ | 1145 | (as white has not changed, nothing will be collected) */ |
1130 | g->sweepstrgc = 0; | 1146 | entersweep(L); |
1131 | g->gcstate = GCSsweepstring; | ||
1132 | } | 1147 | } |
1133 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; | ||
1134 | /* finish any pending sweep phase to start a new cycle */ | 1148 | /* finish any pending sweep phase to start a new cycle */ |
1135 | luaC_runtilstate(L, bitmask(GCSpause)); | 1149 | luaC_runtilstate(L, bitmask(GCSpause)); |
1136 | /* run entire collector */ | 1150 | /* run entire collector */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.93 2012/02/01 21:57:15 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.94 2012/05/11 14:06:07 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -292,6 +292,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
292 | g->allgc = NULL; | 292 | g->allgc = NULL; |
293 | g->finobj = NULL; | 293 | g->finobj = NULL; |
294 | g->tobefnz = NULL; | 294 | g->tobefnz = NULL; |
295 | g->sweepgc = g->sweepfin = NULL; | ||
295 | g->gray = g->grayagain = NULL; | 296 | g->gray = g->grayagain = NULL; |
296 | g->weak = g->ephemeron = g->allweak = NULL; | 297 | g->weak = g->ephemeron = g->allweak = NULL; |
297 | g->totalbytes = sizeof(LG); | 298 | g->totalbytes = sizeof(LG); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.77 2012/02/01 21:57:15 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.78 2012/05/20 20:36:44 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -126,7 +126,8 @@ typedef struct global_State { | |||
126 | int sweepstrgc; /* position of sweep in `strt' */ | 126 | int sweepstrgc; /* position of sweep in `strt' */ |
127 | GCObject *allgc; /* list of all collectable objects */ | 127 | GCObject *allgc; /* list of all collectable objects */ |
128 | GCObject *finobj; /* list of collectable objects with finalizers */ | 128 | GCObject *finobj; /* list of collectable objects with finalizers */ |
129 | GCObject **sweepgc; /* current position of sweep */ | 129 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ |
130 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | ||
130 | GCObject *gray; /* list of gray objects */ | 131 | GCObject *gray; /* list of gray objects */ |
131 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 132 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
132 | GCObject *weak; /* list of tables with weak values */ | 133 | GCObject *weak; /* list of tables with weak values */ |