diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-10-18 17:10:20 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-10-18 17:10:20 -0300 |
| commit | d0815046d003f8f24efcdb03d35dd125ddd3b5f9 (patch) | |
| tree | a1b6a63f16287957bcb2b6a79e003ebb723617fc | |
| parent | 3d54b42d59bcc1b31a369f3497ac22745d63cae6 (diff) | |
| download | lua-d0815046d003f8f24efcdb03d35dd125ddd3b5f9.tar.gz lua-d0815046d003f8f24efcdb03d35dd125ddd3b5f9.tar.bz2 lua-d0815046d003f8f24efcdb03d35dd125ddd3b5f9.zip | |
Some adjustments in transition minor->major
Plus extra comments and other details.
| -rw-r--r-- | lgc.c | 78 | ||||
| -rw-r--r-- | manual/manual.of | 5 |
2 files changed, 46 insertions, 37 deletions
| @@ -424,10 +424,8 @@ static void cleargraylists (global_State *g) { | |||
| 424 | 424 | ||
| 425 | /* | 425 | /* |
| 426 | ** mark root set and reset all gray lists, to start a new collection. | 426 | ** mark root set and reset all gray lists, to start a new collection. |
| 427 | ** 'marked' is initialized with the number of fixed objects in the state, | 427 | ** 'GCmarked' is initialized to count the total number of live bytes |
| 428 | ** to count the total number of live objects during a cycle. (That is | 428 | ** during a cycle. |
| 429 | ** the metafield names, plus the reserved words, plus "_ENV" plus the | ||
| 430 | ** memory-error message.) | ||
| 431 | */ | 429 | */ |
| 432 | static void restartcollection (global_State *g) { | 430 | static void restartcollection (global_State *g) { |
| 433 | cleargraylists(g); | 431 | cleargraylists(g); |
| @@ -1067,10 +1065,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 1067 | ** ======================================================= | 1065 | ** ======================================================= |
| 1068 | */ | 1066 | */ |
| 1069 | 1067 | ||
| 1068 | /* | ||
| 1069 | ** Fields 'GCmarked' and 'GCmajorminor' are used to control the pace and | ||
| 1070 | ** the mode of the collector. They play several roles, depending on the | ||
| 1071 | ** mode of the collector: | ||
| 1072 | ** * KGC_INC: | ||
| 1073 | ** GCmarked: number of marked bytes during a cycle. | ||
| 1074 | ** GCmajorminor: not used. | ||
| 1075 | ** * KGC_GENMINOR | ||
| 1076 | ** GCmarked: number of bytes that became old since last major collection. | ||
| 1077 | ** GCmajorminor: number of bytes marked in last major collection. | ||
| 1078 | ** * KGC_GENMAJOR | ||
| 1079 | ** GCmarked: number of bytes that became old sinse last major collection. | ||
| 1080 | ** GCmajorminor: number of bytes marked in last major collection. | ||
| 1081 | */ | ||
| 1082 | |||
| 1070 | 1083 | ||
| 1071 | /* | 1084 | /* |
| 1072 | ** Set the "time" to wait before starting a new incremental cycle; | 1085 | ** Set the "time" to wait before starting a new incremental cycle; |
| 1073 | ** cycle will start when number of objects in use hits the threshold of | 1086 | ** cycle will start when number of bytes in use hits the threshold of |
| 1074 | ** approximately (marked * pause / 100). | 1087 | ** approximately (marked * pause / 100). |
| 1075 | */ | 1088 | */ |
| 1076 | static void setpause (global_State *g) { | 1089 | static void setpause (global_State *g) { |
| @@ -1258,7 +1271,7 @@ static void finishgencycle (lua_State *L, global_State *g) { | |||
| 1258 | ** in generational mode. | 1271 | ** in generational mode. |
| 1259 | */ | 1272 | */ |
| 1260 | static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { | 1273 | static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { |
| 1261 | g->GCmajorminor = g->GCmarked; /* number of live objects */ | 1274 | g->GCmajorminor = g->GCmarked; /* number of live bytes */ |
| 1262 | g->gckind = kind; | 1275 | g->gckind = kind; |
| 1263 | g->reallyold = g->old1 = g->survival = NULL; | 1276 | g->reallyold = g->old1 = g->survival = NULL; |
| 1264 | g->finobjrold = g->finobjold1 = g->finobjsur = NULL; | 1277 | g->finobjrold = g->finobjold1 = g->finobjsur = NULL; |
| @@ -1269,21 +1282,16 @@ static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { | |||
| 1269 | 1282 | ||
| 1270 | 1283 | ||
| 1271 | /* | 1284 | /* |
| 1272 | ** Decide whether to shift to major mode. It tests two conditions: | 1285 | ** Decide whether to shift to major mode. It shifts if the accumulated |
| 1273 | ** 1) Whether the number of added old objects in this collection is more | 1286 | ** number of added old bytes (counted in 'GCmarked') is larger than |
| 1274 | ** than half the number of new objects. ('step' is equal to the debt set | 1287 | ** 'minormajor'% of the number of lived bytes after the last major |
| 1275 | ** to trigger the next minor collection; that is equal to the number | 1288 | ** collection. (This number is kept in 'GCmajorminor'.) |
| 1276 | ** of objects created since the previous minor collection. Except for | ||
| 1277 | ** forward barriers, it is the maximum number of objects that can become | ||
| 1278 | ** old in each minor collection.) | ||
| 1279 | ** 2) Whether the accumulated number of added old objects is larger | ||
| 1280 | ** than 'minormajor'% of the number of lived objects after the last | ||
| 1281 | ** major collection. (That percentage is computed in 'limit'.) | ||
| 1282 | */ | 1289 | */ |
| 1283 | static int checkminormajor (global_State *g, l_mem addedold1) { | 1290 | static int checkminormajor (global_State *g) { |
| 1284 | l_mem step = applygcparam(g, MINORMUL, g->GCmajorminor); | ||
| 1285 | l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); | 1291 | l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); |
| 1286 | return (addedold1 >= (step >> 1) || g->GCmarked >= limit); | 1292 | if (limit == 0) |
| 1293 | return 0; /* special case: 'minormajor' 0 stops major collections */ | ||
| 1294 | return (g->GCmarked >= limit); | ||
| 1287 | } | 1295 | } |
| 1288 | 1296 | ||
| 1289 | /* | 1297 | /* |
| @@ -1326,13 +1334,13 @@ static void youngcollection (lua_State *L, global_State *g) { | |||
| 1326 | 1334 | ||
| 1327 | sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1); | 1335 | sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1); |
| 1328 | 1336 | ||
| 1329 | /* keep total number of added old1 objects */ | 1337 | /* keep total number of added old1 bytes */ |
| 1330 | g->GCmarked = marked + addedold1; | 1338 | g->GCmarked = marked + addedold1; |
| 1331 | 1339 | ||
| 1332 | /* decide whether to shift to major mode */ | 1340 | /* decide whether to shift to major mode */ |
| 1333 | if (checkminormajor(g, addedold1)) { | 1341 | if (checkminormajor(g)) { |
| 1334 | minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ | 1342 | minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ |
| 1335 | g->GCmarked = 0; /* avoid pause in first major cycle */ | 1343 | g->GCmarked = 0; /* avoid pause in first major cycle (see 'setpause') */ |
| 1336 | } | 1344 | } |
| 1337 | else | 1345 | else |
| 1338 | finishgencycle(L, g); /* still in minor mode; finish it */ | 1346 | finishgencycle(L, g); /* still in minor mode; finish it */ |
| @@ -1361,8 +1369,8 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
| 1361 | sweep2old(L, &g->tobefnz); | 1369 | sweep2old(L, &g->tobefnz); |
| 1362 | 1370 | ||
| 1363 | g->gckind = KGC_GENMINOR; | 1371 | g->gckind = KGC_GENMINOR; |
| 1364 | g->GCmajorminor = g->GCmarked; /* "base" for number of objects */ | 1372 | g->GCmajorminor = g->GCmarked; /* "base" for number of bytes */ |
| 1365 | g->GCmarked = 0; /* to count the number of added old1 objects */ | 1373 | g->GCmarked = 0; /* to count the number of added old1 bytes */ |
| 1366 | finishgencycle(L, g); | 1374 | finishgencycle(L, g); |
| 1367 | } | 1375 | } |
| 1368 | 1376 | ||
| @@ -1423,15 +1431,15 @@ static void fullgen (lua_State *L, global_State *g) { | |||
| 1423 | /* | 1431 | /* |
| 1424 | ** After an atomic incremental step from a major collection, | 1432 | ** After an atomic incremental step from a major collection, |
| 1425 | ** check whether collector could return to minor collections. | 1433 | ** check whether collector could return to minor collections. |
| 1426 | ** It checks whether the number of objects 'tobecollected' | 1434 | ** It checks whether the number of bytes 'tobecollected' |
| 1427 | ** is greater than 'majorminor'% of the number of objects added | 1435 | ** is greater than 'majorminor'% of the number of bytes added |
| 1428 | ** since the last collection ('addedobjs'). | 1436 | ** since the last collection ('addedbytes'). |
| 1429 | */ | 1437 | */ |
| 1430 | static int checkmajorminor (lua_State *L, global_State *g) { | 1438 | static int checkmajorminor (lua_State *L, global_State *g) { |
| 1431 | if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ | 1439 | if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ |
| 1432 | l_mem numbytes = gettotalbytes(g); | 1440 | l_mem numbytes = gettotalbytes(g); |
| 1433 | l_mem addedobjs = numbytes - g->GCmajorminor; | 1441 | l_mem addedbytes = numbytes - g->GCmajorminor; |
| 1434 | l_mem limit = applygcparam(g, MAJORMINOR, addedobjs); | 1442 | l_mem limit = applygcparam(g, MAJORMINOR, addedbytes); |
| 1435 | l_mem tobecollected = numbytes - g->GCmarked; | 1443 | l_mem tobecollected = numbytes - g->GCmarked; |
| 1436 | if (tobecollected > limit) { | 1444 | if (tobecollected > limit) { |
| 1437 | atomic2gen(L, g); /* return to generational mode */ | 1445 | atomic2gen(L, g); /* return to generational mode */ |
| @@ -1670,9 +1678,7 @@ static void incstep (lua_State *L, global_State *g) { | |||
| 1670 | l_mem work2do = applygcparam(g, STEPMUL, stepsize); | 1678 | l_mem work2do = applygcparam(g, STEPMUL, stepsize); |
| 1671 | l_mem stres; | 1679 | l_mem stres; |
| 1672 | int fast = (work2do == 0); /* special case: do a full collection */ | 1680 | int fast = (work2do == 0); /* special case: do a full collection */ |
| 1673 | //printf("\n** %ld %ld %d\n", work2do, stepsize, g->gcstate); | ||
| 1674 | do { /* repeat until enough work */ | 1681 | do { /* repeat until enough work */ |
| 1675 | //printf("%d-", g->gcstate); | ||
| 1676 | stres = singlestep(L, fast); /* perform one single step */ | 1682 | stres = singlestep(L, fast); /* perform one single step */ |
| 1677 | if (stres == step2minor) /* returned to minor collections? */ | 1683 | if (stres == step2minor) /* returned to minor collections? */ |
| 1678 | return; /* nothing else to be done here */ | 1684 | return; /* nothing else to be done here */ |
| @@ -1688,6 +1694,10 @@ static void incstep (lua_State *L, global_State *g) { | |||
| 1688 | } | 1694 | } |
| 1689 | 1695 | ||
| 1690 | 1696 | ||
| 1697 | #if !defined(luai_tracegc) | ||
| 1698 | #define luai_tracegc(L) ((void)0) | ||
| 1699 | #endif | ||
| 1700 | |||
| 1691 | /* | 1701 | /* |
| 1692 | ** Performs a basic GC step if collector is running. (If collector is | 1702 | ** Performs a basic GC step if collector is running. (If collector is |
| 1693 | ** not running, set a reasonable debt to avoid it being called at | 1703 | ** not running, set a reasonable debt to avoid it being called at |
| @@ -1699,20 +1709,16 @@ void luaC_step (lua_State *L) { | |||
| 1699 | if (!gcrunning(g)) /* not running? */ | 1709 | if (!gcrunning(g)) /* not running? */ |
| 1700 | luaE_setdebt(g, 20000); | 1710 | luaE_setdebt(g, 20000); |
| 1701 | else { | 1711 | else { |
| 1702 | //printf("mem: %ld kind: %s ", gettotalbytes(g), | 1712 | luai_tracegc(L); /* for internal debugging */ |
| 1703 | // g->gckind == KGC_INC ? "inc" : g->gckind == KGC_GENMAJOR ? "genmajor" : | ||
| 1704 | // "genminor"); | ||
| 1705 | switch (g->gckind) { | 1713 | switch (g->gckind) { |
| 1706 | case KGC_INC: case KGC_GENMAJOR: | 1714 | case KGC_INC: case KGC_GENMAJOR: |
| 1707 | incstep(L, g); | 1715 | incstep(L, g); |
| 1708 | //printf("%d) ", g->gcstate); | ||
| 1709 | break; | 1716 | break; |
| 1710 | case KGC_GENMINOR: | 1717 | case KGC_GENMINOR: |
| 1711 | youngcollection(L, g); | 1718 | youngcollection(L, g); |
| 1712 | setminordebt(g); | 1719 | setminordebt(g); |
| 1713 | break; | 1720 | break; |
| 1714 | } | 1721 | } |
| 1715 | //printf("-> mem: %ld debt: %ld\n", gettotalbytes(g), g->GCdebt); | ||
| 1716 | } | 1722 | } |
| 1717 | } | 1723 | } |
| 1718 | 1724 | ||
diff --git a/manual/manual.of b/manual/manual.of index c93fbfcb..6947b2a0 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -719,6 +719,8 @@ than the total after the previous major collection. | |||
| 719 | For instance, for a multiplier of 100, | 719 | For instance, for a multiplier of 100, |
| 720 | the collector will do a major collection when the number of old bytes | 720 | the collector will do a major collection when the number of old bytes |
| 721 | gets larger than twice the total after the previous major collection. | 721 | gets larger than twice the total after the previous major collection. |
| 722 | As a special case, | ||
| 723 | a value of 0 stops the collector from doing major collections. | ||
| 722 | 724 | ||
| 723 | The major-minor multiplier controls the shift back to minor collections. | 725 | The major-minor multiplier controls the shift back to minor collections. |
| 724 | For a multiplier @M{x}, | 726 | For a multiplier @M{x}, |
| @@ -6441,7 +6443,8 @@ Changes the collector mode to generational and returns the previous mode. | |||
| 6441 | Changes and/or retrieves the values of a parameter of the collector. | 6443 | Changes and/or retrieves the values of a parameter of the collector. |
| 6442 | This option must be followed by one or two extra arguments: | 6444 | This option must be followed by one or two extra arguments: |
| 6443 | The name of the parameter being changed or retrieved (a string) | 6445 | The name of the parameter being changed or retrieved (a string) |
| 6444 | and an optional new value for that parameter (an integer). | 6446 | and an optional new value for that parameter, |
| 6447 | an integer in the range @M{[0,100000]}. | ||
| 6445 | The first argument must have one of the following values: | 6448 | The first argument must have one of the following values: |
| 6446 | @description{ | 6449 | @description{ |
| 6447 | @item{@St{minormul}| The minor multiplier. } | 6450 | @item{@St{minormul}| The minor multiplier. } |
