diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-05 13:58:28 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-05 13:58:28 -0300 |
commit | 677d90165ffef728231340c6328e9661824dbc34 (patch) | |
tree | 3338e6f1b0c2f82db84def5751ea418a58fbc31a /lgc.c | |
parent | 4244da96bfcf205624487b99b69e9d8dd1857293 (diff) | |
download | lua-677d90165ffef728231340c6328e9661824dbc34.tar.gz lua-677d90165ffef728231340c6328e9661824dbc34.tar.bz2 lua-677d90165ffef728231340c6328e9661824dbc34.zip |
no more generational collection !!!
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 115 |
1 files changed, 19 insertions, 96 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.140.1.2 2013/04/26 18:22:05 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 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 | */ |
@@ -52,10 +52,10 @@ | |||
52 | 52 | ||
53 | 53 | ||
54 | /* | 54 | /* |
55 | ** 'makewhite' erases all color bits plus the old bit and then | 55 | ** 'makewhite' erases all color bits then sets only the current white |
56 | ** sets only the current white bit | 56 | ** bit |
57 | */ | 57 | */ |
58 | #define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) | 58 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) |
59 | #define makewhite(g,x) \ | 59 | #define makewhite(g,x) \ |
60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) | 60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) |
61 | 61 | ||
@@ -137,7 +137,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | |||
137 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 137 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
138 | lua_assert(g->gcstate != GCSpause); | 138 | lua_assert(g->gcstate != GCSpause); |
139 | lua_assert(gch(o)->tt != LUA_TTABLE); | 139 | lua_assert(gch(o)->tt != LUA_TTABLE); |
140 | if (keepinvariantout(g)) /* must keep invariant? */ | 140 | if (keepinvariant(g)) /* must keep invariant? */ |
141 | reallymarkobject(g, v); /* restore invariant */ | 141 | reallymarkobject(g, v); /* restore invariant */ |
142 | else { /* sweep phase */ | 142 | else { /* sweep phase */ |
143 | lua_assert(issweepphase(g)); | 143 | lua_assert(issweepphase(g)); |
@@ -184,7 +184,7 @@ LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { | |||
184 | 184 | ||
185 | 185 | ||
186 | /* | 186 | /* |
187 | ** check color (and invariants) for an upvalue that was closed, | 187 | ** check color (and invariants) for an upvalue that is being closed, |
188 | ** i.e., moved into the 'allgc' list | 188 | ** i.e., moved into the 'allgc' list |
189 | */ | 189 | */ |
190 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | 190 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { |
@@ -192,7 +192,6 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | |||
192 | lua_assert(!isblack(o)); /* open upvalues are never black */ | 192 | lua_assert(!isblack(o)); /* open upvalues are never black */ |
193 | if (isgray(o)) { | 193 | if (isgray(o)) { |
194 | if (keepinvariant(g)) { | 194 | if (keepinvariant(g)) { |
195 | resetoldbit(o); /* see MOVE OLD rule */ | ||
196 | gray2black(o); /* it is being visited now */ | 195 | gray2black(o); /* it is being visited now */ |
197 | markvalue(g, uv->v); | 196 | markvalue(g, uv->v); |
198 | } | 197 | } |
@@ -331,8 +330,7 @@ static void remarkupvals (global_State *g) { | |||
331 | 330 | ||
332 | 331 | ||
333 | /* | 332 | /* |
334 | ** mark root set and reset all gray lists, to start a new | 333 | ** mark root set and reset all gray lists, to start a new collection |
335 | ** incremental (or full) collection | ||
336 | */ | 334 | */ |
337 | static void restartcollection (global_State *g) { | 335 | static void restartcollection (global_State *g) { |
338 | g->gray = g->grayagain = NULL; | 336 | g->gray = g->grayagain = NULL; |
@@ -708,29 +706,14 @@ static void sweepthread (lua_State *L, lua_State *L1) { | |||
708 | /* | 706 | /* |
709 | ** sweep at most 'count' elements from a list of GCObjects erasing dead | 707 | ** sweep at most 'count' elements from a list of GCObjects erasing dead |
710 | ** objects, where a dead (not alive) object is one marked with the "old" | 708 | ** objects, where a dead (not alive) object is one marked with the "old" |
711 | ** (non current) white and not fixed. | 709 | ** (non current) white and not fixed; change all non-dead objects back |
712 | ** In non-generational mode, change all non-dead objects back to white, | 710 | ** to white, preparing for next collection cycle. |
713 | ** preparing for next collection cycle. | ||
714 | ** In generational mode, keep black objects black, and also mark them as | ||
715 | ** old; stop when hitting an old object, as all objects after that | ||
716 | ** one will be old too. | ||
717 | ** When object is a thread, sweep its list of open upvalues too. | 711 | ** When object is a thread, sweep its list of open upvalues too. |
718 | */ | 712 | */ |
719 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 713 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
720 | global_State *g = G(L); | 714 | global_State *g = G(L); |
721 | int ow = otherwhite(g); | 715 | int ow = otherwhite(g); |
722 | int toclear, toset; /* bits to clear and to set in all live objects */ | 716 | int white = luaC_white(g); /* current white */ |
723 | int tostop; /* stop sweep when this is true */ | ||
724 | if (isgenerational(g)) { /* generational mode? */ | ||
725 | toclear = ~0; /* clear nothing */ | ||
726 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ | ||
727 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ | ||
728 | } | ||
729 | else { /* normal mode */ | ||
730 | toclear = maskcolors; /* clear all color bits + old bit */ | ||
731 | toset = luaC_white(g); /* make object white */ | ||
732 | tostop = 0; /* do not stop */ | ||
733 | } | ||
734 | while (*p != NULL && count-- > 0) { | 717 | while (*p != NULL && count-- > 0) { |
735 | GCObject *curr = *p; | 718 | GCObject *curr = *p; |
736 | int marked = gch(curr)->marked; | 719 | int marked = gch(curr)->marked; |
@@ -739,12 +722,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
739 | freeobj(L, curr); /* erase 'curr' */ | 722 | freeobj(L, curr); /* erase 'curr' */ |
740 | } | 723 | } |
741 | else { | 724 | else { |
742 | if (testbits(marked, tostop)) | ||
743 | return NULL; /* stop sweeping this list */ | ||
744 | if (gch(curr)->tt == LUA_TTHREAD) | 725 | if (gch(curr)->tt == LUA_TTHREAD) |
745 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 726 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
746 | /* update marks */ | 727 | /* update marks */ |
747 | gch(curr)->marked = cast_byte((marked & toclear) | toset); | 728 | gch(curr)->marked = cast_byte((marked & maskcolors) | white); |
748 | p = &gch(curr)->next; /* go to next element */ | 729 | p = &gch(curr)->next; /* go to next element */ |
749 | } | 730 | } |
750 | } | 731 | } |
@@ -793,8 +774,7 @@ static GCObject *udata2finalize (global_State *g) { | |||
793 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ | 774 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
794 | g->allgc = o; | 775 | g->allgc = o; |
795 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ | 776 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ |
796 | lua_assert(!isold(o)); /* see MOVE OLD rule */ | 777 | if (!keepinvariant(g)) /* not keeping invariant? */ |
797 | if (!keepinvariantout(g)) /* not keeping invariant? */ | ||
798 | makewhite(g, o); /* "sweep" object */ | 778 | makewhite(g, o); /* "sweep" object */ |
799 | return o; | 779 | return o; |
800 | } | 780 | } |
@@ -889,10 +869,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
889 | ho->next = g->finobj; /* link it in list 'finobj' */ | 869 | ho->next = g->finobj; /* link it in list 'finobj' */ |
890 | g->finobj = o; | 870 | g->finobj = o; |
891 | l_setbit(ho->marked, SEPARATED); /* mark it as such */ | 871 | l_setbit(ho->marked, SEPARATED); /* mark it as such */ |
892 | if (!keepinvariantout(g)) /* not keeping invariant? */ | 872 | if (!keepinvariant(g)) /* not keeping invariant? */ |
893 | makewhite(g, o); /* "sweep" object */ | 873 | makewhite(g, o); /* "sweep" object */ |
894 | else | ||
895 | resetoldbit(o); /* see MOVE OLD rule */ | ||
896 | } | 874 | } |
897 | } | 875 | } |
898 | 876 | ||
@@ -947,36 +925,12 @@ static int entersweep (lua_State *L) { | |||
947 | 925 | ||
948 | 926 | ||
949 | /* | 927 | /* |
950 | ** change GC mode | ||
951 | */ | ||
952 | void luaC_changemode (lua_State *L, int mode) { | ||
953 | global_State *g = G(L); | ||
954 | if (mode == g->gckind) return; /* nothing to change */ | ||
955 | if (mode == KGC_GEN) { /* change to generational mode */ | ||
956 | /* make sure gray lists are consistent */ | ||
957 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
958 | g->GCestimate = gettotalbytes(g); | ||
959 | g->gckind = KGC_GEN; | ||
960 | } | ||
961 | else { /* change to incremental mode */ | ||
962 | /* sweep all objects to turn them back to white | ||
963 | (as white has not changed, nothing extra will be collected) */ | ||
964 | g->gckind = KGC_NORMAL; | ||
965 | entersweep(L); | ||
966 | luaC_runtilstate(L, ~sweepphases); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | |||
971 | /* | ||
972 | ** call all pending finalizers | 928 | ** call all pending finalizers |
973 | */ | 929 | */ |
974 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | 930 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { |
975 | global_State *g = G(L); | 931 | global_State *g = G(L); |
976 | while (g->tobefnz) { | 932 | while (g->tobefnz) |
977 | resetoldbit(g->tobefnz); | ||
978 | GCTM(L, propagateerrors); | 933 | GCTM(L, propagateerrors); |
979 | } | ||
980 | } | 934 | } |
981 | 935 | ||
982 | 936 | ||
@@ -1014,7 +968,7 @@ static l_mem atomic (lua_State *L) { | |||
1014 | work -= g->GCmemtrav; /* restart counting */ | 968 | work -= g->GCmemtrav; /* restart counting */ |
1015 | convergeephemerons(g); | 969 | convergeephemerons(g); |
1016 | /* at this point, all strongly accessible objects are marked. */ | 970 | /* at this point, all strongly accessible objects are marked. */ |
1017 | /* clear values from weak tables, before checking finalizers */ | 971 | /* Clear values from weak tables, before checking finalizers */ |
1018 | clearvalues(g, g->weak, NULL); | 972 | clearvalues(g, g->weak, NULL); |
1019 | clearvalues(g, g->allweak, NULL); | 973 | clearvalues(g, g->allweak, NULL); |
1020 | origweak = g->weak; origall = g->allweak; | 974 | origweak = g->weak; origall = g->allweak; |
@@ -1043,7 +997,6 @@ static lu_mem singlestep (lua_State *L) { | |||
1043 | case GCSpause: { | 997 | case GCSpause: { |
1044 | /* start to count memory traversed */ | 998 | /* start to count memory traversed */ |
1045 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); | 999 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); |
1046 | lua_assert(!isgenerational(g)); | ||
1047 | restartcollection(g); | 1000 | restartcollection(g); |
1048 | g->gcstate = GCSpropagate; | 1001 | g->gcstate = GCSpropagate; |
1049 | return g->GCmemtrav; | 1002 | return g->GCmemtrav; |
@@ -1114,28 +1067,6 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
1114 | } | 1067 | } |
1115 | 1068 | ||
1116 | 1069 | ||
1117 | static void generationalcollection (lua_State *L) { | ||
1118 | global_State *g = G(L); | ||
1119 | lua_assert(g->gcstate == GCSpropagate); | ||
1120 | if (g->GCestimate == 0) { /* signal for another major collection? */ | ||
1121 | luaC_fullgc(L, 0); /* perform a full regular collection */ | ||
1122 | g->GCestimate = gettotalbytes(g); /* update control */ | ||
1123 | } | ||
1124 | else { | ||
1125 | lu_mem estimate = g->GCestimate; | ||
1126 | luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ | ||
1127 | g->gcstate = GCSpropagate; /* skip restart */ | ||
1128 | if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) | ||
1129 | g->GCestimate = 0; /* signal for a major collection */ | ||
1130 | else | ||
1131 | g->GCestimate = estimate; /* keep estimate from last major coll. */ | ||
1132 | |||
1133 | } | ||
1134 | setpause(g, gettotalbytes(g)); | ||
1135 | lua_assert(g->gcstate == GCSpropagate); | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | static void incstep (lua_State *L) { | 1070 | static void incstep (lua_State *L) { |
1140 | global_State *g = G(L); | 1071 | global_State *g = G(L); |
1141 | l_mem debt = g->GCdebt; | 1072 | l_mem debt = g->GCdebt; |
@@ -1163,8 +1094,7 @@ static void incstep (lua_State *L) { | |||
1163 | void luaC_forcestep (lua_State *L) { | 1094 | void luaC_forcestep (lua_State *L) { |
1164 | global_State *g = G(L); | 1095 | global_State *g = G(L); |
1165 | int i; | 1096 | int i; |
1166 | if (isgenerational(g)) generationalcollection(L); | 1097 | incstep(L); |
1167 | else incstep(L); | ||
1168 | /* run a few finalizers (or all of them at the end of a collect cycle) */ | 1098 | /* run a few finalizers (or all of them at the end of a collect cycle) */ |
1169 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) | 1099 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) |
1170 | GCTM(L, 1); /* call one finalizer */ | 1100 | GCTM(L, 1); /* call one finalizer */ |
@@ -1188,14 +1118,11 @@ void luaC_step (lua_State *L) { | |||
1188 | */ | 1118 | */ |
1189 | void luaC_fullgc (lua_State *L, int isemergency) { | 1119 | void luaC_fullgc (lua_State *L, int isemergency) { |
1190 | global_State *g = G(L); | 1120 | global_State *g = G(L); |
1191 | int origkind = g->gckind; | 1121 | lua_assert(g->gckind == KGC_NORMAL); |
1192 | lua_assert(origkind != KGC_EMERGENCY); | ||
1193 | if (isemergency) /* do not run finalizers during emergency GC */ | 1122 | if (isemergency) /* do not run finalizers during emergency GC */ |
1194 | g->gckind = KGC_EMERGENCY; | 1123 | g->gckind = KGC_EMERGENCY; |
1195 | else { | 1124 | else |
1196 | g->gckind = KGC_NORMAL; | ||
1197 | callallpendingfinalizers(L, 1); | 1125 | callallpendingfinalizers(L, 1); |
1198 | } | ||
1199 | if (keepinvariant(g)) { /* may there be some black objects? */ | 1126 | if (keepinvariant(g)) { /* may there be some black objects? */ |
1200 | /* must sweep all objects to turn them back to white | 1127 | /* must sweep all objects to turn them back to white |
1201 | (as white has not changed, nothing will be collected) */ | 1128 | (as white has not changed, nothing will be collected) */ |
@@ -1205,11 +1132,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
1205 | luaC_runtilstate(L, bitmask(GCSpause)); | 1132 | luaC_runtilstate(L, bitmask(GCSpause)); |
1206 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ | 1133 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ |
1207 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ | 1134 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ |
1208 | if (origkind == KGC_GEN) { /* generational mode? */ | 1135 | g->gckind = KGC_NORMAL; |
1209 | /* generational mode must be kept in propagate phase */ | ||
1210 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
1211 | } | ||
1212 | g->gckind = origkind; | ||
1213 | setpause(g, gettotalbytes(g)); | 1136 | setpause(g, gettotalbytes(g)); |
1214 | if (!isemergency) /* do not run finalizers during emergency GC */ | 1137 | if (!isemergency) /* do not run finalizers during emergency GC */ |
1215 | callallpendingfinalizers(L, 1); | 1138 | callallpendingfinalizers(L, 1); |