diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 95 |
1 files changed, 35 insertions, 60 deletions
@@ -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 | */ |
1100 | static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | 1100 | static 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 | */ | ||
1143 | static 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 | */ |
1210 | static l_obj markold (global_State *g, GCObject *from, GCObject *to) { | 1204 | static 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 | */ |
1242 | static void atomic2major (lua_State *L, global_State *g) { | 1234 | static 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 | */ | ||
1382 | static 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 | */ |
1396 | void luaC_changemode (lua_State *L, int newmode) { | 1371 | void 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 | */ |
1414 | static void fullgen (lua_State *L, global_State *g) { | 1389 | static 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 | ||