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 */ } }
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 */ } }
static void do1gcTM (lua_State *L, Udata *udata) { const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { setobj2s(L->top, tm); setuvalue(L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); } }
LUA_API void lua_newuserdatabox (lua_State *L, void *ptr) { Udata *u; lua_lock(L); u = luaS_newudata(L, 4); u->uv.len = 4; // user data box bit is set. *(void**)(u + 1) = ptr; setuvalue(L->top, u); api_incr_top(L); lua_unlock(L); }
void lua_unsafe_pushuserdata(lua_State *L, void *v) { assert(v != NULL); Udata *u = ((Udata*)v)-1; lua_lock(L); setuvalue(L, L->top, u); #ifdef AM_LUA51 L->top++; #else api_incr_top(L); #endif lua_unlock(L); }
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 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 */ 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; 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_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); } }