aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c67
1 files changed, 44 insertions, 23 deletions
diff --git a/lgc.c b/lgc.c
index ecd142cb..114b32d3 100644
--- a/lgc.c
+++ b/lgc.c
@@ -93,6 +93,7 @@
93*/ 93*/
94#define markobjectN(g,t) { if (t) markobject(g,t); } 94#define markobjectN(g,t) { if (t) markobject(g,t); }
95 95
96
96static void reallymarkobject (global_State *g, GCObject *o); 97static void reallymarkobject (global_State *g, GCObject *o);
97static l_obj atomic (lua_State *L); 98static l_obj atomic (lua_State *L);
98static void entersweep (lua_State *L); 99static void entersweep (lua_State *L);
@@ -831,10 +832,10 @@ static void freeobj (lua_State *L, GCObject *o) {
831** for next collection cycle. Return where to continue the traversal or 832** for next collection cycle. Return where to continue the traversal or
832** NULL if list is finished. 833** NULL if list is finished.
833*/ 834*/
834static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) { 835static GCObject **sweeplist (lua_State *L, GCObject **p, l_obj countin) {
835 global_State *g = G(L); 836 global_State *g = G(L);
836 int ow = otherwhite(g); 837 int ow = otherwhite(g);
837 int i; 838 l_obj i;
838 int white = luaC_white(g); /* current white */ 839 int white = luaC_white(g); /* current white */
839 for (i = 0; *p != NULL && i < countin; i++) { 840 for (i = 0; *p != NULL && i < countin; i++) {
840 GCObject *curr = *p; 841 GCObject *curr = *p;
@@ -1357,8 +1358,8 @@ static void setminordebt (global_State *g) {
1357** collection. 1358** collection.
1358*/ 1359*/
1359static void entergen (lua_State *L, global_State *g) { 1360static void entergen (lua_State *L, global_State *g) {
1360 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1361 luaC_runtilstate(L, GCSpause, 1); /* prepare to start a new cycle */
1361 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1362 luaC_runtilstate(L, GCSpropagate, 1); /* start new cycle */
1362 atomic(L); /* propagates all and then do the atomic stuff */ 1363 atomic(L); /* propagates all and then do the atomic stuff */
1363 atomic2gen(L, g); 1364 atomic2gen(L, g);
1364 setminordebt(g); /* set debt assuming next cycle will be minor */ 1365 setminordebt(g); /* set debt assuming next cycle will be minor */
@@ -1515,10 +1516,14 @@ static l_obj atomic (lua_State *L) {
1515} 1516}
1516 1517
1517 1518
1519/*
1520** Do a sweep step. The normal case (not fast) sweeps at most GCSWEEPMAX
1521** elements. The fast case sweeps the whole list.
1522*/
1518static void sweepstep (lua_State *L, global_State *g, 1523static void sweepstep (lua_State *L, global_State *g,
1519 int nextstate, GCObject **nextlist) { 1524 int nextstate, GCObject **nextlist, int fast) {
1520 if (g->sweepgc) 1525 if (g->sweepgc)
1521 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); 1526 g->sweepgc = sweeplist(L, g->sweepgc, fast ? MAX_LOBJ : GCSWEEPMAX);
1522 else { /* enter next state */ 1527 else { /* enter next state */
1523 g->gcstate = nextstate; 1528 g->gcstate = nextstate;
1524 g->sweepgc = nextlist; 1529 g->sweepgc = nextlist;
@@ -1526,7 +1531,19 @@ static void sweepstep (lua_State *L, global_State *g,
1526} 1531}
1527 1532
1528 1533
1529static l_obj singlestep (lua_State *L) { 1534/*
1535** Performs one incremental "step" in an incremental garbage collection.
1536** For indivisible work, a step goes to the next state. When marking
1537** (propagating), a step traverses one object. When sweeping, a step
1538** sweeps GCSWEEPMAX objects, to avoid a big overhead for sweeping
1539** objects one by one. (Sweeping is inexpensive, no matter the
1540** object.) When 'fast' is true, 'singlestep' tries to finish a state
1541** "as fast as possible". In particular, it skips the propagation
1542** phase and leaves all objects to be traversed by the atomic phase:
1543** That avoids traversing twice some objects, such as theads and
1544** weak tables.
1545*/
1546static l_obj singlestep (lua_State *L, int fast) {
1530 global_State *g = G(L); 1547 global_State *g = G(L);
1531 l_obj work; 1548 l_obj work;
1532 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1549 lua_assert(!g->gcstopem); /* collector is not reentrant */
@@ -1539,7 +1556,7 @@ static l_obj singlestep (lua_State *L) {
1539 break; 1556 break;
1540 } 1557 }
1541 case GCSpropagate: { 1558 case GCSpropagate: {
1542 if (g->gray == NULL) { /* no more gray objects? */ 1559 if (fast || g->gray == NULL) {
1543 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1560 g->gcstate = GCSenteratomic; /* finish propagate phase */
1544 work = 0; 1561 work = 0;
1545 } 1562 }
@@ -1556,17 +1573,17 @@ static l_obj singlestep (lua_State *L) {
1556 break; 1573 break;
1557 } 1574 }
1558 case GCSswpallgc: { /* sweep "regular" objects */ 1575 case GCSswpallgc: { /* sweep "regular" objects */
1559 sweepstep(L, g, GCSswpfinobj, &g->finobj); 1576 sweepstep(L, g, GCSswpfinobj, &g->finobj, fast);
1560 work = GCSWEEPMAX; 1577 work = GCSWEEPMAX;
1561 break; 1578 break;
1562 } 1579 }
1563 case GCSswpfinobj: { /* sweep objects with finalizers */ 1580 case GCSswpfinobj: { /* sweep objects with finalizers */
1564 sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1581 sweepstep(L, g, GCSswptobefnz, &g->tobefnz, fast);
1565 work = GCSWEEPMAX; 1582 work = GCSWEEPMAX;
1566 break; 1583 break;
1567 } 1584 }
1568 case GCSswptobefnz: { /* sweep objects to be finalized */ 1585 case GCSswptobefnz: { /* sweep objects to be finalized */
1569 sweepstep(L, g, GCSswpend, NULL); 1586 sweepstep(L, g, GCSswpend, NULL, fast);
1570 work = GCSWEEPMAX; 1587 work = GCSWEEPMAX;
1571 break; 1588 break;
1572 } 1589 }
@@ -1596,14 +1613,15 @@ static l_obj singlestep (lua_State *L) {
1596 1613
1597 1614
1598/* 1615/*
1599** advances the garbage collector until it reaches a state allowed 1616** Advances the garbage collector until it reaches the given state.
1600** by 'statemask' 1617** (The option 'fast' is only for testing; in normal code, 'fast'
1618** here is always true.)
1601*/ 1619*/
1602void luaC_runtilstate (lua_State *L, int statesmask) { 1620void luaC_runtilstate (lua_State *L, int state, int fast) {
1603 global_State *g = G(L); 1621 global_State *g = G(L);
1604 lua_assert(g->gckind == KGC_INC); 1622 lua_assert(g->gckind == KGC_INC);
1605 while (!testbit(statesmask, g->gcstate)) 1623 while (state != g->gcstate)
1606 singlestep(L); 1624 singlestep(L, fast);
1607} 1625}
1608 1626
1609 1627
@@ -1618,8 +1636,13 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1618static void incstep (lua_State *L, global_State *g) { 1636static void incstep (lua_State *L, global_State *g) {
1619 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1637 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1620 l_obj work2do = applygcparam(g, gcstepmul, stepsize); 1638 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1621 do { /* repeat until pause or enough "credit" (negative debt) */ 1639 int fast = 0;
1622 l_obj work = singlestep(L); /* perform one single step */ 1640 if (work2do == 0) { /* special case: do a full collection */
1641 work2do = MAX_LOBJ; /* do unlimited work */
1642 fast = 1;
1643 }
1644 do { /* repeat until pause or enough work */
1645 l_obj work = singlestep(L, fast); /* perform one single step */
1623 if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */ 1646 if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */
1624 return; /* nothing else to be done here */ 1647 return; /* nothing else to be done here */
1625 work2do -= work; 1648 work2do -= work;
@@ -1665,13 +1688,11 @@ static void fullinc (lua_State *L, global_State *g) {
1665 if (keepinvariant(g)) /* black objects? */ 1688 if (keepinvariant(g)) /* black objects? */
1666 entersweep(L); /* sweep everything to turn them back to white */ 1689 entersweep(L); /* sweep everything to turn them back to white */
1667 /* finish any pending sweep phase to start a new cycle */ 1690 /* finish any pending sweep phase to start a new cycle */
1668 luaC_runtilstate(L, bitmask(GCSpause)); 1691 luaC_runtilstate(L, GCSpause, 1);
1669 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1692 luaC_runtilstate(L, GCScallfin, 1); /* run up to finalizers */
1670 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */
1671 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1672 /* 'marked' must be correct after a full GC cycle */ 1693 /* 'marked' must be correct after a full GC cycle */
1673 lua_assert(g->marked == gettotalobjs(g)); 1694 lua_assert(g->marked == gettotalobjs(g));
1674 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1695 luaC_runtilstate(L, GCSpause, 1); /* finish collection */
1675 setpause(g); 1696 setpause(g);
1676} 1697}
1677 1698