/* ** if object 'o' has a finalizer, remove it from 'allgc' list (must ** search the list to find it) and link it in 'finobj' list. */ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { global_State *g = G(L); if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ isfinalized(o) || /* ... or is finalized... */ gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ return; /* nothing to be done */ else { /* move 'o' to 'finobj' list */ GCObject **p; GCheader *ho = gch(o); if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ lua_assert(issweepphase(g)); g->sweepgc = sweeptolive(L, g->sweepgc, NULL); } /* search for pointer pointing to 'o' */ for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } *p = ho->next; /* remove 'o' from root list */ ho->next = g->finobj; /* link it in list 'finobj' */ g->finobj = o; l_setbit(ho->marked, SEPARATED); /* mark it as such */ if (!keepinvariantout(g)) /* not keeping invariant? */ makewhite(g, o); /* "sweep" object */ else resetoldbit(o); /* see MOVE OLD rule */ } }
/* ** barrier that moves collector forward, that is, mark the white object ** being pointed by a black object. (If in sweep phase, clear the black ** object to white [sweep it] to avoid other barrier calls for this ** same object.) */ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); if (keepinvariant(g)) /* must keep invariant? */ reallymarkobject(g, v); /* restore invariant */ else { /* sweep phase */ lua_assert(issweepphase(g)); makewhite(g, o); /* mark main obj. as white to avoid other barriers */ } }
static GCObject *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ lua_assert(tofinalize(o)); g->tobefnz = o->next; /* remove it from 'tobefnz' list */ o->next = g->allgc; /* return it to 'allgc' list */ g->allgc = o; resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ if (issweepphase(g)) makewhite(g, o); /* "sweep" object */ return o; }
/* ** barrier that moves collector forward, that is, mark the white object ** being pointed by a black object. */ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); lua_assert(isgenerational(g) || g->gcstate != GCSpause); lua_assert(gch(o)->tt != LUA_TTABLE); if (keepinvariant(g)) /* must keep invariant? */ reallymarkobject(g, v); /* restore invariant */ else { /* sweep phase */ lua_assert(issweepphase(g)); makewhite(g, o); /* mark main obj. as white to avoid other barriers */ } }
/* ** check color (and invariants) for an upvalue that was closed, ** i.e., moved into the 'allgc' list */ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { GCObject *o = obj2gco(uv); lua_assert(!isblack(o)); /* open upvalues are never black */ if (isgray(o)) { if (keepinvariant(g)) { resetoldbit(o); /* see MOVE OLD rule */ gray2black(o); /* it is being visited now */ markvalue(g, uv->v); } else { lua_assert(issweepphase(g)); makewhite(g, o); } } }
/* ** if object 'o' has a finalizer, remove it from 'allgc' list (must ** search the list to find it) and link it in 'finobj' list. */ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { global_State *g = G(L); if (tofinalize(o) || /* obj. is already marked... */ gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ return; /* nothing to be done */ else { /* move 'o' to 'finobj' list */ GCObject **p; if (issweepphase(g)) { makewhite(g, o); /* "sweep" object 'o' */ if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ } /* search for pointer pointing to 'o' */ for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } *p = o->next; /* remove 'o' from 'allgc' list */ o->next = g->finobj; /* link it in 'finobj' list */ g->finobj = o; l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ } }