static void GCTM (lua_State *L) { global_State *g = G(L); GCObject *o = g->tmudata->gch.next; /* get first element */ Udata *udata = rawgco2u(o); const TValue *tm; /* remove udata from `tmudata' */ if (o == g->tmudata) /* last element? */ g->tmudata = NULL; else g->tmudata->gch.next = udata->uv.next; udata->uv.next = g->mainthread->next; /* return it to `root' list */ g->mainthread->next = o; makewhite(g, o); tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { lu_byte oldah = L->allowhook; lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); L->allowhook = oldah; /* restore hooks */ g->GCthreshold = oldt; /* restore threshold */ } }
void GCTM (lua_State *L) { #else static void GCTM (lua_State *L) { #endif /* LUA_REFCOUNT */ global_State *g = G(L); GCObject *o = g->tmudata->gch.next; /* get first element */ Udata *udata = rawgco2u(o); const TValue *tm; /* remove udata from `tmudata' */ if (o == g->tmudata) /* last element? */ g->tmudata = NULL; else g->tmudata->gch.next = udata->uv.next; #if LUA_REFCOUNT udata->uv.prev = (GCObject*)&G(L)->mainthread->next; #endif /* LUA_REFCOUNT */ udata->uv.next = g->mainthread->next; /* return it to `root' list */ #if LUA_REFCOUNT if (udata->uv.next) udata->uv.next->uv.prev = obj2gco(udata); #endif /* LUA_REFCOUNT */ g->mainthread->next = o; makewhite(g, o); tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { lu_byte oldah = L->allowhook; lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ #if LUA_REFCOUNT /* We could be in the middle of a stack set, so call the __gc metamethod on one stack level past the current one. */ L->top++; /* we're freeing this object, but fake ref count it, because GCTM actually uses it */ udata->uv.ref++; L->top += 2; setobj2s(L, L->top - 2, tm); setuvalue(L, L->top - 1, udata); luaD_call(L, L->top - 2, 0); udata->uv.ref--; L->top--; setnilvalue2n(L, L->top - 1); #else setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); #endif /* LUA_REFCOUNT */ L->allowhook = oldah; /* restore hooks */ g->GCthreshold = oldt; /* restore threshold */ } }
/* ** mark an object. Userdata, strings, and closed upvalues are visited ** and turned black here. Other objects are marked gray and added ** to appropriate list to be visited (and turned black) later. (Open ** upvalues are already linked in 'headuv' list.) */ static void reallymarkobject (global_State *g, GCObject *o) { reentry: white2gray(o); switch (gch(o)->tt) { case LUA_TSHRSTR: case LUA_TLNGSTR: { gray2black(o); g->GCmemtrav += sizestring(gco2ts(o)); break; } case LUA_TUSERDATA: { TValue uvalue; markobject(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); getuservalue(g->mainthread, rawgco2u(o), &uvalue); if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ o = gcvalue(&uvalue); goto reentry; } break; } case LUA_TLCL: { gco2lcl(o)->gclist = g->gray; g->gray = o; break; } case LUA_TCCL: { gco2ccl(o)->gclist = g->gray; g->gray = o; break; } case LUA_TTABLE: { linktable(gco2t(o), &g->gray); break; } case LUA_TTHREAD: { gco2th(o)->gclist = g->gray; g->gray = o; break; } case LUA_TPROTO: { gco2p(o)->gclist = g->gray; g->gray = o; break; } default: lua_assert(0); break; } }
static void freeobj (lua_State *L, GCObject *o) { global_State *g = G(L); lua_assert(is_robj(o)); switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTHREAD: { lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); luaE_freethread(L, gco2th(o)); break; } case LUA_TSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } case LUA_TUSERDATA: { const Udata *udata = rawgco2u(o); const TValue *tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { lu_byte oldah = L->allowhook; lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); L->allowhook = oldah; /* restore hooks */ g->GCthreshold = oldt; /* restore threshold */ } luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } }
void rstack_reject (lua_State *L, GCObject *src) { RStack *rs = rstack(L); RObject *robj = rstack_getrobj(rs, src); lua_assert(robj && src == robj->body); luaC_link(L, src, src->gch.tt); switch(src->gch.tt) { case LUA_TTABLE: luaH_reject(L, gco2h(src)); break; case LUA_TUSERDATA: luaS_rejectu(L, rawgco2u(src)); break; // TODO: implement default: lua_assert(0); } robj->body = NULL; }