/* ** traverse one gray object, turning it to black (except for threads, ** which are always gray). */ static void propagatemark (global_State *g) { lu_mem size; GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); switch (gch(o)->tt) { case LUA_TTABLE: { Table *h = gco2t(o); g->gray = h->gclist; /* remove from 'gray' list */ size = traversetable(g, h); break; } case LUA_TLCL: { LClosure *cl = gco2lcl(o); g->gray = cl->gclist; /* remove from 'gray' list */ size = traverseLclosure(g, cl); break; } case LUA_TCCL: { CClosure *cl = gco2ccl(o); g->gray = cl->gclist; /* remove from 'gray' list */ size = traverseCclosure(g, cl); break; } case LUA_TTHREAD: { lua_State *th = gco2th(o); g->gray = th->gclist; /* remove from 'gray' list */ th->gclist = g->grayagain; g->grayagain = o; /* insert into 'grayagain' list */ black2gray(o); size = traversestack(g, th); break; } case LUA_TPROTO: { Proto *p = gco2p(o); g->gray = p->gclist; /* remove from 'gray' list */ size = traverseproto(g, p); break; } default: lua_assert(0); return; } g->GCmemtrav += size; }
void luaC_callGCTM (lua_State *L) { lu_byte oldah = L->allowhook; L->allowhook = 0; /* stop debug hooks during GC tag methods */ L->top++; /* reserve space to keep udata while runs its gc method */ #if LUA_REFCOUNT while (G(L)->tmudata_head.next != (GCObject*)&G(L)->tmudata_tail) { GCObject *o = G(L)->tmudata_head.next; Udata *udata = gcotou(o); G(L)->tmudata_head.next = udata->uv.next; /* remove udata from `tmudata' */ udata->uv.prev = (GCObject*)&G(L)->rootudata_head; udata->uv.next = G(L)->rootudata_head.next; if (udata->uv.next) udata->uv.next->uv.prev = o; G(L)->rootudata_head.next = o; #else !LUA_REFCOUNT while (G(L)->tmudata != NULL) { GCObject *o = G(L)->tmudata; Udata *udata = gcotou(o); G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */ udata->uv.next = G(L)->rootudata; /* return it to `root' list */ G(L)->rootudata = o; #endif LUA_REFCOUNT setuvalue(L->top - 1, udata); /* keep a reference to it */ unmark(o); markfinalized(udata); do1gcTM(L, udata); } L->top--; L->allowhook = oldah; /* restore hooks */ } void luaC_sweep (lua_State *L, int all) { if (all) all = 256; /* larger than any mark */ #if LUA_REFCOUNT sweeplist(L, &G(L)->rootudata_head.next, (GCObject*)&G(L)->rootudata_tail, all); #else !LUA_REFCOUNT sweeplist(L, &G(L)->rootudata, NULL, all); #endif LUA_REFCOUNT sweepstrings(L, all); #if LUA_REFCOUNT sweeplist(L, &G(L)->rootgc_head.next, (GCObject*)&G(L)->rootgc_tail, all); #else !LUA_REFCOUNT sweeplist(L, &G(L)->rootgc, NULL, all); #endif LUA_REFCOUNT } /* mark root set */ static void markroot (GCState *st, lua_State *L) { int i; global_State *g = st->g; markobject(st, defaultmeta(L)); for (i = 0; i < LUA_NTYPES; i++) { markobject(st, defaultmetatypes(L, i)); } markobject(st, registry(L)); traversestack(st, g->mainthread); if (L != g->mainthread) /* another thread is running? */ markvalue(st, L); /* cannot collect it */ if (G(L)->userGCFunction) { st->L = g->mainthread; G(L)->userGCFunction(st); } }