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 (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; case LUA_TTHREAD: { lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); luaE_freethread(L, gcototh(o)); break; } case LUA_TSTRING: { luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); break; } case LUA_TWSTRING: { luaM_free(L, o, sizewstring(gcototws(o)->tsv.len)); break; } case LUA_TUSERDATA: { luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); break; } #if LUA_REFCOUNT case LUA_TNIL: { break; // Do nothing. } #endif LUA_REFCOUNT 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); } }
void lua_close() { TaggedString *alludata = luaS_collectudata(); GCthreshold = MAX_INT; // to avoid GC during GC luaC_hashcallIM((Hash *)roottable.next); // GC t.methods for tables luaC_strcallIM(alludata); // GC tag methods for userdata luaD_gcIM(&luaO_nilobject); // GC tag method for nil (signal end of GC) luaH_free((Hash *)roottable.next); luaF_freeproto((TProtoFunc *)rootproto.next); luaF_freeclosure((Closure *)rootcl.next); luaS_free(alludata); luaS_freeall(); luaM_free(IMtable); luaM_free(refArray); luaM_free(Mbuffer); LState *tmpState, *state; for (state = lua_rootState; state != nullptr;) { tmpState = state->next; lua_statedeinit(state); luaM_free(state); state = tmpState; } Mbuffer = nullptr; IMtable = nullptr; refArray = nullptr; lua_rootState = lua_state = nullptr; #ifdef LUA_DEBUG printf("total de blocos: %ld\n", numblocks); printf("total de memoria: %ld\n", totalmem); #endif }
static void freeobj(lua_State *L, GCObject *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: { luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } }
int32 lua_collectgarbage (int32 limit) { int32 recovered = L->nblocks; /* to subtract nblocks after gc */ Hash *freetable; TaggedString *freestr; TProtoFunc *freefunc; Closure *freeclos; markall(); invalidaterefs(); freestr = luaS_collector(); freetable = (Hash *)listcollect(&(L->roottable)); freefunc = (TProtoFunc *)listcollect(&(L->rootproto)); freeclos = (Closure *)listcollect(&(L->rootcl)); L->GCthreshold *= 4; /* to avoid GC during GC */ luaC_hashcallIM(freetable); /* GC tag methods for tables */ luaC_strcallIM(freestr); /* GC tag methods for userdata */ luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ luaH_free(freetable); luaS_free(freestr); luaF_freeproto(freefunc); luaF_freeclosure(freeclos); recovered = recovered-L->nblocks; L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; return recovered; }
static void collectproto (lua_State *L) { Proto **p = &L->rootproto; Proto *next; while ((next = *p) != NULL) { if (next->marked) { next->marked = 0; p = &next->next; } else { *p = next->next; luaF_freeproto(L, next); } } }
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 lua_close (void) { TaggedString *alludata = luaS_collectudata(); L->GCthreshold = MAX_INT; /* to avoid GC during GC */ luaC_hashcallIM((Hash *)L->roottable.next); /* GC t.methods for tables */ luaC_strcallIM(alludata); /* GC tag methods for userdata */ luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ luaH_free((Hash *)L->roottable.next); luaF_freeproto((TProtoFunc *)L->rootproto.next); luaF_freeclosure((Closure *)L->rootcl.next); luaS_free(alludata); luaS_freeall(); luaM_free(L->stack.stack); luaM_free(L->IMtable); luaM_free(L->refArray); luaM_free(L->Mbuffer); luaM_free(L->Cblocks); luaM_free(L); L = NULL; #ifdef DEBUG printf("total de blocos: %ld\n", numblocks); printf("total de memoria: %ld\n", totalmem); #endif }
static void cleartable (lua_State *L, GCObject *l) { #else static void cleartable (GCObject *l) { #endif /* LUA_REFCOUNT */ while (l) { Table *h = gco2h(l); int i = h->sizearray; lua_assert(testbit(h->marked, VALUEWEAKBIT) || testbit(h->marked, KEYWEAKBIT)); if (testbit(h->marked, VALUEWEAKBIT)) { while (i--) { TValue *o = &h->array[i]; #if LUA_REFCOUNT if (iscleared(o, 0)) { /* value was collected? */ if (iscollectable(o)) o->value.gc->gch.ref--; setnilvalue2n(l, o); /* remove value */ } #else if (iscleared(o, 0)) /* value was collected? */ setnilvalue(o); /* remove value */ #endif /* LUA_REFCOUNT */ } } i = sizenode(h); while (i--) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { #if LUA_REFCOUNT if (iscollectable(gval(n))) gval(n)->value.gc->gch.ref--; setnilvalue2n(L, gval(n)); /* remove value ... */ #else setnilvalue(gval(n)); /* remove value ... */ #endif /* LUA_REFCOUNT */ removeentry(n); /* remove entry from table */ } } l = h->gclist; } } static void freeobj (lua_State *L, GCObject *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; } #if LUA_WIDESTRING case LUA_TWSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } #endif /* LUA_WIDESTRING */ case LUA_TUSERDATA: { luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } } #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ sweepwholelist(L, &gco2th(curr)->openupval); if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); makewhite(g, curr); /* make it white (for next cycle) */ p = &curr->gch.next; } else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); #if LUA_REFCOUNT if (curr->gch.prev) curr->gch.prev->gch.next = curr->gch.next; if (curr->gch.next) curr->gch.next->gch.prev = (GCObject*)p; #endif /* LUA_REFCOUNT */ *p = curr->gch.next; if (curr == g->rootgc) /* is the first element of the list? */ g->rootgc = curr->gch.next; /* adjust first */ freeobj(L, curr); } } return p; }