diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 11:06:27 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 11:06:27 -0300 |
commit | 666e95a66d1a2ceb98bdf320980b3f655264a9c9 (patch) | |
tree | 663862abbb42c78f6bc31f7975777e60f8340ebe /lgc.c | |
parent | 4eda1acafa1a69224b2d4f786cf1ec8f7a4d9ac5 (diff) | |
download | lua-666e95a66d1a2ceb98bdf320980b3f655264a9c9.tar.gz lua-666e95a66d1a2ceb98bdf320980b3f655264a9c9.tar.bz2 lua-666e95a66d1a2ceb98bdf320980b3f655264a9c9.zip |
Option 0 for step multiplier makes GC non-incremental
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 67 |
1 files changed, 44 insertions, 23 deletions
@@ -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 | |||
96 | static void reallymarkobject (global_State *g, GCObject *o); | 97 | static void reallymarkobject (global_State *g, GCObject *o); |
97 | static l_obj atomic (lua_State *L); | 98 | static l_obj atomic (lua_State *L); |
98 | static void entersweep (lua_State *L); | 99 | static 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 | */ |
834 | static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) { | 835 | static 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 | */ |
1359 | static void entergen (lua_State *L, global_State *g) { | 1360 | static 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 | */ | ||
1518 | static void sweepstep (lua_State *L, global_State *g, | 1523 | static 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 | ||
1529 | static 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 | */ | ||
1546 | static 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 | */ |
1602 | void luaC_runtilstate (lua_State *L, int statesmask) { | 1620 | void 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) { | |||
1618 | static void incstep (lua_State *L, global_State *g) { | 1636 | static 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 | ||