aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-12-07 15:45:41 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-12-07 15:45:41 -0300
commitad73b332240ef5b9bab1517517f63a1425dc7545 (patch)
treef16bc7d4e498e009dbd83e1988b0d203129724cb /lgc.c
parent925fe8a0f2a667c96c015ee74d1a702af9ea5507 (diff)
downloadlua-ad73b332240ef5b9bab1517517f63a1425dc7545.tar.gz
lua-ad73b332240ef5b9bab1517517f63a1425dc7545.tar.bz2
lua-ad73b332240ef5b9bab1517517f63a1425dc7545.zip
Check minor->major made at the end of a minor cycle
It does not make sense to wait for another cycle to decide when much of the information about creation of old objects is already available.
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