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 | |
| parent | 789e7acdea3ada96bd00b7aac6d82e805bfee85c (diff) | |
| download | lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.tar.gz lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.tar.bz2 lua-925fe8a0f2a667c96c015ee74d1a702af9ea5507.zip | |
First criteria for shifts minor<->major
| -rw-r--r-- | lapi.c | 25 | ||||
| -rw-r--r-- | lbaselib.c | 13 | ||||
| -rw-r--r-- | lgc.c | 81 | ||||
| -rw-r--r-- | lgc.h | 48 | ||||
| -rw-r--r-- | lstate.c | 3 | ||||
| -rw-r--r-- | lstate.h | 9 | ||||
| -rw-r--r-- | lua.c | 2 | ||||
| -rw-r--r-- | manual/manual.of | 134 |
8 files changed, 187 insertions, 128 deletions
| @@ -1204,26 +1204,29 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { | |||
| 1204 | break; | 1204 | break; |
| 1205 | } | 1205 | } |
| 1206 | case LUA_GCGEN: { | 1206 | case LUA_GCGEN: { |
| 1207 | unsigned int minormul = va_arg(argp, unsigned int); | 1207 | int minormul = va_arg(argp, int); |
| 1208 | unsigned int majormul = va_arg(argp, unsigned int); | 1208 | int minormajor = va_arg(argp, int); |
| 1209 | int majorminor = va_arg(argp, int); | ||
| 1209 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; | 1210 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; |
| 1210 | if (minormul != 0) | 1211 | if (minormul >= 0) |
| 1211 | setgcparam(g, genminormul, minormul); | 1212 | setgcparam(g, genminormul, minormul); |
| 1212 | if (majormul != 0) | 1213 | if (minormajor >= 0) |
| 1213 | setgcparam(g, genmajormul, majormul); | 1214 | setgcparam(g, minormajor, minormajor); |
| 1215 | if (majorminor >= 0) | ||
| 1216 | setgcparam(g, majorminor, majorminor); | ||
| 1214 | luaC_changemode(L, KGC_GENMINOR); | 1217 | luaC_changemode(L, KGC_GENMINOR); |
| 1215 | break; | 1218 | break; |
| 1216 | } | 1219 | } |
| 1217 | case LUA_GCINC: { | 1220 | case LUA_GCINC: { |
| 1218 | unsigned int pause = va_arg(argp, unsigned int); | 1221 | int pause = va_arg(argp, int); |
| 1219 | unsigned int stepmul = va_arg(argp, unsigned int); | 1222 | int stepmul = va_arg(argp, int); |
| 1220 | unsigned int stepsize = va_arg(argp, unsigned int); | 1223 | int stepsize = va_arg(argp, int); |
| 1221 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; | 1224 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; |
| 1222 | if (pause != 0) | 1225 | if (pause >= 0) |
| 1223 | setgcparam(g, gcpause, pause); | 1226 | setgcparam(g, gcpause, pause); |
| 1224 | if (stepmul != 0) | 1227 | if (stepmul >= 0) |
| 1225 | setgcparam(g, gcstepmul, stepmul); | 1228 | setgcparam(g, gcstepmul, stepmul); |
| 1226 | if (stepsize != 0) | 1229 | if (stepsize >= 0) |
| 1227 | g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize | 1230 | g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize |
| 1228 | : log2maxs(l_obj); | 1231 | : log2maxs(l_obj); |
| 1229 | luaC_changemode(L, KGC_INC); | 1232 | luaC_changemode(L, KGC_INC); |
| @@ -224,14 +224,15 @@ static int luaB_collectgarbage (lua_State *L) { | |||
| 224 | return 1; | 224 | return 1; |
| 225 | } | 225 | } |
| 226 | case LUA_GCGEN: { | 226 | case LUA_GCGEN: { |
| 227 | int minormul = (int)luaL_optinteger(L, 2, 0); | 227 | int minormul = (int)luaL_optinteger(L, 2, -1); |
| 228 | int majormul = (int)luaL_optinteger(L, 3, 0); | 228 | int majorminor = (int)luaL_optinteger(L, 3, -1); |
| 229 | return pushmode(L, lua_gc(L, o, minormul, majormul)); | 229 | int minormajor = (int)luaL_optinteger(L, 4, -1); |
| 230 | return pushmode(L, lua_gc(L, o, minormul, majorminor, minormajor)); | ||
| 230 | } | 231 | } |
| 231 | case LUA_GCINC: { | 232 | case LUA_GCINC: { |
| 232 | int pause = (int)luaL_optinteger(L, 2, 0); | 233 | int pause = (int)luaL_optinteger(L, 2, -1); |
| 233 | int stepmul = (int)luaL_optinteger(L, 3, 0); | 234 | int stepmul = (int)luaL_optinteger(L, 3, -1); |
| 234 | int stepsize = (int)luaL_optinteger(L, 4, 0); | 235 | int stepsize = (int)luaL_optinteger(L, 4, -1); |
| 235 | return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); | 236 | return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); |
| 236 | } | 237 | } |
| 237 | default: { | 238 | default: { |
| @@ -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 | ||
| @@ -161,10 +161,24 @@ | |||
| 161 | 161 | ||
| 162 | /* Default Values for GC parameters */ | 162 | /* Default Values for GC parameters */ |
| 163 | 163 | ||
| 164 | /* generational */ | 164 | /* |
| 165 | ** Minor collections will shift to major ones after LUAI_MINORMAJOR% | ||
| 166 | ** objects become old. | ||
| 167 | */ | ||
| 168 | #define LUAI_MINORMAJOR 100 | ||
| 169 | |||
| 170 | /* | ||
| 171 | ** Major collections will shift to minor ones after a collection | ||
| 172 | ** collects at least LUAI_MAJORMINOR% of the new objects. | ||
| 173 | */ | ||
| 174 | #define LUAI_MAJORMINOR 80 | ||
| 175 | |||
| 176 | /* | ||
| 177 | ** A young (minor) collection will run after creating LUAI_GENMINORMUL% | ||
| 178 | ** new objects. | ||
| 179 | */ | ||
| 180 | #define LUAI_GENMINORMUL 20 | ||
| 165 | 181 | ||
| 166 | #define LUAI_GENMAJORMUL 100 /* major multiplier */ | ||
| 167 | #define LUAI_GENMINORMUL 20 /* minor multiplier */ | ||
| 168 | 182 | ||
| 169 | /* incremental */ | 183 | /* incremental */ |
| 170 | 184 | ||
| @@ -187,27 +201,17 @@ | |||
| 187 | 201 | ||
| 188 | /* | 202 | /* |
| 189 | ** Macros to set and apply GC parameters. GC parameters are given in | 203 | ** Macros to set and apply GC parameters. GC parameters are given in |
| 190 | ** percentage points, but are stored as lu_byte. To reduce their | 204 | ** percentage points, but are stored as lu_byte. To avoid repeated |
| 191 | ** values and avoid repeated divisions by 100, these macros store | 205 | ** divisions by 100, these macros store the original parameter |
| 192 | ** the original parameter multiplied by 2^n and divided by 100. | 206 | ** multiplied by 128 and divided by 100. To apply them, if it first |
| 193 | ** To apply them, the value is divided by 2^n (a shift) and then | 207 | ** divides the value by 128 it may lose precision; if it first |
| 194 | ** multiplied by the stored parameter, yielding | 208 | ** multiplies by the parameter, it may overflow. So, it first divides |
| 195 | ** value / 2^n * (original parameter * 2^n / 100), or approximately | 209 | ** by 32, then multiply by the parameter, and then divides the result by |
| 196 | ** (value * original parameter / 100). | 210 | ** 4. |
| 197 | ** | ||
| 198 | ** For most parameters, which are typically larger than 100%, 2^n is | ||
| 199 | ** 16 (2^4), allowing maximum values up to ~1500%, with a granularity | ||
| 200 | ** of ~6%. For the minor multiplier, which is typically smaller, | ||
| 201 | ** 2^n is 64 (2^6) to allow more precision. In that case, the maximum | ||
| 202 | ** value is ~400%, with a granularity of ~1.5%. | ||
| 203 | */ | 211 | */ |
| 204 | #define gcparamshift(p) \ | ||
| 205 | (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4) | ||
| 206 | |||
| 207 | #define setgcparam(g,p,v) \ | ||
| 208 | (g->p = (cast_uint(v) << gcparamshift(p)) / 100u) | ||
| 209 | #define applygcparam(g,p,v) (((v) >> gcparamshift(p)) * g->p) | ||
| 210 | 212 | ||
| 213 | #define setgcparam(g,p,v) (g->gcp##p = (cast_uint(v) << 7) / 100u) | ||
| 214 | #define applygcparam(g,p,v) ((((v) >> 5) * g->gcp##p) >> 2) | ||
| 211 | 215 | ||
| 212 | 216 | ||
| 213 | /* | 217 | /* |
| @@ -368,8 +368,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) { | |||
| 368 | setgcparam(g, gcpause, LUAI_GCPAUSE); | 368 | setgcparam(g, gcpause, LUAI_GCPAUSE); |
| 369 | setgcparam(g, gcstepmul, LUAI_GCMUL); | 369 | setgcparam(g, gcstepmul, LUAI_GCMUL); |
| 370 | g->gcstepsize = LUAI_GCSTEPSIZE; | 370 | g->gcstepsize = LUAI_GCSTEPSIZE; |
| 371 | setgcparam(g, genmajormul, LUAI_GENMAJORMUL); | ||
| 372 | setgcparam(g, genminormul, LUAI_GENMINORMUL); | 371 | setgcparam(g, genminormul, LUAI_GENMINORMUL); |
| 372 | setgcparam(g, minormajor, LUAI_MINORMAJOR); | ||
| 373 | setgcparam(g, majorminor, LUAI_MAJORMINOR); | ||
| 373 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; | 374 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
| 374 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 375 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
| 375 | /* memory allocation error: free partial state */ | 376 | /* memory allocation error: free partial state */ |
| @@ -264,16 +264,17 @@ typedef struct global_State { | |||
| 264 | TValue l_registry; | 264 | TValue l_registry; |
| 265 | TValue nilvalue; /* a nil value */ | 265 | TValue nilvalue; /* a nil value */ |
| 266 | unsigned int seed; /* randomized seed for hashes */ | 266 | unsigned int seed; /* randomized seed for hashes */ |
| 267 | unsigned short gcpgenminormul; /* control minor generational collections */ | ||
| 268 | unsigned short gcpmajorminor; /* control shift major->minor */ | ||
| 269 | unsigned short gcpminormajor; /* control shift minor->major */ | ||
| 270 | unsigned short gcpgcpause; /* size of pause between successive GCs */ | ||
| 271 | unsigned short gcpgcstepmul; /* GC "speed" */ | ||
| 267 | lu_byte currentwhite; | 272 | lu_byte currentwhite; |
| 268 | lu_byte gcstate; /* state of garbage collector */ | 273 | lu_byte gcstate; /* state of garbage collector */ |
| 269 | lu_byte gckind; /* kind of GC running */ | 274 | lu_byte gckind; /* kind of GC running */ |
| 270 | lu_byte gcstopem; /* stops emergency collections */ | 275 | lu_byte gcstopem; /* stops emergency collections */ |
| 271 | lu_byte genminormul; /* control for minor generational collections */ | ||
| 272 | lu_byte genmajormul; /* control for major generational collections */ | ||
| 273 | lu_byte gcstp; /* control whether GC is running */ | 276 | lu_byte gcstp; /* control whether GC is running */ |
| 274 | lu_byte gcemergency; /* true if this is an emergency collection */ | 277 | lu_byte gcemergency; /* true if this is an emergency collection */ |
| 275 | lu_byte gcpause; /* size of pause between successive GCs */ | ||
| 276 | lu_byte gcstepmul; /* GC "speed" */ | ||
| 277 | lu_byte gcstepsize; /* (log2 of) GC granularity */ | 278 | lu_byte gcstepsize; /* (log2 of) GC granularity */ |
| 278 | GCObject *allgc; /* list of all collectable objects */ | 279 | GCObject *allgc; /* list of all collectable objects */ |
| 279 | GCObject **sweepgc; /* current position of sweep in list */ | 280 | GCObject **sweepgc; /* current position of sweep in list */ |
| @@ -646,7 +646,7 @@ static int pmain (lua_State *L) { | |||
| 646 | luai_openlibs(L); /* open standard libraries */ | 646 | luai_openlibs(L); /* open standard libraries */ |
| 647 | createargtable(L, argv, argc, script); /* create table 'arg' */ | 647 | createargtable(L, argv, argc, script); /* create table 'arg' */ |
| 648 | lua_gc(L, LUA_GCRESTART); /* start GC... */ | 648 | lua_gc(L, LUA_GCRESTART); /* start GC... */ |
| 649 | lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ | 649 | lua_gc(L, LUA_GCGEN, -1, -1, -1); /* ...in generational mode */ |
| 650 | if (!(args & has_E)) { /* no option '-E'? */ | 650 | if (!(args & has_E)) { /* no option '-E'? */ |
| 651 | if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ | 651 | if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ |
| 652 | return 0; /* error running LUA_INIT */ | 652 | return 0; /* error running LUA_INIT */ |
diff --git a/manual/manual.of b/manual/manual.of index 263ced72..8607e57d 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -621,7 +621,8 @@ that is inaccessible from Lua. | |||
| 621 | another live object refer to the object.) | 621 | another live object refer to the object.) |
| 622 | Because Lua has no knowledge about @N{C code}, | 622 | Because Lua has no knowledge about @N{C code}, |
| 623 | it never collects objects accessible through the registry @see{registry}, | 623 | it never collects objects accessible through the registry @see{registry}, |
| 624 | which includes the global environment @see{globalenv}. | 624 | which includes the global environment @see{globalenv} and |
| 625 | the main thread. | ||
| 625 | 626 | ||
| 626 | 627 | ||
| 627 | The garbage collector (GC) in Lua can work in two modes: | 628 | The garbage collector (GC) in Lua can work in two modes: |
| @@ -638,8 +639,8 @@ therefore, optimal settings are also non-portable. | |||
| 638 | You can change the GC mode and parameters by calling | 639 | You can change the GC mode and parameters by calling |
| 639 | @Lid{lua_gc} @N{in C} | 640 | @Lid{lua_gc} @N{in C} |
| 640 | or @Lid{collectgarbage} in Lua. | 641 | or @Lid{collectgarbage} in Lua. |
| 641 | You can also use these functions to control | 642 | You can also use these functions to control the collector directly, |
| 642 | the collector directly (e.g., to stop and restart it). | 643 | for instance to stop or restart it. |
| 643 | 644 | ||
| 644 | } | 645 | } |
| 645 | 646 | ||
| @@ -656,39 +657,36 @@ and the @def{garbage-collector step size}. | |||
| 656 | 657 | ||
| 657 | The garbage-collector pause | 658 | The garbage-collector pause |
| 658 | controls how long the collector waits before starting a new cycle. | 659 | controls how long the collector waits before starting a new cycle. |
| 659 | The collector starts a new cycle when the use of memory | 660 | The collector starts a new cycle when the number of objects |
| 660 | hits @M{n%} of the use after the previous collection. | 661 | hits @M{n%} of the total after the previous collection. |
| 661 | Larger values make the collector less aggressive. | 662 | Larger values make the collector less aggressive. |
| 662 | Values equal to or less than 100 mean the collector will not wait to | 663 | Values equal to or less than 100 mean the collector will not wait to |
| 663 | start a new cycle. | 664 | start a new cycle. |
| 664 | A value of 200 means that the collector waits for the total memory in use | 665 | A value of 200 means that the collector waits for |
| 665 | to double before starting a new cycle. | 666 | the total number of objects to double before starting a new cycle. |
| 666 | The default value is 200; the maximum value is 1000. | 667 | The default value is 200; the maximum value is 1000. |
| 667 | 668 | ||
| 668 | The garbage-collector step multiplier | 669 | The garbage-collector step multiplier |
| 669 | controls the speed of the collector relative to | 670 | controls the speed of the collector relative to |
| 670 | memory allocation, | 671 | object creation, |
| 671 | that is, | 672 | that is, |
| 672 | how many elements it marks or sweeps for each | 673 | how many objects it marks or sweeps for each object created. |
| 673 | kilobyte of memory allocated. | 674 | Larger values make the collector more aggressive. |
| 674 | Larger values make the collector more aggressive but also increase | 675 | Beware that values too small can |
| 675 | the size of each incremental step. | 676 | make the collector too slow to ever finish a cycle. |
| 676 | You should not use values less than 100, | 677 | The default value is 300; the maximum value is 1000. |
| 677 | because they make the collector too slow and | ||
| 678 | can result in the collector never finishing a cycle. | ||
| 679 | The default value is 100; the maximum value is 1000. | ||
| 680 | 678 | ||
| 681 | The garbage-collector step size controls the | 679 | The garbage-collector step size controls the |
| 682 | size of each incremental step, | 680 | size of each incremental step, |
| 683 | specifically how many bytes the interpreter allocates | 681 | specifically how many objects the interpreter creates |
| 684 | before performing a step. | 682 | before performing a step. |
| 685 | This parameter is logarithmic: | 683 | This parameter is logarithmic: |
| 686 | A value of @M{n} means the interpreter will allocate @M{2@sp{n}} | 684 | A value of @M{n} means the interpreter will create @M{2@sp{n}} |
| 687 | bytes between steps and perform equivalent work during the step. | 685 | objects between steps and perform equivalent work during the step. |
| 688 | A large value (e.g., 60) makes the collector a stop-the-world | 686 | A large value (e.g., 60) makes the collector a stop-the-world |
| 689 | (non-incremental) collector. | 687 | (non-incremental) collector. |
| 690 | The default value is 13, | 688 | The default value is 8, |
| 691 | which means steps of approximately @N{8 Kbytes}. | 689 | which means steps of approximately @N{256 objects}. |
| 692 | 690 | ||
| 693 | } | 691 | } |
| 694 | 692 | ||
| @@ -697,31 +695,44 @@ which means steps of approximately @N{8 Kbytes}. | |||
| 697 | In generational mode, | 695 | In generational mode, |
| 698 | the collector does frequent @emph{minor} collections, | 696 | the collector does frequent @emph{minor} collections, |
| 699 | which traverses only objects recently created. | 697 | which traverses only objects recently created. |
| 700 | If after a minor collection the use of memory is still above a limit, | 698 | If after a minor collection the number of objects is above a limit, |
| 701 | the collector does a stop-the-world @emph{major} collection, | 699 | the collector shifts to a @emph{major} collection, |
| 702 | which traverses all objects. | 700 | which traverses all objects. |
| 703 | The generational mode uses two parameters: | 701 | The collector will then stay doing major collections until |
| 704 | the @def{minor multiplier} and the @def{the major multiplier}. | 702 | it detects that the program is generating enough garbage to justify |
| 703 | going back to minor collections. | ||
| 704 | |||
| 705 | The generational mode uses three parameters: | ||
| 706 | the @def{minor multiplier}, the @def{minor-major multiplier}, | ||
| 707 | and the @def{major-minor multiplier}. | ||
| 705 | 708 | ||
| 706 | The minor multiplier controls the frequency of minor collections. | 709 | The minor multiplier controls the frequency of minor collections. |
| 707 | For a minor multiplier @M{x}, | 710 | For a minor multiplier @M{x}, |
| 708 | a new minor collection will be done when memory | 711 | a new minor collection will be done when the number of objects |
| 709 | grows @M{x%} larger than the memory in use after the previous major | 712 | grows @M{x%} larger than the number in use just after the last collection. |
| 710 | collection. | ||
| 711 | For instance, for a multiplier of 20, | 713 | For instance, for a multiplier of 20, |
| 712 | the collector will do a minor collection when the use of memory | 714 | the collector will do a minor collection when the number of objects |
| 713 | gets 20% larger than the use after the previous major collection. | 715 | gets 20% larger than the total after the last major collection. |
| 714 | The default value is 20; the maximum value is 200. | 716 | The default value is 20. |
| 715 | 717 | ||
| 716 | The major multiplier controls the frequency of major collections. | 718 | The minor-major multiplier controls the shift to major collections. |
| 717 | For a major multiplier @M{x}, | 719 | For a multiplier @M{x}, |
| 718 | a new major collection will be done when memory | 720 | the collector will shift to a major collection |
| 719 | grows @M{x%} larger than the memory in use after the previous major | 721 | when the number of old objects grows @M{x%} larger |
| 720 | collection. | 722 | than the total after the previous major collection. |
| 721 | For instance, for a multiplier of 100, | 723 | For instance, for a multiplier of 100, |
| 722 | the collector will do a major collection when the use of memory | 724 | the collector will do a major collection when the number of old objects |
| 723 | gets larger than twice the use after the previous collection. | 725 | gets larger than twice the total after the previous major collection. |
| 724 | The default value is 100; the maximum value is 1000. | 726 | The default value is 100. |
| 727 | |||
| 728 | The major-minor multiplier controls the shift back to minor collections. | ||
| 729 | For a multiplier @M{x}, | ||
| 730 | the collector will shift back to minor collections | ||
| 731 | after a major collection collects at least @M{x%} of the allocated objects. | ||
| 732 | In particular, for a multiplier of 0, | ||
| 733 | the collector will immediately shift back to minor collections | ||
| 734 | after doing one cycle of major collections. | ||
| 735 | The default value is 20. | ||
| 725 | 736 | ||
| 726 | } | 737 | } |
| 727 | 738 | ||
| @@ -3311,9 +3322,8 @@ Returns the remainder of dividing the current amount of bytes of | |||
| 3311 | memory in use by Lua by 1024. | 3322 | memory in use by Lua by 1024. |
| 3312 | } | 3323 | } |
| 3313 | 3324 | ||
| 3314 | @item{@id{LUA_GCSTEP} @T{(int stepsize)}| | 3325 | @item{@id{LUA_GCSTEP}| |
| 3315 | Performs an incremental step of garbage collection, | 3326 | Performs a step of garbage collection. |
| 3316 | corresponding to the allocation of @id{stepsize} Kbytes. | ||
| 3317 | } | 3327 | } |
| 3318 | 3328 | ||
| 3319 | @item{@id{LUA_GCISRUNNING}| | 3329 | @item{@id{LUA_GCISRUNNING}| |
| @@ -3321,13 +3331,13 @@ Returns a boolean that tells whether the collector is running | |||
| 3321 | (i.e., not stopped). | 3331 | (i.e., not stopped). |
| 3322 | } | 3332 | } |
| 3323 | 3333 | ||
| 3324 | @item{@id{LUA_GCINC} (int pause, int stepmul, stepsize)| | 3334 | @item{@id{LUA_GCINC} (int pause, int stepmul, int stepsize)| |
| 3325 | Changes the collector to incremental mode | 3335 | Changes the collector to incremental mode |
| 3326 | with the given parameters @see{incmode}. | 3336 | with the given parameters @see{incmode}. |
| 3327 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). | 3337 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). |
| 3328 | } | 3338 | } |
| 3329 | 3339 | ||
| 3330 | @item{@id{LUA_GCGEN} (int minormul, int majormul)| | 3340 | @item{@id{LUA_GCGEN} (int minormul, int minormajor, int majorminor)| |
| 3331 | Changes the collector to generational mode | 3341 | Changes the collector to generational mode |
| 3332 | with the given parameters @see{genmode}. | 3342 | with the given parameters @see{genmode}. |
| 3333 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). | 3343 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). |
| @@ -6312,13 +6322,14 @@ gives the exact number of bytes in use by Lua. | |||
| 6312 | 6322 | ||
| 6313 | @item{@St{step}| | 6323 | @item{@St{step}| |
| 6314 | Performs a garbage-collection step. | 6324 | Performs a garbage-collection step. |
| 6315 | The step @Q{size} is controlled by @id{arg}. | 6325 | In incremental mode, |
| 6316 | With a zero value, | 6326 | that step corresponds to the current step size; |
| 6317 | the collector will perform one basic (indivisible) step. | 6327 | the function returns @true if the step finished a collection cycle. |
| 6318 | For non-zero values, | 6328 | In generational mode, |
| 6319 | the collector will perform as if that amount of memory | 6329 | the step performs a full minor collection or |
| 6320 | (in Kbytes) had been allocated by Lua. | 6330 | a major collection, |
| 6321 | Returns @true if the step finished a collection cycle. | 6331 | if the collector has scheduled one; |
| 6332 | the function returns @true if the step performed a major collection. | ||
| 6322 | } | 6333 | } |
| 6323 | 6334 | ||
| 6324 | @item{@St{isrunning}| | 6335 | @item{@St{isrunning}| |
| @@ -6332,15 +6343,15 @@ This option can be followed by three numbers: | |||
| 6332 | the garbage-collector pause, | 6343 | the garbage-collector pause, |
| 6333 | the step multiplier, | 6344 | the step multiplier, |
| 6334 | and the step size @see{incmode}. | 6345 | and the step size @see{incmode}. |
| 6335 | A zero means to not change that value. | 6346 | A -1 or absent value means to not change that value. |
| 6336 | } | 6347 | } |
| 6337 | 6348 | ||
| 6338 | @item{@St{generational}| | 6349 | @item{@St{generational}| |
| 6339 | Change the collector mode to generational. | 6350 | Change the collector mode to generational. |
| 6340 | This option can be followed by two numbers: | 6351 | This option can be followed by three numbers: |
| 6341 | the garbage-collector minor multiplier | 6352 | the garbage-collector minor multiplier, |
| 6342 | and the major multiplier @see{genmode}. | 6353 | the minor-major multiplier, and the major-minor multiplier @see{genmode}. |
| 6343 | A zero means to not change that value. | 6354 | A -1 or absent value means to not change that value. |
| 6344 | } | 6355 | } |
| 6345 | 6356 | ||
| 6346 | } | 6357 | } |
| @@ -9229,6 +9240,9 @@ declare a local variable with the same name in the loop body. | |||
| 9229 | @itemize{ | 9240 | @itemize{ |
| 9230 | 9241 | ||
| 9231 | @item{ | 9242 | @item{ |
| 9243 | There were several changes in the parameters | ||
| 9244 | for the options @St{incremental} and @St{generational} | ||
| 9245 | of the function @Lid{collectgarbage}. | ||
| 9232 | } | 9246 | } |
| 9233 | 9247 | ||
| 9234 | } | 9248 | } |
| @@ -9245,6 +9259,12 @@ it is equivalent to @Lid{lua_closethread} with | |||
| 9245 | @id{from} being @id{NULL}. | 9259 | @id{from} being @id{NULL}. |
| 9246 | } | 9260 | } |
| 9247 | 9261 | ||
| 9262 | @item{ | ||
| 9263 | There were several changes in the parameters | ||
| 9264 | for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN} | ||
| 9265 | of the function @Lid{lua_gc}. | ||
| 9266 | } | ||
| 9267 | |||
| 9248 | } | 9268 | } |
| 9249 | 9269 | ||
| 9250 | } | 9270 | } |
