diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 36 |
1 files changed, 24 insertions, 12 deletions
@@ -1575,52 +1575,64 @@ static int sweepstep (lua_State *L, global_State *g, | |||
1575 | 1575 | ||
1576 | static lu_mem singlestep (lua_State *L) { | 1576 | static lu_mem singlestep (lua_State *L) { |
1577 | global_State *g = G(L); | 1577 | global_State *g = G(L); |
1578 | lu_mem work; | ||
1579 | lua_assert(!g->gcstopem); /* collector is not reentrant */ | ||
1580 | g->gcstopem = 1; /* no emergency collections while collecting */ | ||
1578 | switch (g->gcstate) { | 1581 | switch (g->gcstate) { |
1579 | case GCSpause: { | 1582 | case GCSpause: { |
1580 | restartcollection(g); | 1583 | restartcollection(g); |
1581 | g->gcstate = GCSpropagate; | 1584 | g->gcstate = GCSpropagate; |
1582 | return 1; | 1585 | work = 1; |
1586 | break; | ||
1583 | } | 1587 | } |
1584 | case GCSpropagate: { | 1588 | case GCSpropagate: { |
1585 | if (g->gray == NULL) { /* no more gray objects? */ | 1589 | if (g->gray == NULL) { /* no more gray objects? */ |
1586 | g->gcstate = GCSenteratomic; /* finish propagate phase */ | 1590 | g->gcstate = GCSenteratomic; /* finish propagate phase */ |
1587 | return 0; | 1591 | work = 0; |
1588 | } | 1592 | } |
1589 | else | 1593 | else |
1590 | return propagatemark(g); /* traverse one gray object */ | 1594 | work = propagatemark(g); /* traverse one gray object */ |
1595 | break; | ||
1591 | } | 1596 | } |
1592 | case GCSenteratomic: { | 1597 | case GCSenteratomic: { |
1593 | lu_mem work = atomic(L); /* work is what was traversed by 'atomic' */ | 1598 | work = atomic(L); /* work is what was traversed by 'atomic' */ |
1594 | entersweep(L); | 1599 | entersweep(L); |
1595 | g->GCestimate = gettotalbytes(g); /* first estimate */; | 1600 | g->GCestimate = gettotalbytes(g); /* first estimate */; |
1596 | return work; | 1601 | break; |
1597 | } | 1602 | } |
1598 | case GCSswpallgc: { /* sweep "regular" objects */ | 1603 | case GCSswpallgc: { /* sweep "regular" objects */ |
1599 | return sweepstep(L, g, GCSswpfinobj, &g->finobj); | 1604 | work = sweepstep(L, g, GCSswpfinobj, &g->finobj); |
1605 | break; | ||
1600 | } | 1606 | } |
1601 | case GCSswpfinobj: { /* sweep objects with finalizers */ | 1607 | case GCSswpfinobj: { /* sweep objects with finalizers */ |
1602 | return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); | 1608 | work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); |
1609 | break; | ||
1603 | } | 1610 | } |
1604 | case GCSswptobefnz: { /* sweep objects to be finalized */ | 1611 | case GCSswptobefnz: { /* sweep objects to be finalized */ |
1605 | return sweepstep(L, g, GCSswpend, NULL); | 1612 | work = sweepstep(L, g, GCSswpend, NULL); |
1613 | break; | ||
1606 | } | 1614 | } |
1607 | case GCSswpend: { /* finish sweeps */ | 1615 | case GCSswpend: { /* finish sweeps */ |
1608 | checkSizes(L, g); | 1616 | checkSizes(L, g); |
1609 | g->gcstate = GCScallfin; | 1617 | g->gcstate = GCScallfin; |
1610 | return 0; | 1618 | work = 0; |
1619 | break; | ||
1611 | } | 1620 | } |
1612 | case GCScallfin: { /* call remaining finalizers */ | 1621 | case GCScallfin: { /* call remaining finalizers */ |
1613 | if (g->tobefnz && !g->gcemergency) { | 1622 | if (g->tobefnz && !g->gcemergency) { |
1614 | int n = runafewfinalizers(L, GCFINMAX); | 1623 | g->gcstopem = 0; /* ok collections during finalizers */ |
1615 | return n * GCFINALIZECOST; | 1624 | work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; |
1616 | } | 1625 | } |
1617 | else { /* emergency mode or no more finalizers */ | 1626 | else { /* emergency mode or no more finalizers */ |
1618 | g->gcstate = GCSpause; /* finish collection */ | 1627 | g->gcstate = GCSpause; /* finish collection */ |
1619 | return 0; | 1628 | work = 0; |
1620 | } | 1629 | } |
1630 | break; | ||
1621 | } | 1631 | } |
1622 | default: lua_assert(0); return 0; | 1632 | default: lua_assert(0); return 0; |
1623 | } | 1633 | } |
1634 | g->gcstopem = 0; | ||
1635 | return work; | ||
1624 | } | 1636 | } |
1625 | 1637 | ||
1626 | 1638 | ||