diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-07 15:45:11 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-07 15:45:11 -0300 |
commit | 925fe8a0f2a667c96c015ee74d1a702af9ea5507 (patch) | |
tree | bca1cb92e11218498f4c76f651f4a5fa1a8c87b5 /lgc.c | |
parent | 789e7acdea3ada96bd00b7aac6d82e805bfee85c (diff) | |
download | lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.tar.gz lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.tar.bz2 lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.zip |
First criteria for shifts minor<->major
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 81 |
1 files changed, 55 insertions, 26 deletions
@@ -1205,20 +1205,21 @@ static void correctgraylists (global_State *g) { | |||
1205 | /* | 1205 | /* |
1206 | ** Mark black 'OLD1' objects when starting a new young collection. | 1206 | ** 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 | 1207 | ** Gray objects are already in some gray list, and so will be visited in |
1208 | ** the atomic step. The counter 'GCmajorminor' keeps how many objects to | 1208 | ** the atomic step. Returns the number of objects that became old. |
1209 | ** become old before a major collection. | ||
1210 | */ | 1209 | */ |
1211 | static void markold (global_State *g, GCObject *from, GCObject *to) { | 1210 | static l_obj markold (global_State *g, GCObject *from, GCObject *to) { |
1212 | GCObject *p; | 1211 | GCObject *p; |
1212 | l_obj count = 0; | ||
1213 | for (p = from; p != to; p = p->next) { | 1213 | for (p = from; p != to; p = p->next) { |
1214 | if (getage(p) == G_OLD1) { | 1214 | if (getage(p) == G_OLD1) { |
1215 | lua_assert(!iswhite(p)); | 1215 | lua_assert(!iswhite(p)); |
1216 | setage(p, G_OLD); /* now they are old */ | 1216 | setage(p, G_OLD); /* now they are old */ |
1217 | g->GCmajorminor--; /* one more old object */ | 1217 | count++; /* one more old object */ |
1218 | if (isblack(p)) | 1218 | if (isblack(p)) |
1219 | reallymarkobject(g, p); | 1219 | reallymarkobject(g, p); |
1220 | } | 1220 | } |
1221 | } | 1221 | } |
1222 | return count; | ||
1222 | } | 1223 | } |
1223 | 1224 | ||
1224 | 1225 | ||
@@ -1240,7 +1241,7 @@ static void finishgencycle (lua_State *L, global_State *g) { | |||
1240 | */ | 1241 | */ |
1241 | static void atomic2major (lua_State *L, global_State *g) { | 1242 | static void atomic2major (lua_State *L, global_State *g) { |
1242 | l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; | 1243 | l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; |
1243 | g->GCmajorminor = gettotalobjs(g); | 1244 | g->GCmajorminor = g->marked; /* number of live objects */ |
1244 | g->gckind = KGC_GENMAJOR; | 1245 | g->gckind = KGC_GENMAJOR; |
1245 | g->reallyold = g->old1 = g->survival = NULL; | 1246 | g->reallyold = g->old1 = g->survival = NULL; |
1246 | g->finobjrold = g->finobjold1 = g->finobjsur = NULL; | 1247 | g->finobjrold = g->finobjold1 = g->finobjsur = NULL; |
@@ -1250,29 +1251,53 @@ static void atomic2major (lua_State *L, global_State *g) { | |||
1250 | 1251 | ||
1251 | 1252 | ||
1252 | /* | 1253 | /* |
1254 | ** Decide whether to shift to major mode. It tests two conditions: | ||
1255 | ** 1) Whether the number of added old objects in this collection is more | ||
1256 | ** than half the number of new objects. ("step" is the number of objects | ||
1257 | ** created between minor collections. Except for forward barriers, it | ||
1258 | ** is the maximum number of objects that can become old in each minor | ||
1259 | ** collection.) | ||
1260 | ** 2) Whether the accumulated number of added old objects is larger | ||
1261 | ** than 'minormajor'% of the number of lived objects after the last | ||
1262 | ** major collection. (That percentage is computed in 'limit'.) | ||
1263 | */ | ||
1264 | static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { | ||
1265 | l_obj step = applygcparam(g, genminormul, g->GCmajorminor); | ||
1266 | l_obj limit = applygcparam(g, minormajor, g->GCmajorminor); | ||
1267 | //printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); | ||
1268 | if (addedold1 >= (step >> 1) || g->marked >= limit) { | ||
1269 | atomic2major(L, g); /* go to major mode */ | ||
1270 | return 1; | ||
1271 | } | ||
1272 | return 0; /* stay in minor mode */ | ||
1273 | } | ||
1274 | |||
1275 | /* | ||
1253 | ** Does a young collection. First, mark 'OLD1' objects. Then does the | 1276 | ** Does a young collection. First, mark 'OLD1' objects. Then does the |
1254 | ** atomic step. Then, check whether to continue in minor mode. If so, | 1277 | ** atomic step. Then, check whether to continue in minor mode. If so, |
1255 | ** sweep all lists and advance pointers. Finally, finish the collection. | 1278 | ** sweep all lists and advance pointers. Finally, finish the collection. |
1256 | */ | 1279 | */ |
1257 | static void youngcollection (lua_State *L, global_State *g) { | 1280 | static void youngcollection (lua_State *L, global_State *g) { |
1281 | l_obj addedold1 = 0; | ||
1282 | l_obj marked = g->marked; /* preserve 'g->marked' */ | ||
1258 | GCObject **psurvival; /* to point to first non-dead survival object */ | 1283 | GCObject **psurvival; /* to point to first non-dead survival object */ |
1259 | GCObject *dummy; /* dummy out parameter to 'sweepgen' */ | 1284 | GCObject *dummy; /* dummy out parameter to 'sweepgen' */ |
1260 | lua_assert(g->gcstate == GCSpropagate); | 1285 | lua_assert(g->gcstate == GCSpropagate); |
1261 | g->marked = 0; | ||
1262 | if (g->firstold1) { /* are there regular OLD1 objects? */ | 1286 | if (g->firstold1) { /* are there regular OLD1 objects? */ |
1263 | markold(g, g->firstold1, g->reallyold); /* mark them */ | 1287 | addedold1 += markold(g, g->firstold1, g->reallyold); /* mark them */ |
1264 | g->firstold1 = NULL; /* no more OLD1 objects (for now) */ | 1288 | g->firstold1 = NULL; /* no more OLD1 objects (for now) */ |
1265 | } | 1289 | } |
1266 | markold(g, g->finobj, g->finobjrold); | 1290 | addedold1 += markold(g, g->finobj, g->finobjrold); |
1267 | markold(g, g->tobefnz, NULL); | 1291 | addedold1 += markold(g, g->tobefnz, NULL); |
1292 | |||
1293 | atomic(L); /* will lose 'g->marked' */ | ||
1268 | 1294 | ||
1269 | atomic(L); | 1295 | /* keep total number of added old1 objects */ |
1296 | g->marked = marked + addedold1; | ||
1270 | 1297 | ||
1271 | /* decide whether to shift to major mode */ | 1298 | /* decide whether to shift to major mode */ |
1272 | if (g->GCmajorminor <= 0) { /* ?? */ | 1299 | if (checkminormajor(L, g, addedold1)) |
1273 | atomic2major(L, g); /* go to major mode */ | ||
1274 | return; /* nothing else to be done here */ | 1300 | return; /* nothing else to be done here */ |
1275 | } | ||
1276 | 1301 | ||
1277 | /* sweep nursery and get a pointer to its last live element */ | 1302 | /* sweep nursery and get a pointer to its last live element */ |
1278 | g->gcstate = GCSswpallgc; | 1303 | g->gcstate = GCSswpallgc; |
@@ -1319,7 +1344,8 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
1319 | sweep2old(L, &g->tobefnz); | 1344 | sweep2old(L, &g->tobefnz); |
1320 | 1345 | ||
1321 | g->gckind = KGC_GENMINOR; | 1346 | g->gckind = KGC_GENMINOR; |
1322 | g->GCmajorminor = applygcparam(g, genmajormul, g->marked); | 1347 | g->GCmajorminor = g->marked; /* "base" for number of objects */ |
1348 | g->marked = 0; /* to count the number of added old1 objects */ | ||
1323 | finishgencycle(L, g); | 1349 | finishgencycle(L, g); |
1324 | } | 1350 | } |
1325 | 1351 | ||
@@ -1329,7 +1355,7 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
1329 | ** total number of objects grows 'genminormul'%. | 1355 | ** total number of objects grows 'genminormul'%. |
1330 | */ | 1356 | */ |
1331 | static void setminordebt (global_State *g) { | 1357 | static void setminordebt (global_State *g) { |
1332 | luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g))); | 1358 | luaE_setdebt(g, applygcparam(g, genminormul, g->GCmajorminor)); |
1333 | } | 1359 | } |
1334 | 1360 | ||
1335 | 1361 | ||
@@ -1369,13 +1395,11 @@ static void enterinc (global_State *g) { | |||
1369 | */ | 1395 | */ |
1370 | void luaC_changemode (lua_State *L, int newmode) { | 1396 | void luaC_changemode (lua_State *L, int newmode) { |
1371 | global_State *g = G(L); | 1397 | global_State *g = G(L); |
1398 | if (g->gckind == KGC_GENMAJOR) /* doing major collections? */ | ||
1399 | g->gckind = KGC_INC; /* already incremental but in name */ | ||
1372 | if (newmode != g->gckind) { /* does it need to change? */ | 1400 | if (newmode != g->gckind) { /* does it need to change? */ |
1373 | if (newmode == KGC_INC) { /* entering incremental mode? */ | 1401 | if (newmode == KGC_INC) /* entering incremental mode? */ |
1374 | if (g->gckind == KGC_GENMAJOR) | 1402 | enterinc(g); /* entering incremental mode */ |
1375 | g->gckind = KGC_INC; /* already incremental but in name */ | ||
1376 | else | ||
1377 | enterinc(g); /* entering incremental mode */ | ||
1378 | } | ||
1379 | else { | 1403 | else { |
1380 | lua_assert(newmode == KGC_GENMINOR); | 1404 | lua_assert(newmode == KGC_GENMINOR); |
1381 | entergen(L, g); | 1405 | entergen(L, g); |
@@ -1396,16 +1420,24 @@ static void fullgen (lua_State *L, global_State *g) { | |||
1396 | /* | 1420 | /* |
1397 | ** After an atomic incremental step from a major collection, | 1421 | ** After an atomic incremental step from a major collection, |
1398 | ** check whether collector could return to minor collections. | 1422 | ** check whether collector could return to minor collections. |
1423 | ** It checks whether the number of objects 'tobecollected' | ||
1424 | ** is greater than 'majorminor'% of the number of objects added | ||
1425 | ** since the last collection ('addedobjs'). | ||
1399 | */ | 1426 | */ |
1400 | static int checkmajorminor (lua_State *L, global_State *g) { | 1427 | static int checkmajorminor (lua_State *L, global_State *g) { |
1401 | if (g->gckind == KGC_GENMAJOR) { | 1428 | if (g->gckind == KGC_GENMAJOR) { |
1402 | l_obj numobjs = gettotalobjs(g); /* current count */ | 1429 | l_obj numobjs = gettotalobjs(g); |
1403 | if (g->marked < numobjs - (numobjs >> 2)) { /* ?? */ | 1430 | l_obj addedobjs = numobjs - g->GCmajorminor; |
1431 | l_obj limit = applygcparam(g, majorminor, addedobjs); | ||
1432 | l_obj tobecollected = numobjs - g->marked; | ||
1433 | //printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs); | ||
1434 | if (tobecollected > limit) { | ||
1404 | atomic2gen(L, g); /* return to generational mode */ | 1435 | atomic2gen(L, g); /* return to generational mode */ |
1405 | setminordebt(g); | 1436 | setminordebt(g); |
1406 | return 0; /* exit incremental collection */ | 1437 | return 0; /* exit incremental collection */ |
1407 | } | 1438 | } |
1408 | } | 1439 | } |
1440 | g->GCmajorminor = g->marked; /* prepare for next collection */ | ||
1409 | return 1; /* stay doing incremental collections */ | 1441 | return 1; /* stay doing incremental collections */ |
1410 | } | 1442 | } |
1411 | 1443 | ||
@@ -1634,8 +1666,6 @@ void luaC_step (lua_State *L) { | |||
1634 | if (!gcrunning(g)) /* not running? */ | 1666 | if (!gcrunning(g)) /* not running? */ |
1635 | luaE_setdebt(g, 2000); | 1667 | luaE_setdebt(g, 2000); |
1636 | else { | 1668 | else { |
1637 | //printf("> step: %d %d %ld %ld -> ", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt); | ||
1638 | |||
1639 | switch (g->gckind) { | 1669 | switch (g->gckind) { |
1640 | case KGC_INC: case KGC_GENMAJOR: | 1670 | case KGC_INC: case KGC_GENMAJOR: |
1641 | incstep(L, g); | 1671 | incstep(L, g); |
@@ -1645,7 +1675,6 @@ void luaC_step (lua_State *L) { | |||
1645 | setminordebt(g); | 1675 | setminordebt(g); |
1646 | break; | 1676 | break; |
1647 | } | 1677 | } |
1648 | //printf("%d %d %ld %ld\n", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt); | ||
1649 | } | 1678 | } |
1650 | } | 1679 | } |
1651 | 1680 | ||