diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-02-23 18:07:34 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-02-23 18:07:34 -0300 |
commit | f5f3df3bd17fb3489bbd26ab39fe1580a8dbf9c9 (patch) | |
tree | 84f67f71a728bc988661349c361f2a968b1d4910 | |
parent | e6c1e6005a9346d378e004a6d6e7fd98c7ee191b (diff) | |
download | lua-f5f3df3bd17fb3489bbd26ab39fe1580a8dbf9c9.tar.gz lua-f5f3df3bd17fb3489bbd26ab39fe1580a8dbf9c9.tar.bz2 lua-f5f3df3bd17fb3489bbd26ab39fe1580a8dbf9c9.zip |
generational collection: new attempt (still incomplete)
-rw-r--r-- | lapi.c | 10 | ||||
-rw-r--r-- | lbaselib.c | 6 | ||||
-rw-r--r-- | lgc.c | 183 | ||||
-rw-r--r-- | lgc.h | 9 | ||||
-rw-r--r-- | lstate.c | 3 | ||||
-rw-r--r-- | lstate.h | 8 | ||||
-rw-r--r-- | ltests.c | 12 | ||||
-rw-r--r-- | lua.h | 4 |
8 files changed, 195 insertions, 40 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.258 2016/01/05 16:07:21 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1097,6 +1097,14 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1097 | res = g->gcrunning; | 1097 | res = g->gcrunning; |
1098 | break; | 1098 | break; |
1099 | } | 1099 | } |
1100 | case LUA_GCGEN: { | ||
1101 | luaC_changemode(L, KGC_GEN); | ||
1102 | break; | ||
1103 | } | ||
1104 | case LUA_GCINC: { | ||
1105 | luaC_changemode(L, KGC_NORMAL); | ||
1106 | break; | ||
1107 | } | ||
1100 | default: res = -1; /* invalid option */ | 1108 | default: res = -1; /* invalid option */ |
1101 | } | 1109 | } |
1102 | lua_unlock(L); | 1110 | lua_unlock(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.314 2016/09/05 19:06:34 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -173,10 +173,10 @@ static int luaB_rawset (lua_State *L) { | |||
173 | static int luaB_collectgarbage (lua_State *L) { | 173 | static int luaB_collectgarbage (lua_State *L) { |
174 | static const char *const opts[] = {"stop", "restart", "collect", | 174 | static const char *const opts[] = {"stop", "restart", "collect", |
175 | "count", "step", "setpause", "setstepmul", | 175 | "count", "step", "setpause", "setstepmul", |
176 | "isrunning", NULL}; | 176 | "isrunning", "generational", "incremental", NULL}; |
177 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 177 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
178 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, | 178 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
179 | LUA_GCISRUNNING}; | 179 | LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; |
180 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | 180 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
181 | int ex = (int)luaL_optinteger(L, 2, 0); | 181 | int ex = (int)luaL_optinteger(L, 2, 0); |
182 | int res = lua_gc(L, o, ex); | 182 | int res = lua_gc(L, o, ex); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.214 2016/11/07 12:38:35 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.215 2016/12/22 13:08:50 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 | */ |
@@ -59,11 +59,10 @@ | |||
59 | #define PAUSEADJ 100 | 59 | #define PAUSEADJ 100 |
60 | 60 | ||
61 | 61 | ||
62 | /* | 62 | /* mask to erase all color bits */ |
63 | ** 'makewhite' erases all color bits then sets only the current white | ||
64 | ** bit | ||
65 | */ | ||
66 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) | 63 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) |
64 | |||
65 | /* macro to erase all color bits then sets only the current white bit */ | ||
67 | #define makewhite(g,x) \ | 66 | #define makewhite(g,x) \ |
68 | (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) | 67 | (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) |
69 | 68 | ||
@@ -92,6 +91,7 @@ | |||
92 | #define markobjectN(g,t) { if (t) markobject(g,t); } | 91 | #define markobjectN(g,t) { if (t) markobject(g,t); } |
93 | 92 | ||
94 | static void reallymarkobject (global_State *g, GCObject *o); | 93 | static void reallymarkobject (global_State *g, GCObject *o); |
94 | static l_mem atomic (lua_State *L); | ||
95 | 95 | ||
96 | 96 | ||
97 | /* | 97 | /* |
@@ -155,8 +155,11 @@ static int iscleared (global_State *g, const TValue *o) { | |||
155 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | 155 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
156 | global_State *g = G(L); | 156 | global_State *g = G(L); |
157 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 157 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
158 | if (keepinvariant(g)) /* must keep invariant? */ | 158 | if (keepinvariant(g)) { /* must keep invariant? */ |
159 | reallymarkobject(g, v); /* restore invariant */ | 159 | reallymarkobject(g, v); /* restore invariant */ |
160 | if (isold(o)) | ||
161 | l_setbit((v)->marked, OLDBIT); | ||
162 | } | ||
160 | else { /* sweep phase */ | 163 | else { /* sweep phase */ |
161 | lua_assert(issweepphase(g)); | 164 | lua_assert(issweepphase(g)); |
162 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | 165 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ |
@@ -186,8 +189,10 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
186 | global_State *g = G(L); | 189 | global_State *g = G(L); |
187 | GCObject *o = gcvalue(uv->v); | 190 | GCObject *o = gcvalue(uv->v); |
188 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ | 191 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ |
189 | if (keepinvariant(g)) | 192 | if (keepinvariant(g)) { |
190 | markobject(g, o); | 193 | markobject(g, o); |
194 | l_setbit((o)->marked, OLDBIT); | ||
195 | } | ||
191 | } | 196 | } |
192 | 197 | ||
193 | 198 | ||
@@ -922,6 +927,121 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
922 | /* }====================================================== */ | 927 | /* }====================================================== */ |
923 | 928 | ||
924 | 929 | ||
930 | /* | ||
931 | ** {====================================================== | ||
932 | ** Generational Collector | ||
933 | ** ======================================================= | ||
934 | */ | ||
935 | |||
936 | |||
937 | #if 0 | ||
938 | static int count (GCObject *p, GCObject *limit) { | ||
939 | int res = 0; | ||
940 | for (; p != NULL && p != limit; p = p->next) | ||
941 | res++; | ||
942 | return res; | ||
943 | } | ||
944 | #endif | ||
945 | |||
946 | |||
947 | static GCObject **sweepgen (lua_State *L, GCObject **p, GCObject *limit, | ||
948 | int zeromask, int onemask) { | ||
949 | global_State *g = G(L); | ||
950 | int ow = otherwhite(g); | ||
951 | GCObject *curr; | ||
952 | while ((curr = *p) != limit) { | ||
953 | int marked = curr->marked; | ||
954 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ | ||
955 | lua_assert(!isold(curr)); | ||
956 | *p = curr->next; /* remove 'curr' from list */ | ||
957 | freeobj(L, curr); /* erase 'curr' */ | ||
958 | } | ||
959 | else { /* correct mark */ | ||
960 | if (!isold(curr)) /* don't change old objects */ | ||
961 | curr->marked = cast_byte((marked & zeromask) | onemask); | ||
962 | p = &curr->next; /* go to next element */ | ||
963 | } | ||
964 | } | ||
965 | return p; | ||
966 | } | ||
967 | |||
968 | |||
969 | static void startgencycle (lua_State *L, global_State *g) { | ||
970 | propagateall(g); | ||
971 | atomic(L); | ||
972 | } | ||
973 | |||
974 | |||
975 | static void finishgencycle (lua_State *L, global_State *g, int mask) { | ||
976 | sweepgen(L, &g->finobj, NULL, ~0, mask); | ||
977 | sweepgen(L, &g->tobefnz, NULL, ~0, mask); | ||
978 | checkSizes(L, g); | ||
979 | g->gcstate = GCSpropagate; /* skip restart */ | ||
980 | callallpendingfinalizers(L); | ||
981 | } | ||
982 | |||
983 | |||
984 | static void youngcollection (lua_State *L, global_State *g) { | ||
985 | GCObject **psurvival; | ||
986 | lua_assert(g->gcstate == GCSpropagate); | ||
987 | startgencycle(L, g); | ||
988 | /* sweep nursery */ | ||
989 | psurvival = sweepgen(L, &g->allgc, g->survival, maskcolors, luaC_white(g)); | ||
990 | lua_assert(*psurvival == g->survival); | ||
991 | /* sweep 'survival' list, making elements old */ | ||
992 | sweepgen(L, psurvival, g->old, ~0, bitmask(OLDBIT)); | ||
993 | /* incorporate 'survival' list into old list */ | ||
994 | g->old = *psurvival; | ||
995 | /* surviving young objects go to 'survival' list */ | ||
996 | g->survival = g->allgc; | ||
997 | finishgencycle(L, g, 0); | ||
998 | lua_checkmemory(L); | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | static void entergen (lua_State *L, global_State *g) { | ||
1003 | lua_checkmemory(L); | ||
1004 | lua_assert(g->old == NULL && g->survival == NULL); | ||
1005 | luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ | ||
1006 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ | ||
1007 | startgencycle(L, g); | ||
1008 | /* sweep all ellements making them old */ | ||
1009 | sweepgen(L, &g->allgc, g->survival, ~0, bitmask(OLDBIT)); | ||
1010 | /* everything alive now is old; 'survival' is empty */ | ||
1011 | g->old = g->survival = g->allgc; | ||
1012 | finishgencycle(L, g, bitmask(OLDBIT)); | ||
1013 | lua_checkmemory(L); | ||
1014 | } | ||
1015 | |||
1016 | |||
1017 | void luaC_changemode (lua_State *L, int newmode) { | ||
1018 | global_State *g = G(L); | ||
1019 | if (newmode != g->gckind) { /* otherwise, nothing to be done */ | ||
1020 | if (newmode == KGC_GEN) /* entering generational mode? */ | ||
1021 | entergen(L, g); | ||
1022 | else { /* entering incremental mode */ | ||
1023 | lua_checkmemory(L); | ||
1024 | youngcollection(L, g); | ||
1025 | g->old = g->survival = NULL; | ||
1026 | lua_checkmemory(L); | ||
1027 | } | ||
1028 | g->gckind = newmode; | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | static void genstep (lua_State *L, global_State *g) { | ||
1034 | lu_mem mem; | ||
1035 | youngcollection(L, g); | ||
1036 | mem = gettotalbytes(g); | ||
1037 | luaE_setdebt(g, -((mem / 100) * 20)); | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | |||
1042 | |||
1043 | /* }====================================================== */ | ||
1044 | |||
925 | 1045 | ||
926 | /* | 1046 | /* |
927 | ** {====================================================== | 1047 | ** {====================================================== |
@@ -963,17 +1083,24 @@ static void entersweep (lua_State *L) { | |||
963 | } | 1083 | } |
964 | 1084 | ||
965 | 1085 | ||
1086 | static void deletealllist (lua_State *L, GCObject *p) { | ||
1087 | while (p) { | ||
1088 | GCObject *next = p->next; | ||
1089 | freeobj(L, p); | ||
1090 | p = next; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | |||
966 | void luaC_freeallobjects (lua_State *L) { | 1095 | void luaC_freeallobjects (lua_State *L) { |
967 | global_State *g = G(L); | 1096 | global_State *g = G(L); |
968 | separatetobefnz(g, 1); /* separate all objects with finalizers */ | 1097 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
969 | lua_assert(g->finobj == NULL); | 1098 | lua_assert(g->finobj == NULL); |
970 | callallpendingfinalizers(L); | 1099 | callallpendingfinalizers(L); |
971 | lua_assert(g->tobefnz == NULL); | 1100 | lua_assert(g->tobefnz == NULL); |
972 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 1101 | deletealllist(L, g->finobj); |
973 | g->gckind = KGC_NORMAL; | 1102 | deletealllist(L, g->allgc); |
974 | sweepwholelist(L, &g->finobj); | 1103 | deletealllist(L, g->fixedgc); /* collect fixed objects */ |
975 | sweepwholelist(L, &g->allgc); | ||
976 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | ||
977 | lua_assert(g->strt.nuse == 0); | 1104 | lua_assert(g->strt.nuse == 0); |
978 | } | 1105 | } |
979 | 1106 | ||
@@ -996,6 +1123,7 @@ static l_mem atomic (lua_State *L) { | |||
996 | propagateall(g); /* propagate changes */ | 1123 | propagateall(g); /* propagate changes */ |
997 | work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ | 1124 | work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ |
998 | g->gray = grayagain; | 1125 | g->gray = grayagain; |
1126 | g->grayagain = NULL; | ||
999 | propagateall(g); /* traverse 'grayagain' list */ | 1127 | propagateall(g); /* traverse 'grayagain' list */ |
1000 | g->GCmemtrav = 0; /* restart counting */ | 1128 | g->GCmemtrav = 0; /* restart counting */ |
1001 | convergeephemerons(g); | 1129 | convergeephemerons(g); |
@@ -1052,10 +1180,10 @@ static lu_mem singlestep (lua_State *L) { | |||
1052 | } | 1180 | } |
1053 | case GCSpropagate: { | 1181 | case GCSpropagate: { |
1054 | g->GCmemtrav = 0; | 1182 | g->GCmemtrav = 0; |
1055 | lua_assert(g->gray); | 1183 | if (g->gray == NULL) /* no more gray objects? */ |
1056 | propagatemark(g); | ||
1057 | if (g->gray == NULL) /* no more gray objects? */ | ||
1058 | g->gcstate = GCSatomic; /* finish propagate phase */ | 1184 | g->gcstate = GCSatomic; /* finish propagate phase */ |
1185 | else | ||
1186 | propagatemark(g); /* traverse one gray object */ | ||
1059 | return g->GCmemtrav; /* memory traversed in this step */ | 1187 | return g->GCmemtrav; /* memory traversed in this step */ |
1060 | } | 1188 | } |
1061 | case GCSatomic: { | 1189 | case GCSatomic: { |
@@ -1123,15 +1251,10 @@ static l_mem getdebt (global_State *g) { | |||
1123 | } | 1251 | } |
1124 | 1252 | ||
1125 | /* | 1253 | /* |
1126 | ** performs a basic GC step when collector is running | 1254 | ** performs a basic incremental step |
1127 | */ | 1255 | */ |
1128 | void luaC_step (lua_State *L) { | 1256 | static void incstep (lua_State *L, global_State *g) { |
1129 | global_State *g = G(L); | 1257 | l_mem debt = getdebt(g); /* GC deficit (to be paid now) */ |
1130 | l_mem debt = getdebt(g); /* GC deficit (be paid now) */ | ||
1131 | if (!g->gcrunning) { /* not running? */ | ||
1132 | luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ | ||
1133 | return; | ||
1134 | } | ||
1135 | do { /* repeat until pause or enough "credit" (negative debt) */ | 1258 | do { /* repeat until pause or enough "credit" (negative debt) */ |
1136 | lu_mem work = singlestep(L); /* perform one single step */ | 1259 | lu_mem work = singlestep(L); /* perform one single step */ |
1137 | debt -= work; | 1260 | debt -= work; |
@@ -1145,6 +1268,19 @@ void luaC_step (lua_State *L) { | |||
1145 | } | 1268 | } |
1146 | } | 1269 | } |
1147 | 1270 | ||
1271 | /* | ||
1272 | ** performs a basic GC step when collector is running | ||
1273 | */ | ||
1274 | void luaC_step (lua_State *L) { | ||
1275 | global_State *g = G(L); | ||
1276 | if (!g->gcrunning) /* not running? */ | ||
1277 | luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ | ||
1278 | else if (g->gckind == KGC_NORMAL) | ||
1279 | incstep(L, g); | ||
1280 | else | ||
1281 | genstep(L, g); | ||
1282 | } | ||
1283 | |||
1148 | 1284 | ||
1149 | /* | 1285 | /* |
1150 | ** Performs a full GC cycle; if 'isemergency', set a flag to avoid | 1286 | ** Performs a full GC cycle; if 'isemergency', set a flag to avoid |
@@ -1164,7 +1300,6 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
1164 | } | 1300 | } |
1165 | /* finish any pending sweep phase to start a new cycle */ | 1301 | /* finish any pending sweep phase to start a new cycle */ |
1166 | luaC_runtilstate(L, bitmask(GCSpause)); | 1302 | luaC_runtilstate(L, bitmask(GCSpause)); |
1167 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ | ||
1168 | luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ | 1303 | luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ |
1169 | /* estimate must be correct after a full GC cycle */ | 1304 | /* estimate must be correct after a full GC cycle */ |
1170 | lua_assert(g->GCestimate == gettotalbytes(g)); | 1305 | lua_assert(g->GCestimate == gettotalbytes(g)); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 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 | */ |
@@ -79,7 +79,8 @@ | |||
79 | #define WHITE1BIT 1 /* object is white (type 1) */ | 79 | #define WHITE1BIT 1 /* object is white (type 1) */ |
80 | #define BLACKBIT 2 /* object is black */ | 80 | #define BLACKBIT 2 /* object is black */ |
81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ | 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ |
82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 82 | #define OLDBIT 4 /* object is old (gen. mode) */ |
83 | #define TESTGRAYBIT 7 /* used by tests (luaL_checkmemory) */ | ||
83 | 84 | ||
84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 85 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
85 | 86 | ||
@@ -88,11 +89,12 @@ | |||
88 | #define isblack(x) testbit((x)->marked, BLACKBIT) | 89 | #define isblack(x) testbit((x)->marked, BLACKBIT) |
89 | #define isgray(x) /* neither white nor black */ \ | 90 | #define isgray(x) /* neither white nor black */ \ |
90 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) | 91 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) |
92 | #define isold(x) testbit((x)->marked, OLDBIT) | ||
91 | 93 | ||
92 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) | 94 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) |
93 | 95 | ||
94 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) | 96 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) |
95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) | 97 | #define isdeadm(ow,m) ((m) & (ow)) |
96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) | 98 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) |
97 | 99 | ||
98 | #define changewhite(x) ((x)->marked ^= WHITEBITS) | 100 | #define changewhite(x) ((x)->marked ^= WHITEBITS) |
@@ -142,6 +144,7 @@ LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); | |||
142 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); | 144 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); |
143 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | 145 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
144 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); | 146 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); |
147 | LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); | ||
145 | 148 | ||
146 | 149 | ||
147 | #endif | 150 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.132 2015/11/02 16:01:41 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 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 | */ |
@@ -319,6 +319,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
319 | g->gcstate = GCSpause; | 319 | g->gcstate = GCSpause; |
320 | g->gckind = KGC_NORMAL; | 320 | g->gckind = KGC_NORMAL; |
321 | g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; | 321 | g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; |
322 | g->survival = g->old = NULL; | ||
322 | g->sweepgc = NULL; | 323 | g->sweepgc = NULL; |
323 | g->gray = g->grayagain = NULL; | 324 | g->gray = g->grayagain = NULL; |
324 | g->weak = g->ephemeron = g->allweak = NULL; | 325 | g->weak = g->ephemeron = g->allweak = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.133 2016/12/22 13:08:50 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.134 2017/02/15 18:52:13 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 | */ |
@@ -70,7 +70,8 @@ struct lua_longjmp; /* defined in ldo.c */ | |||
70 | 70 | ||
71 | /* kinds of Garbage Collection */ | 71 | /* kinds of Garbage Collection */ |
72 | #define KGC_NORMAL 0 | 72 | #define KGC_NORMAL 0 |
73 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ | 73 | #define KGC_GEN 1 /* generational gc */ |
74 | #define KGC_EMERGENCY 2 /* gc was forced by an allocation failure */ | ||
74 | 75 | ||
75 | 76 | ||
76 | typedef struct stringtable { | 77 | typedef struct stringtable { |
@@ -158,6 +159,9 @@ typedef struct global_State { | |||
158 | GCObject *allweak; /* list of all-weak tables */ | 159 | GCObject *allweak; /* list of all-weak tables */ |
159 | GCObject *tobefnz; /* list of userdata to be GC */ | 160 | GCObject *tobefnz; /* list of userdata to be GC */ |
160 | GCObject *fixedgc; /* list of objects not to be collected */ | 161 | GCObject *fixedgc; /* list of objects not to be collected */ |
162 | /* fields for generational collector */ | ||
163 | GCObject *old; /* start of old objects */ | ||
164 | GCObject *survival; /* start of objects that survived one GC cycle */ | ||
161 | struct lua_State *twups; /* list of threads with open upvalues */ | 165 | struct lua_State *twups; /* list of threads with open upvalues */ |
162 | unsigned int gcfinnum; /* number of finalizers to call in each GC step */ | 166 | unsigned int gcfinnum; /* number of finalizers to call in each GC step */ |
163 | int gcpause; /* size of pause between successive GCs */ | 167 | int gcpause; /* size of pause between successive GCs */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.210 2016/11/07 12:38:35 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.211 2016/12/04 20:17:24 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -195,9 +195,13 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | |||
195 | 195 | ||
196 | 196 | ||
197 | static void printobj (global_State *g, GCObject *o) { | 197 | static void printobj (global_State *g, GCObject *o) { |
198 | printf("||%s(%p)-%c(%02X)||", | 198 | printf("||%s(%p)-%c%c(%02X)||", |
199 | ttypename(novariant(o->tt)), (void *)o, | 199 | ttypename(novariant(o->tt)), (void *)o, |
200 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->marked); | 200 | isdead(g,o) ? 'd' : isblack(o) ? 'b' : iswhite(o) ? 'w' : 'g', |
201 | testbit(o->marked, OLDBIT) ? 'o' : 'n', | ||
202 | o->marked); | ||
203 | if (o->tt == LUA_TSHRSTR || o->tt == LUA_TLNGSTR) | ||
204 | printf(" '%s'", getstr(gco2ts(o))); | ||
201 | } | 205 | } |
202 | 206 | ||
203 | 207 | ||
@@ -364,8 +368,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
364 | } | 368 | } |
365 | 369 | ||
366 | 370 | ||
367 | #define TESTGRAYBIT 7 | ||
368 | |||
369 | static void checkgraylist (global_State *g, GCObject *o) { | 371 | static void checkgraylist (global_State *g, GCObject *o) { |
370 | ((void)g); /* better to keep it available if we need to print an object */ | 372 | ((void)g); /* better to keep it available if we need to print an object */ |
371 | while (o) { | 373 | while (o) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.332 2016/12/22 15:51:20 roberto Exp roberto $ |
3 | ** Lua - A Scripting Language | 3 | ** Lua - A Scripting Language |
4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
5 | ** See Copyright Notice at the end of this file | 5 | ** See Copyright Notice at the end of this file |
@@ -308,6 +308,8 @@ LUA_API int (lua_isyieldable) (lua_State *L); | |||
308 | #define LUA_GCSETPAUSE 6 | 308 | #define LUA_GCSETPAUSE 6 |
309 | #define LUA_GCSETSTEPMUL 7 | 309 | #define LUA_GCSETSTEPMUL 7 |
310 | #define LUA_GCISRUNNING 9 | 310 | #define LUA_GCISRUNNING 9 |
311 | #define LUA_GCGEN 10 | ||
312 | #define LUA_GCINC 11 | ||
311 | 313 | ||
312 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 314 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
313 | 315 | ||