diff options
Diffstat (limited to '')
-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 | } |