static void freeobj (lua_State *L, GCObject *o) { switch (o->tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TLCL: { freeLclosure(L, gco2lcl(o)); break; } case LUA_TCCL: { luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); break; } case LUA_TTABLE: luaH_free(L, gco2t(o)); break; case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: luaS_remove(L, gco2ts(o)); /* remove it from hash table */ luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); break; case LUA_TLNGSTR: { luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; } default: lua_assert(0); } }
static void freeobj (lua_State *L, GCObject *o) { switch (gch(o)->tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TLCL: { luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); break; } case LUA_TCCL: { luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); break; } case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2t(o)); break; case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: G(L)->strt.nuse--; /* go through */ case LUA_TLNGSTR: { luaM_freemem(L, o, sizestring(gco2ts(o))); break; } default: lua_assert(0); } }
LClosure *luaF_newLclosure (lua_State *L, int n) { GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); LClosure *c = gco2lcl(o); c->p = NULL; c->nupvalues = cast_byte(n); while (n--) c->upvals[n] = NULL; return c; }
/* ** 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) { lu_mem size; white2gray(o); switch (gch(o)->tt) { case LUA_TSHRSTR: case LUA_TLNGSTR: { size = sizestring(gco2ts(o)); break; /* nothing else to mark; make it black */ } case LUA_TUSERDATA: { Table *mt = gco2u(o)->metatable; markobject(g, mt); markobject(g, gco2u(o)->env); size = sizeudata(gco2u(o)); break; } case LUA_TUPVAL: { UpVal *uv = gco2uv(o); markvalue(g, uv->v); if (uv->v != &uv->u.value) /* open? */ return; /* open upvalues remain gray */ size = sizeof(UpVal); break; } case LUA_TLCL: { gco2lcl(o)->gclist = g->gray; g->gray = o; return; } case LUA_TCCL: { gco2ccl(o)->gclist = g->gray; g->gray = o; return; } case LUA_TTABLE: { linktable(gco2t(o), &g->gray); return; } case LUA_TTHREAD: { gco2th(o)->gclist = g->gray; g->gray = o; return; } case LUA_TPROTO: { gco2p(o)->gclist = g->gray; g->gray = o; return; } default: lua_assert(0); return; } gray2black(o); g->GCmemtrav += size; }
/* ** 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 (o->tt) { case LUA_TSHRSTR: { gray2black(o); g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); break; } case LUA_TLNGSTR: { gray2black(o); g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); break; } case LUA_TUSERDATA: { TValue uvalue; markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); getuservalue(g->mainthread, gco2u(o), &uvalue); if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ o = gcvalue(&uvalue); goto reentry; } break; } case LUA_TLCL: { linkgclist(gco2lcl(o), g->gray); break; } case LUA_TCCL: { linkgclist(gco2ccl(o), g->gray); break; } case LUA_TTABLE: { linkgclist(gco2t(o), g->gray); break; } case LUA_TTHREAD: { linkgclist(gco2th(o), g->gray); break; } case LUA_TPROTO: { linkgclist(gco2p(o), g->gray); break; } default: lua_assert(0); break; } }
/* ** 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 (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 */ linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ black2gray(o); size = traversethread(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; }