aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c141
1 files changed, 73 insertions, 68 deletions
diff --git a/lgc.c b/lgc.c
index 6a77b09b..50e6e0e9 100644
--- a/lgc.c
+++ b/lgc.c
@@ -206,7 +206,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
206 } 206 }
207 else { /* sweep phase */ 207 else { /* sweep phase */
208 lua_assert(issweepphase(g)); 208 lua_assert(issweepphase(g));
209 if (g->gckind != KGC_GEN) /* incremental mode? */ 209 if (g->gckind != KGC_GENMINOR) /* incremental mode? */
210 makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 210 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
211 } 211 }
212} 212}
@@ -219,7 +219,8 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
219void luaC_barrierback_ (lua_State *L, GCObject *o) { 219void luaC_barrierback_ (lua_State *L, GCObject *o) {
220 global_State *g = G(L); 220 global_State *g = G(L);
221 lua_assert(isblack(o) && !isdead(g, o)); 221 lua_assert(isblack(o) && !isdead(g, o));
222 lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); 222 lua_assert((g->gckind != KGC_GENMINOR)
223 || (isold(o) && getage(o) != G_TOUCHED1));
223 if (getage(o) == G_TOUCHED2) /* already in gray list? */ 224 if (getage(o) == G_TOUCHED2) /* already in gray list? */
224 set2gray(o); /* make it gray to become touched1 */ 225 set2gray(o); /* make it gray to become touched1 */
225 else /* link it in 'grayagain' and paint it gray */ 226 else /* link it in 'grayagain' and paint it gray */
@@ -1116,13 +1117,14 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1116 freeobj(L, curr); /* erase 'curr' */ 1117 freeobj(L, curr); /* erase 'curr' */
1117 } 1118 }
1118 else { /* correct mark and age */ 1119 else { /* correct mark and age */
1119 if (getage(curr) == G_NEW) { /* new objects go back to white */ 1120 int age = getage(curr);
1121 if (age == G_NEW) { /* new objects go back to white */
1120 int marked = curr->marked & ~maskgcbits; /* erase GC bits */ 1122 int marked = curr->marked & ~maskgcbits; /* erase GC bits */
1121 curr->marked = cast_byte(marked | G_SURVIVAL | white); 1123 curr->marked = cast_byte(marked | G_SURVIVAL | white);
1122 } 1124 }
1123 else { /* all other objects will be old, and so keep their color */ 1125 else { /* all other objects will be old, and so keep their color */
1124 lua_assert(getage(curr) != G_OLD1); /* advanced in 'markold' */ 1126 lua_assert(age != G_OLD1); /* advanced in 'markold' */
1125 setage(curr, nextage[getage(curr)]); 1127 setage(curr, nextage[age]);
1126 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) 1128 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL)
1127 *pfirstold1 = curr; /* first OLD1 object in the list */ 1129 *pfirstold1 = curr; /* first OLD1 object in the list */
1128 } 1130 }
@@ -1202,8 +1204,9 @@ static void correctgraylists (global_State *g) {
1202 1204
1203/* 1205/*
1204** Mark black 'OLD1' objects when starting a new young collection. 1206** Mark black 'OLD1' objects when starting a new young collection.
1205** Gray objects are already in some gray list, and so will be visited 1207** Gray objects are already in some gray list, and so will be visited in
1206** in the atomic step. 1208** the atomic step. The counter 'GCmajorminor' keeps how many objects to
1209** become old before a major collection.
1207*/ 1210*/
1208static void markold (global_State *g, GCObject *from, GCObject *to) { 1211static void markold (global_State *g, GCObject *from, GCObject *to) {
1209 GCObject *p; 1212 GCObject *p;
@@ -1211,6 +1214,7 @@ static void markold (global_State *g, GCObject *from, GCObject *to) {
1211 if (getage(p) == G_OLD1) { 1214 if (getage(p) == G_OLD1) {
1212 lua_assert(!iswhite(p)); 1215 lua_assert(!iswhite(p));
1213 setage(p, G_OLD); /* now they are old */ 1216 setage(p, G_OLD); /* now they are old */
1217 g->GCmajorminor--; /* one more old object */
1214 if (isblack(p)) 1218 if (isblack(p))
1215 reallymarkobject(g, p); 1219 reallymarkobject(g, p);
1216 } 1220 }
@@ -1231,22 +1235,45 @@ static void finishgencycle (lua_State *L, global_State *g) {
1231 1235
1232 1236
1233/* 1237/*
1238** shifts from the end of an atomic step in a minor collection to
1239** major collections.
1240*/
1241static void atomic2major (lua_State *L, global_State *g) {
1242 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1243 g->GCmajorminor = gettotalobjs(g);
1244 g->gckind = KGC_GENMAJOR;
1245 g->reallyold = g->old1 = g->survival = NULL;
1246 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1247 entersweep(L); /* continue from atomic as an incremental cycle */
1248 luaE_setdebt(g, stepsize);
1249}
1250
1251
1252/*
1234** Does a young collection. First, mark 'OLD1' objects. Then does the 1253** Does a young collection. First, mark 'OLD1' objects. Then does the
1235** atomic step. Then, sweep all lists and advance pointers. Finally, 1254** atomic step. Then, check whether to continue in minor mode. If so,
1236** finish the collection. 1255** sweep all lists and advance pointers. Finally, finish the collection.
1237*/ 1256*/
1238static void youngcollection (lua_State *L, global_State *g) { 1257static void youngcollection (lua_State *L, global_State *g) {
1239 GCObject **psurvival; /* to point to first non-dead survival object */ 1258 GCObject **psurvival; /* to point to first non-dead survival object */
1240 GCObject *dummy; /* dummy out parameter to 'sweepgen' */ 1259 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1241 lua_assert(g->gcstate == GCSpropagate); 1260 lua_assert(g->gcstate == GCSpropagate);
1261 g->marked = 0;
1242 if (g->firstold1) { /* are there regular OLD1 objects? */ 1262 if (g->firstold1) { /* are there regular OLD1 objects? */
1243 markold(g, g->firstold1, g->reallyold); /* mark them */ 1263 markold(g, g->firstold1, g->reallyold); /* mark them */
1244 g->firstold1 = NULL; /* no more OLD1 objects (for now) */ 1264 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1245 } 1265 }
1246 markold(g, g->finobj, g->finobjrold); 1266 markold(g, g->finobj, g->finobjrold);
1247 markold(g, g->tobefnz, NULL); 1267 markold(g, g->tobefnz, NULL);
1268
1248 atomic(L); 1269 atomic(L);
1249 1270
1271 /* decide whether to shift to major mode */
1272 if (g->GCmajorminor <= 0) { /* ?? */
1273 atomic2major(L, g); /* go to major mode */
1274 return; /* nothing else to be done here */
1275 }
1276
1250 /* sweep nursery and get a pointer to its last live element */ 1277 /* sweep nursery and get a pointer to its last live element */
1251 g->gcstate = GCSswpallgc; 1278 g->gcstate = GCSswpallgc;
1252 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); 1279 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1);
@@ -1291,8 +1318,8 @@ static void atomic2gen (lua_State *L, global_State *g) {
1291 1318
1292 sweep2old(L, &g->tobefnz); 1319 sweep2old(L, &g->tobefnz);
1293 1320
1294 g->gckind = KGC_GEN; 1321 g->gckind = KGC_GENMINOR;
1295 g->GClastmajor = gettotalobjs(g); /* base for memory control */ 1322 g->GCmajorminor = applygcparam(g, genmajormul, g->marked);
1296 finishgencycle(L, g); 1323 finishgencycle(L, g);
1297} 1324}
1298 1325
@@ -1328,9 +1355,9 @@ static void entergen (lua_State *L, global_State *g) {
1328*/ 1355*/
1329static void enterinc (global_State *g) { 1356static void enterinc (global_State *g) {
1330 whitelist(g, g->allgc); 1357 whitelist(g, g->allgc);
1331 g->reallyold = g->old1 = g->survival = NULL;
1332 whitelist(g, g->finobj); 1358 whitelist(g, g->finobj);
1333 whitelist(g, g->tobefnz); 1359 whitelist(g, g->tobefnz);
1360 g->reallyold = g->old1 = g->survival = NULL;
1334 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1361 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1335 g->gcstate = GCSpause; 1362 g->gcstate = GCSpause;
1336 g->gckind = KGC_INC; 1363 g->gckind = KGC_INC;
@@ -1350,7 +1377,7 @@ void luaC_changemode (lua_State *L, int newmode) {
1350 enterinc(g); /* entering incremental mode */ 1377 enterinc(g); /* entering incremental mode */
1351 } 1378 }
1352 else { 1379 else {
1353 lua_assert(newmode == KGC_GEN); 1380 lua_assert(newmode == KGC_GENMINOR);
1354 entergen(L, g); 1381 entergen(L, g);
1355 } 1382 }
1356 } 1383 }
@@ -1367,50 +1394,19 @@ static void fullgen (lua_State *L, global_State *g) {
1367 1394
1368 1395
1369/* 1396/*
1370** Does a major collector up to the atomic phase and then either 1397** After an atomic incremental step from a major collection,
1371** returns to minor collections or stays doing major ones. If the 1398** check whether collector could return to minor collections.
1372** number of objects collected this time (numobjs - marked) is more than
1373** half the number of objects created since the last major collection
1374** (numobjs - lastmajor), it goes back to minor collections.
1375*/ 1399*/
1376static void genmajorstep (lua_State *L, global_State *g) { 1400static int checkmajorminor (lua_State *L, global_State *g) {
1377 l_obj lastmajor = g->GClastmajor; /* count from last collection */ 1401 if (g->gckind == KGC_GENMAJOR) {
1378 l_obj numobjs = gettotalobjs(g); /* current count */ 1402 l_obj numobjs = gettotalobjs(g); /* current count */
1379 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1403 if (g->marked < numobjs - (numobjs >> 2)) { /* ?? */
1380 atomic(L); /* mark everybody */ 1404 atomic2gen(L, g); /* return to generational mode */
1381 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) { 1405 setminordebt(g);
1382 atomic2gen(L, g); /* return to generational mode */ 1406 return 0; /* exit incremental collection */
1383 setminordebt(g); 1407 }
1384 }
1385 else { /* bad collection; stay in major mode */
1386 entersweep(L);
1387 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1388 setpause(g);
1389 g->GClastmajor = gettotalobjs(g);
1390 }
1391}
1392
1393
1394/*
1395** Does a generational "step". If the total number of objects grew
1396** more than 'majormul'% since the last major collection, does a
1397** major collection. Otherwise, does a minor collection.
1398*/
1399static void genstep (lua_State *L, global_State *g) {
1400 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1401 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1402 if (gettotalobjs(g) > majorbase + majorinc) {
1403 /* do a major collection */
1404 enterinc(g);
1405 g->gckind = KGC_GENMAJOR;
1406 genmajorstep(L, g);
1407 }
1408 else { /* regular case; do a minor collection */
1409 g->marked = 0;
1410 youngcollection(L, g);
1411 setminordebt(g);
1412 lua_assert(g->GClastmajor == majorbase);
1413 } 1408 }
1409 return 1; /* stay doing incremental collections */
1414} 1410}
1415 1411
1416/* }====================================================== */ 1412/* }====================================================== */
@@ -1548,7 +1544,8 @@ static l_obj singlestep (lua_State *L) {
1548 } 1544 }
1549 case GCSenteratomic: { 1545 case GCSenteratomic: {
1550 work = atomic(L); 1546 work = atomic(L);
1551 entersweep(L); 1547 if (checkmajorminor(L, g))
1548 entersweep(L);
1552 break; 1549 break;
1553 } 1550 }
1554 case GCSswpallgc: { /* sweep "regular" objects */ 1551 case GCSswpallgc: { /* sweep "regular" objects */
@@ -1597,6 +1594,7 @@ static l_obj singlestep (lua_State *L) {
1597*/ 1594*/
1598void luaC_runtilstate (lua_State *L, int statesmask) { 1595void luaC_runtilstate (lua_State *L, int statesmask) {
1599 global_State *g = G(L); 1596 global_State *g = G(L);
1597 lua_assert(g->gckind == KGC_INC);
1600 while (!testbit(statesmask, g->gcstate)) 1598 while (!testbit(statesmask, g->gcstate))
1601 singlestep(L); 1599 singlestep(L);
1602} 1600}
@@ -1615,13 +1613,14 @@ static void incstep (lua_State *L, global_State *g) {
1615 l_obj work2do = applygcparam(g, gcstepmul, stepsize); 1613 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1616 do { /* repeat until pause or enough "credit" (negative debt) */ 1614 do { /* repeat until pause or enough "credit" (negative debt) */
1617 l_obj work = singlestep(L); /* perform one single step */ 1615 l_obj work = singlestep(L); /* perform one single step */
1616 if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */
1617 return; /* nothing else to be done here */
1618 work2do -= work; 1618 work2do -= work;
1619 } while (work2do > 0 && g->gcstate != GCSpause); 1619 } while (work2do > 0 && g->gcstate != GCSpause);
1620 if (g->gcstate == GCSpause) 1620 if (g->gcstate == GCSpause)
1621 setpause(g); /* pause until next cycle */ 1621 setpause(g); /* pause until next cycle */
1622 else { 1622 else
1623 luaE_setdebt(g, stepsize); 1623 luaE_setdebt(g, stepsize);
1624 }
1625} 1624}
1626 1625
1627/* 1626/*
@@ -1635,17 +1634,18 @@ void luaC_step (lua_State *L) {
1635 if (!gcrunning(g)) /* not running? */ 1634 if (!gcrunning(g)) /* not running? */
1636 luaE_setdebt(g, 2000); 1635 luaE_setdebt(g, 2000);
1637 else { 1636 else {
1637//printf("> step: %d %d %ld %ld -> ", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
1638
1638 switch (g->gckind) { 1639 switch (g->gckind) {
1639 case KGC_INC: 1640 case KGC_INC: case KGC_GENMAJOR:
1640 incstep(L, g); 1641 incstep(L, g);
1641 break; 1642 break;
1642 case KGC_GEN: 1643 case KGC_GENMINOR:
1643 genstep(L, g); 1644 youngcollection(L, g);
1644 break; 1645 setminordebt(g);
1645 case KGC_GENMAJOR:
1646 genmajorstep(L, g);
1647 break; 1646 break;
1648 } 1647 }
1648//printf("%d %d %ld %ld\n", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
1649 } 1649 }
1650} 1650}
1651 1651
@@ -1681,10 +1681,15 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1681 global_State *g = G(L); 1681 global_State *g = G(L);
1682 lua_assert(!g->gcemergency); 1682 lua_assert(!g->gcemergency);
1683 g->gcemergency = isemergency; /* set flag */ 1683 g->gcemergency = isemergency; /* set flag */
1684 if (g->gckind == KGC_GEN) 1684 switch (g->gckind) {
1685 fullgen(L, g); 1685 case KGC_GENMINOR: fullgen(L, g); break;
1686 else 1686 case KGC_INC: fullinc(L, g); break;
1687 fullinc(L, g); 1687 case KGC_GENMAJOR:
1688 g->gckind = KGC_INC;
1689 fullinc(L, g);
1690 g->gckind = KGC_GENMAJOR;
1691 break;
1692 }
1688 g->gcemergency = 0; 1693 g->gcemergency = 0;
1689} 1694}
1690 1695