aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c95
1 files changed, 35 insertions, 60 deletions
diff --git a/lgc.c b/lgc.c
index a4f63765..ecd142cb 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1098,7 +1098,8 @@ static void sweep2old (lua_State *L, GCObject **p) {
1098** will also remove objects turned white here from any gray list. 1098** will also remove objects turned white here from any gray list.
1099*/ 1099*/
1100static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, 1100static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1101 GCObject *limit, GCObject **pfirstold1) { 1101 GCObject *limit, GCObject **pfirstold1,
1102 l_obj *paddedold) {
1102 static const lu_byte nextage[] = { 1103 static const lu_byte nextage[] = {
1103 G_SURVIVAL, /* from G_NEW */ 1104 G_SURVIVAL, /* from G_NEW */
1104 G_OLD1, /* from G_SURVIVAL */ 1105 G_OLD1, /* from G_SURVIVAL */
@@ -1108,6 +1109,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1108 G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ 1109 G_TOUCHED1, /* from G_TOUCHED1 (do not change) */
1109 G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ 1110 G_TOUCHED2 /* from G_TOUCHED2 (do not change) */
1110 }; 1111 };
1112 l_obj addedold = 0;
1111 int white = luaC_white(g); 1113 int white = luaC_white(g);
1112 GCObject *curr; 1114 GCObject *curr;
1113 while ((curr = *p) != limit) { 1115 while ((curr = *p) != limit) {
@@ -1125,29 +1127,21 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1125 else { /* all other objects will be old, and so keep their color */ 1127 else { /* all other objects will be old, and so keep their color */
1126 lua_assert(age != G_OLD1); /* advanced in 'markold' */ 1128 lua_assert(age != G_OLD1); /* advanced in 'markold' */
1127 setage(curr, nextage[age]); 1129 setage(curr, nextage[age]);
1128 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) 1130 if (getage(curr) == G_OLD1) {
1129 *pfirstold1 = curr; /* first OLD1 object in the list */ 1131 addedold++; /* one more object becoming old */
1132 if (*pfirstold1 == NULL)
1133 *pfirstold1 = curr; /* first OLD1 object in the list */
1134 }
1130 } 1135 }
1131 p = &curr->next; /* go to next element */ 1136 p = &curr->next; /* go to next element */
1132 } 1137 }
1133 } 1138 }
1139 *paddedold += addedold;
1134 return p; 1140 return p;
1135} 1141}
1136 1142
1137 1143
1138/* 1144/*
1139** Traverse a list making all its elements white and clearing their
1140** age. In incremental mode, all objects are 'new' all the time,
1141** except for fixed strings (which are always old).
1142*/
1143static void whitelist (global_State *g, GCObject *p) {
1144 int white = luaC_white(g);
1145 for (; p != NULL; p = p->next)
1146 p->marked = cast_byte((p->marked & ~maskgcbits) | white);
1147}
1148
1149
1150/*
1151** Correct a list of gray objects. Return a pointer to the last element 1145** Correct a list of gray objects. Return a pointer to the last element
1152** left on the list, so that we can link another list to the end of 1146** left on the list, so that we can link another list to the end of
1153** this one. 1147** this one.
@@ -1205,21 +1199,18 @@ static void correctgraylists (global_State *g) {
1205/* 1199/*
1206** Mark black 'OLD1' objects when starting a new young collection. 1200** Mark black 'OLD1' objects when starting a new young collection.
1207** Gray objects are already in some gray list, and so will be visited in 1201** Gray objects are already in some gray list, and so will be visited in
1208** the atomic step. Returns the number of objects that became old. 1202** the atomic step.
1209*/ 1203*/
1210static l_obj markold (global_State *g, GCObject *from, GCObject *to) { 1204static void markold (global_State *g, GCObject *from, GCObject *to) {
1211 GCObject *p; 1205 GCObject *p;
1212 l_obj count = 0;
1213 for (p = from; p != to; p = p->next) { 1206 for (p = from; p != to; p = p->next) {
1214 if (getage(p) == G_OLD1) { 1207 if (getage(p) == G_OLD1) {
1215 lua_assert(!iswhite(p)); 1208 lua_assert(!iswhite(p));
1216 setage(p, G_OLD); /* now they are old */ 1209 setage(p, G_OLD); /* now they are old */
1217 count++; /* one more old object */
1218 if (isblack(p)) 1210 if (isblack(p))
1219 reallymarkobject(g, p); 1211 reallymarkobject(g, p);
1220 } 1212 }
1221 } 1213 }
1222 return count;
1223} 1214}
1224 1215
1225 1216
@@ -1236,16 +1227,17 @@ static void finishgencycle (lua_State *L, global_State *g) {
1236 1227
1237 1228
1238/* 1229/*
1239** shifts from the end of an atomic step in a minor collection to 1230** Shifts from a minor collection to major collections. It starts in
1240** major collections. 1231** the "sweep all" state to clear all objects, which are mostly black
1232** in generational mode.
1241*/ 1233*/
1242static void atomic2major (lua_State *L, global_State *g) { 1234static void minor2inc (lua_State *L, global_State *g, int kind) {
1243 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1235 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1244 g->GCmajorminor = g->marked; /* number of live objects */ 1236 g->GCmajorminor = g->marked; /* number of live objects */
1245 g->gckind = KGC_GENMAJOR; 1237 g->gckind = kind;
1246 g->reallyold = g->old1 = g->survival = NULL; 1238 g->reallyold = g->old1 = g->survival = NULL;
1247 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1239 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1248 entersweep(L); /* continue from atomic as an incremental cycle */ 1240 entersweep(L); /* continue as an incremental cycle */
1249 luaE_setdebt(g, stepsize); 1241 luaE_setdebt(g, stepsize);
1250} 1242}
1251 1243
@@ -1266,7 +1258,7 @@ static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
1266 l_obj limit = applygcparam(g, minormajor, g->GCmajorminor); 1258 l_obj limit = applygcparam(g, minormajor, g->GCmajorminor);
1267//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); 1259//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
1268 if (addedold1 >= (step >> 1) || g->marked >= limit) { 1260 if (addedold1 >= (step >> 1) || g->marked >= limit) {
1269 atomic2major(L, g); /* go to major mode */ 1261 minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */
1270 return 1; 1262 return 1;
1271 } 1263 }
1272 return 0; /* stay in minor mode */ 1264 return 0; /* stay in minor mode */
@@ -1284,41 +1276,40 @@ static void youngcollection (lua_State *L, global_State *g) {
1284 GCObject *dummy; /* dummy out parameter to 'sweepgen' */ 1276 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1285 lua_assert(g->gcstate == GCSpropagate); 1277 lua_assert(g->gcstate == GCSpropagate);
1286 if (g->firstold1) { /* are there regular OLD1 objects? */ 1278 if (g->firstold1) { /* are there regular OLD1 objects? */
1287 addedold1 += markold(g, g->firstold1, g->reallyold); /* mark them */ 1279 markold(g, g->firstold1, g->reallyold); /* mark them */
1288 g->firstold1 = NULL; /* no more OLD1 objects (for now) */ 1280 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1289 } 1281 }
1290 addedold1 += markold(g, g->finobj, g->finobjrold); 1282 markold(g, g->finobj, g->finobjrold);
1291 addedold1 += markold(g, g->tobefnz, NULL); 1283 markold(g, g->tobefnz, NULL);
1292 1284
1293 atomic(L); /* will lose 'g->marked' */ 1285 atomic(L); /* will lose 'g->marked' */
1294 1286
1295 /* keep total number of added old1 objects */
1296 g->marked = marked + addedold1;
1297
1298 /* decide whether to shift to major mode */
1299 if (checkminormajor(L, g, addedold1))
1300 return; /* nothing else to be done here */
1301
1302 /* sweep nursery and get a pointer to its last live element */ 1287 /* sweep nursery and get a pointer to its last live element */
1303 g->gcstate = GCSswpallgc; 1288 g->gcstate = GCSswpallgc;
1304 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); 1289 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1, &addedold1);
1305 /* sweep 'survival' */ 1290 /* sweep 'survival' */
1306 sweepgen(L, g, psurvival, g->old1, &g->firstold1); 1291 sweepgen(L, g, psurvival, g->old1, &g->firstold1, &addedold1);
1307 g->reallyold = g->old1; 1292 g->reallyold = g->old1;
1308 g->old1 = *psurvival; /* 'survival' survivals are old now */ 1293 g->old1 = *psurvival; /* 'survival' survivals are old now */
1309 g->survival = g->allgc; /* all news are survivals */ 1294 g->survival = g->allgc; /* all news are survivals */
1310 1295
1311 /* repeat for 'finobj' lists */ 1296 /* repeat for 'finobj' lists */
1312 dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */ 1297 dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */
1313 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy); 1298 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy, &addedold1);
1314 /* sweep 'survival' */ 1299 /* sweep 'survival' */
1315 sweepgen(L, g, psurvival, g->finobjold1, &dummy); 1300 sweepgen(L, g, psurvival, g->finobjold1, &dummy, &addedold1);
1316 g->finobjrold = g->finobjold1; 1301 g->finobjrold = g->finobjold1;
1317 g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ 1302 g->finobjold1 = *psurvival; /* 'survival' survivals are old now */
1318 g->finobjsur = g->finobj; /* all news are survivals */ 1303 g->finobjsur = g->finobj; /* all news are survivals */
1319 1304
1320 sweepgen(L, g, &g->tobefnz, NULL, &dummy); 1305 sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1);
1321 finishgencycle(L, g); 1306
1307 /* keep total number of added old1 objects */
1308 g->marked = marked + addedold1;
1309
1310 /* decide whether to shift to major mode */
1311 if (!checkminormajor(L, g, addedold1))
1312 finishgencycle(L, g); /* still in minor mode; finish it */
1322} 1313}
1323 1314
1324 1315
@@ -1375,22 +1366,6 @@ static void entergen (lua_State *L, global_State *g) {
1375 1366
1376 1367
1377/* 1368/*
1378** Enter incremental mode. Turn all objects white, make all
1379** intermediate lists point to NULL (to avoid invalid pointers),
1380** and go to the pause state.
1381*/
1382static void enterinc (global_State *g) {
1383 whitelist(g, g->allgc);
1384 whitelist(g, g->finobj);
1385 whitelist(g, g->tobefnz);
1386 g->reallyold = g->old1 = g->survival = NULL;
1387 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1388 g->gcstate = GCSpause;
1389 g->gckind = KGC_INC;
1390}
1391
1392
1393/*
1394** Change collector mode to 'newmode'. 1369** Change collector mode to 'newmode'.
1395*/ 1370*/
1396void luaC_changemode (lua_State *L, int newmode) { 1371void luaC_changemode (lua_State *L, int newmode) {
@@ -1399,7 +1374,7 @@ void luaC_changemode (lua_State *L, int newmode) {
1399 g->gckind = KGC_INC; /* already incremental but in name */ 1374 g->gckind = KGC_INC; /* already incremental but in name */
1400 if (newmode != g->gckind) { /* does it need to change? */ 1375 if (newmode != g->gckind) { /* does it need to change? */
1401 if (newmode == KGC_INC) /* entering incremental mode? */ 1376 if (newmode == KGC_INC) /* entering incremental mode? */
1402 enterinc(g); /* entering incremental mode */ 1377 minor2inc(L, g, KGC_INC); /* entering incremental mode */
1403 else { 1378 else {
1404 lua_assert(newmode == KGC_GENMINOR); 1379 lua_assert(newmode == KGC_GENMINOR);
1405 entergen(L, g); 1380 entergen(L, g);
@@ -1412,7 +1387,7 @@ void luaC_changemode (lua_State *L, int newmode) {
1412** Does a full collection in generational mode. 1387** Does a full collection in generational mode.
1413*/ 1388*/
1414static void fullgen (lua_State *L, global_State *g) { 1389static void fullgen (lua_State *L, global_State *g) {
1415 enterinc(g); 1390 minor2inc(L, g, KGC_INC);
1416 entergen(L, g); 1391 entergen(L, g);
1417} 1392}
1418 1393