46#define GCFINALIZECOST 50
53#define WORK2MEM sizeof(TValue)
64#define maskcolors (bitmask(BLACKBIT) | WHITEBITS)
67#define maskgcbits (maskcolors | AGEBITS)
71#define makewhite(g,x) \
72 (x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g)))
75#define set2gray(x) resetbits(x->marked, maskcolors)
80 (x->marked = cast_byte((x->marked & ~WHITEBITS) | bitmask(BLACKBIT)))
83#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
85#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
91#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
94#define markvalue(g,o) { checkliveness(g->mainthread,o); \
95 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
97#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
99#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
105#define markobjectN(g,t) { if (t) markobject(g,t); }
122#define gnodelast(h) gnode(h, cast_sizet(sizenode(h)))
127 case LUA_VTABLE:
return &gco2t(o)->gclist;
128 case LUA_VLCL:
return &gco2lcl(o)->gclist;
129 case LUA_VCCL:
return &gco2ccl(o)->gclist;
130 case LUA_VTHREAD:
return &gco2th(o)->gclist;
131 case LUA_VPROTO:
return &gco2p(o)->gclist;
132 case LUA_VUSERDATA: {
134 lua_assert(u->nuvalue > 0);
137 default: lua_assert(0);
return 0;
146#define linkgclist(o,p) linkgclist_(obj2gco(o), &(o)->gclist, &(p))
149 lua_assert(!isgray(o));
159#define linkobjgclist(o,p) linkgclist_(obj2gco(o), getgclist(o), &(p))
171static void clearkey (
Node *n) {
172 lua_assert(isempty(gval(n)));
173 if (keyiscollectable(n))
186 if (o == NULL)
return 0;
187 else if (novariant(o->tt) == LUA_TSTRING) {
191 else return iswhite(o);
210 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
211 if (keepinvariant(g)) {
212 reallymarkobject(g, v);
214 lua_assert(!isold(v));
219 lua_assert(issweepphase(g));
220 if (g->gckind == KGC_INC)
232 lua_assert(isblack(o) && !isdead(g, o));
233 lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1));
234 if (getage(o) == G_TOUCHED2)
237 linkobjgclist(o, g->grayagain);
239 setage(o, G_TOUCHED1);
245 lua_assert(g->allgc == o);
249 o->next = g->fixedgc;
260 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));
262 o->marked = luaC_white(g);
271 return luaC_newobjdt(L, tt, sz, 0);
305 UpVal *uv = gco2upv(o);
310 markvalue(g, uv->v.p);
313 case LUA_VUSERDATA: {
315 if (u->nuvalue == 0) {
316 markobjectN(g, u->metatable);
322 case LUA_VLCL:
case LUA_VCCL:
case LUA_VTABLE:
323 case LUA_VTHREAD:
case LUA_VPROTO: {
324 linkobjgclist(o, g->gray);
327 default: lua_assert(0);
break;
337 for (i=0; i < LUA_NUMTAGS; i++)
338 markobjectN(g, g->mt[i]);
348 for (o = g->tobefnz; o != NULL; o = o->next) {
371 while ((thread = *p) != NULL) {
373 if (!iswhite(thread) && thread->openupval != NULL)
377 lua_assert(!isold(thread) || thread->openupval == NULL);
379 thread->twups = thread;
380 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
381 lua_assert(getage(uv) <= getage(thread));
384 lua_assert(upisopen(uv) && isgray(uv));
385 markvalue(g, uv->v.p);
395 g->gray = g->grayagain = NULL;
396 g->weak = g->allweak = g->ephemeron = NULL;
405 markobject(g, g->mainthread);
406 markvalue(g, &g->l_registry);
431 lua_assert(isblack(o));
432 if (getage(o) == G_TOUCHED1) {
433 linkobjgclist(o, g->grayagain);
435 else if (getage(o) == G_TOUCHED2)
436 changeage(o, G_TOUCHED2, G_OLD);
447 Node *n, *limit = gnodelast(h);
450 int hasclears = (h->alimit > 0);
451 for (n = gnode(h, 0); n < limit; n++) {
452 if (isempty(gval(n)))
455 lua_assert(!keyisnil(n));
457 if (!hasclears && iscleared(g, gcvalueN(gval(n))))
461 if (g->gcstate == GCSatomic && hasclears)
462 linkgclist(h, g->weak);
464 linkgclist(h, g->grayagain);
485 unsigned int asize = luaH_realasize(h);
486 unsigned int nsize = sizenode(h);
488 for (i = 0; i < asize; i++) {
489 if (valiswhite(&h->array[i])) {
491 reallymarkobject(g, gcvalue(&h->array[i]));
496 for (i = 0; i < nsize; i++) {
497 Node *n = inv ? gnode(h, nsize - 1 - i) : gnode(h, i);
498 if (isempty(gval(n)))
500 else if (iscleared(g, gckeyN(n))) {
502 if (valiswhite(gval(n)))
505 else if (valiswhite(gval(n))) {
507 reallymarkobject(g, gcvalue(gval(n)));
511 if (g->gcstate == GCSpropagate)
512 linkgclist(h, g->grayagain);
514 linkgclist(h, g->ephemeron);
516 linkgclist(h, g->allweak);
518 genlink(g, obj2gco(h));
524 Node *n, *limit = gnodelast(h);
526 unsigned int asize = luaH_realasize(h);
527 for (i = 0; i < asize; i++)
528 markvalue(g, &h->array[i]);
529 for (n = gnode(h, 0); n < limit; n++) {
530 if (isempty(gval(n)))
533 lua_assert(!keyisnil(n));
535 markvalue(g, gval(n));
538 genlink(g, obj2gco(h));
543 const char *weakkey, *weakvalue;
544 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
545 markobjectN(g, h->metatable);
546 if (mode && ttisstring(mode) &&
547 (cast_void(weakkey = strchr(svalue(mode),
'k')),
548 cast_void(weakvalue = strchr(svalue(mode),
'v')),
549 (weakkey || weakvalue))) {
551 traverseweakvalue(g, h);
553 traverseephemeron(g, h, 0);
555 linkgclist(h, g->allweak);
558 traversestrongtable(g, h);
559 return 1 + h->alimit + 2 * allocsizenode(h);
565 markobjectN(g, u->metatable);
566 for (i = 0; i < u->nuvalue; i++)
567 markvalue(g, &u->uv[i].uv);
568 genlink(g, obj2gco(u));
569 return 1 + u->nuvalue;
580 markobjectN(g, f->source);
581 for (i = 0; i < f->sizek; i++)
582 markvalue(g, &f->k[i]);
583 for (i = 0; i < f->sizeupvalues; i++)
584 markobjectN(g, f->upvalues[i].name);
585 for (i = 0; i < f->sizep; i++)
586 markobjectN(g, f->p[i]);
587 for (i = 0; i < f->sizelocvars; i++)
588 markobjectN(g, f->locvars[i].varname);
589 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
595 for (i = 0; i < cl->nupvalues; i++)
596 markvalue(g, &cl->upvalue[i]);
597 return 1 + cl->nupvalues;
606 markobjectN(g, cl->p);
607 for (i = 0; i < cl->nupvalues; i++) {
608 UpVal *uv = cl->upvals[i];
611 return 1 + cl->nupvalues;
629 StkId o = th->stack.p;
630 if (isold(th) || g->gcstate == GCSpropagate)
631 linkgclist(th, g->grayagain);
634 lua_assert(g->gcstate == GCSatomic ||
635 th->openupval == NULL || isintwups(th));
636 for (; o < th->top.p; o++)
637 markvalue(g, s2v(o));
638 for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
640 if (g->gcstate == GCSatomic) {
641 for (; o < th->stack_last.p + EXTRA_STACK; o++)
644 if (!isintwups(th) && th->openupval != NULL) {
645 th->twups = g->twups;
649 else if (!g->gcemergency)
650 luaD_shrinkstack(th);
651 return 1 + stacksize(th);
661 g->gray = *getgclist(o);
663 case LUA_VTABLE:
return traversetable(g, gco2t(o));
664 case LUA_VUSERDATA:
return traverseudata(g, gco2u(o));
665 case LUA_VLCL:
return traverseLclosure(g, gco2lcl(o));
666 case LUA_VCCL:
return traverseCclosure(g, gco2ccl(o));
667 case LUA_VPROTO:
return traverseproto(g, gco2p(o));
668 case LUA_VTHREAD:
return traversethread(g, gco2th(o));
669 default: lua_assert(0);
return 0;
677 tot += propagatemark(g);
697 while ((w = next) != NULL) {
701 if (traverseephemeron(g, h, dir)) {
724 for (; l; l = gco2t(l)->gclist) {
726 Node *limit = gnodelast(h);
728 for (n = gnode(h, 0); n < limit; n++) {
729 if (iscleared(g, gckeyN(n)))
731 if (isempty(gval(n)))
743 for (; l != f; l = gco2t(l)->gclist) {
745 Node *n, *limit = gnodelast(h);
747 unsigned int asize = luaH_realasize(h);
748 for (i = 0; i < asize; i++) {
750 if (iscleared(g, gcvalueN(o)))
753 for (n = gnode(h, 0); n < limit; n++) {
754 if (iscleared(g, gcvalueN(gval(n))))
756 if (isempty(gval(n)))
765 luaF_unlinkupval(uv);
773 luaF_freeproto(L, gco2p(o));
776 freeupval(L, gco2upv(o));
780 luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
785 luaM_freemem(L, cl, sizeCclosure(cl->nupvalues));
789 luaH_free(L, gco2t(o));
792 luaE_freethread(L, gco2th(o));
794 case LUA_VUSERDATA: {
796 luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
802 luaM_freemem(L, ts, sizelstring(ts->shrlen));
807 luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
810 default: lua_assert(0);
825 int ow = otherwhite(g);
827 int white = luaC_white(g);
828 for (i = 0; *p != NULL && i < countin; i++) {
830 int marked = curr->marked;
831 if (isdeadm(ow, marked)) {
836 curr->marked = cast_byte((marked & ~maskgcbits) | white);
842 return (*p == NULL) ? NULL : p;
852 p = sweeplist(L, p, 1, NULL);
870 if (!g->gcemergency) {
871 if (g->strt.nuse < g->strt.size / 4) {
872 l_mem olddebt = g->GCdebt;
873 luaS_resize(L, g->strt.size / 2);
874 g->GCestimate += g->GCdebt - olddebt;
886 lua_assert(tofinalize(o));
887 g->tobefnz = o->next;
890 resetbit(o->marked, FINALIZEDBIT);
893 else if (getage(o) == G_OLD1)
899static void dothecall (
lua_State *L,
void *ud) {
901 luaD_callnoyield(L, L->top.p - 2, 0);
909 lua_assert(!g->gcemergency);
910 setgcovalue(L, &v, udata2finalize(g));
911 tm = luaT_gettmbyobj(L, &v, TM_GC);
914 lu_byte oldah = L->allowhook;
915 int oldgcstp = g->gcstp;
918 setobj2s(L, L->top.p++, tm);
919 setobj2s(L, L->top.p++, &v);
920 L->ci->callstatus |= CIST_FIN;
921 status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0);
922 L->ci->callstatus &= ~CIST_FIN;
923 L->allowhook = oldah;
925 if (l_unlikely(status != LUA_OK)) {
926 luaE_warnerror(L,
"__gc");
936static int runafewfinalizers (
lua_State *L,
int n) {
939 for (i = 0; i < n && g->tobefnz; i++)
948static void callallpendingfinalizers (
lua_State *L) {
975 GCObject **lastnext = findlast(&g->tobefnz);
976 while ((curr = *p) != g->finobjold1) {
977 lua_assert(tofinalize(curr));
978 if (!(iswhite(curr) || all))
981 if (curr == g->finobjsur)
982 g->finobjsur = curr->next;
984 curr->next = *lastnext;
986 lastnext = &curr->next;
1006 checkpointer(&g->survival, o);
1007 checkpointer(&g->old1, o);
1008 checkpointer(&g->reallyold, o);
1009 checkpointer(&g->firstold1, o);
1019 if (tofinalize(o) ||
1020 gfasttm(g, mt, TM_GC) == NULL ||
1021 (g->gcstp & GCSTPCLS))
1025 if (issweepphase(g)) {
1027 if (g->sweepgc == &o->next)
1028 g->sweepgc = sweeptolive(L, g->sweepgc);
1031 correctpointers(g, o);
1033 for (p = &g->allgc; *p != o; p = &(*p)->next) { }
1035 o->next = g->finobj;
1037 l_setbit(o->marked, FINALIZEDBIT);
1058 l_mem threshold, debt;
1059 int pause = getgcparam(g->gcpause);
1060 l_mem estimate = g->GCestimate / PAUSEADJ;
1061 lua_assert(estimate > 0);
1062 threshold = (pause < MAX_LMEM / estimate)
1065 debt = gettotalbytes(g) - threshold;
1066 if (debt > 0) debt = 0;
1067 luaE_setdebt(g, debt);
1080 while ((curr = *p) != NULL) {
1081 if (iswhite(curr)) {
1082 lua_assert(isdead(g, curr));
1087 setage(curr, G_OLD);
1088 if (curr->tt == LUA_VTHREAD) {
1090 linkgclist(th, g->grayagain);
1092 else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr)))
1115 static const lu_byte nextage[] = {
1124 int white = luaC_white(g);
1126 while ((curr = *p) != limit) {
1127 if (iswhite(curr)) {
1128 lua_assert(!isold(curr) && isdead(g, curr));
1133 if (getage(curr) == G_NEW) {
1134 int marked = curr->marked & ~maskgcbits;
1135 curr->marked = cast_byte(marked | G_SURVIVAL | white);
1138 setage(curr, nextage[getage(curr)]);
1139 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL)
1155 int white = luaC_white(g);
1156 for (; p != NULL; p = p->next)
1157 p->marked = cast_byte((p->marked & ~maskgcbits) | white);
1172 while ((curr = *p) != NULL) {
1176 else if (getage(curr) == G_TOUCHED1) {
1177 lua_assert(isgray(curr));
1179 changeage(curr, G_TOUCHED1, G_TOUCHED2);
1182 else if (curr->tt == LUA_VTHREAD) {
1183 lua_assert(isgray(curr));
1187 lua_assert(isold(curr));
1188 if (getage(curr) == G_TOUCHED2)
1189 changeage(curr, G_TOUCHED2, G_OLD);
1193 remove: *p = *next;
continue;
1194 remain: p = next;
continue;
1204 GCObject **list = correctgraylist(&g->grayagain);
1205 *list = g->weak; g->weak = NULL;
1206 list = correctgraylist(list);
1207 *list = g->allweak; g->allweak = NULL;
1208 list = correctgraylist(list);
1209 *list = g->ephemeron; g->ephemeron = NULL;
1210 correctgraylist(list);
1221 for (p = from; p != to; p = p->next) {
1222 if (getage(p) == G_OLD1) {
1223 lua_assert(!iswhite(p));
1224 changeage(p, G_OLD1, G_OLD);
1226 reallymarkobject(g, p);
1236 correctgraylists(g);
1238 g->gcstate = GCSpropagate;
1239 if (!g->gcemergency)
1240 callallpendingfinalizers(L);
1252 lua_assert(g->gcstate == GCSpropagate);
1254 markold(g, g->firstold1, g->reallyold);
1255 g->firstold1 = NULL;
1257 markold(g, g->finobj, g->finobjrold);
1258 markold(g, g->tobefnz, NULL);
1262 g->gcstate = GCSswpallgc;
1263 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1);
1265 sweepgen(L, g, psurvival, g->old1, &g->firstold1);
1266 g->reallyold = g->old1;
1267 g->old1 = *psurvival;
1268 g->survival = g->allgc;
1272 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy);
1274 sweepgen(L, g, psurvival, g->finobjold1, &dummy);
1275 g->finobjrold = g->finobjold1;
1276 g->finobjold1 = *psurvival;
1277 g->finobjsur = g->finobj;
1279 sweepgen(L, g, &g->tobefnz, NULL, &dummy);
1280 finishgencycle(L, g);
1293 g->gcstate = GCSswpallgc;
1294 sweep2old(L, &g->allgc);
1296 g->reallyold = g->old1 = g->survival = g->allgc;
1297 g->firstold1 = NULL;
1300 sweep2old(L, &g->finobj);
1301 g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj;
1303 sweep2old(L, &g->tobefnz);
1305 g->gckind = KGC_GEN;
1307 g->GCestimate = gettotalbytes(g);
1308 finishgencycle(L, g);
1317 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul));
1329 luaC_runtilstate(L, bitmask(GCSpause));
1330 luaC_runtilstate(L, bitmask(GCSpropagate));
1331 numobjs = atomic(L);
1344 whitelist(g, g->allgc);
1345 g->reallyold = g->old1 = g->survival = NULL;
1346 whitelist(g, g->finobj);
1347 whitelist(g, g->tobefnz);
1348 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1349 g->gcstate = GCSpause;
1350 g->gckind = KGC_INC;
1358void luaC_changemode (
lua_State *L,
int newmode) {
1360 if (newmode != g->gckind) {
1361 if (newmode == KGC_GEN)
1375 return entergen(L, g);
1402 lu_mem lastatomic = g->lastatomic;
1403 if (g->gckind == KGC_GEN)
1405 luaC_runtilstate(L, bitmask(GCSpropagate));
1406 newatomic = atomic(L);
1407 if (newatomic < lastatomic + (lastatomic >> 3)) {
1412 g->GCestimate = gettotalbytes(g); ;
1414 luaC_runtilstate(L, bitmask(GCSpause));
1416 g->lastatomic = newatomic;
1441 if (g->lastatomic != 0)
1444 lu_mem majorbase = g->GCestimate;
1445 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul);
1446 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) {
1447 lu_mem numobjs = fullgen(L, g);
1448 if (gettotalbytes(g) < majorbase + (majorinc / 2)) {
1451 lua_assert(g->lastatomic == 0);
1454 g->lastatomic = numobjs;
1459 youngcollection(L, g);
1461 g->GCestimate = majorbase;
1464 lua_assert(isdecGCmodegen(g));
1486 g->gcstate = GCSswpallgc;
1487 lua_assert(g->sweepgc == NULL);
1488 g->sweepgc = sweeptolive(L, &g->allgc);
1497 while (p != limit) {
1509void luaC_freeallobjects (
lua_State *L) {
1511 g->gcstp = GCSTPCLS;
1512 luaC_changemode(L, KGC_INC);
1513 separatetobefnz(g, 1);
1514 lua_assert(g->finobj == NULL);
1515 callallpendingfinalizers(L);
1516 deletelist(L, g->allgc, obj2gco(g->mainthread));
1517 lua_assert(g->finobj == NULL);
1518 deletelist(L, g->fixedgc, NULL);
1519 lua_assert(g->strt.nuse == 0);
1527 GCObject *grayagain = g->grayagain;
1528 g->grayagain = NULL;
1529 lua_assert(g->ephemeron == NULL && g->weak == NULL);
1530 lua_assert(!iswhite(g->mainthread));
1531 g->gcstate = GCSatomic;
1534 markvalue(g, &g->l_registry);
1536 work += propagateall(g);
1538 work += remarkupvals(g);
1539 work += propagateall(g);
1540 g->gray = grayagain;
1541 work += propagateall(g);
1542 convergeephemerons(g);
1545 clearbyvalues(g, g->weak, NULL);
1546 clearbyvalues(g, g->allweak, NULL);
1547 origweak = g->weak; origall = g->allweak;
1548 separatetobefnz(g, 0);
1549 work += markbeingfnz(g);
1550 work += propagateall(g);
1551 convergeephemerons(g);
1554 clearbykeys(g, g->ephemeron);
1555 clearbykeys(g, g->allweak);
1557 clearbyvalues(g, g->weak, origweak);
1558 clearbyvalues(g, g->allweak, origall);
1560 g->currentwhite = cast_byte(otherwhite(g));
1561 lua_assert(g->gray == NULL);
1567 int nextstate,
GCObject **nextlist) {
1569 l_mem olddebt = g->GCdebt;
1571 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);
1572 g->GCestimate += g->GCdebt - olddebt;
1576 g->gcstate = nextstate;
1577 g->sweepgc = nextlist;
1583static lu_mem singlestep (
lua_State *L) {
1586 lua_assert(!g->gcstopem);
1588 switch (g->gcstate) {
1590 restartcollection(g);
1591 g->gcstate = GCSpropagate;
1595 case GCSpropagate: {
1596 if (g->gray == NULL) {
1597 g->gcstate = GCSenteratomic;
1601 work = propagatemark(g);
1604 case GCSenteratomic: {
1607 g->GCestimate = gettotalbytes(g); ;
1611 work = sweepstep(L, g, GCSswpfinobj, &g->finobj);
1614 case GCSswpfinobj: {
1615 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1618 case GCSswptobefnz: {
1619 work = sweepstep(L, g, GCSswpend, NULL);
1624 g->gcstate = GCScallfin;
1629 if (g->tobefnz && !g->gcemergency) {
1631 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST;
1634 g->gcstate = GCSpause;
1639 default: lua_assert(0);
return 0;
1650void luaC_runtilstate (
lua_State *L,
int statesmask) {
1652 while (!testbit(statesmask, g->gcstate))
1666 int stepmul = (getgcparam(g->gcstepmul) | 1);
1667 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul;
1668 l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))
1669 ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul
1672 lu_mem work = singlestep(L);
1674 }
while (debt > -stepsize && g->gcstate != GCSpause);
1675 if (g->gcstate == GCSpause)
1678 debt = (debt / stepmul) * WORK2MEM;
1679 luaE_setdebt(g, debt);
1691 luaE_setdebt(g, -2000);
1693 if(isdecGCmodegen(g))
1709 if (keepinvariant(g))
1712 luaC_runtilstate(L, bitmask(GCSpause));
1713 luaC_runtilstate(L, bitmask(GCScallfin));
1715 lua_assert(g->GCestimate == gettotalbytes(g));
1716 luaC_runtilstate(L, bitmask(GCSpause));
1726void luaC_fullgc (
lua_State *L,
int isemergency) {
1728 lua_assert(!g->gcemergency);
1729 g->gcemergency = isemergency;
1730 if (g->gckind == KGC_INC)