/*1** $Id: lgc.c $2** Garbage Collector3** See Copyright Notice in lua.h4*/56#define lgc_c7#define LUA_CORE89#include "lprefix.h"1011#include <stdio.h>12#include <string.h>131415#include "lua.h"1617#include "ldebug.h"18#include "ldo.h"19#include "lfunc.h"20#include "lgc.h"21#include "lmem.h"22#include "lobject.h"23#include "lstate.h"24#include "lstring.h"25#include "ltable.h"26#include "ltm.h"272829/*30** Maximum number of elements to sweep in each single step.31** (Large enough to dissipate fixed overheads but small enough32** to allow small steps for the collector.)33*/34#define GCSWEEPMAX 1003536/*37** Maximum number of finalizers to call in each single step.38*/39#define GCFINMAX 10404142/*43** Cost of calling one finalizer.44*/45#define GCFINALIZECOST 50464748/*49** The equivalent, in bytes, of one unit of "work" (visiting a slot,50** sweeping an object, etc.)51*/52#define WORK2MEM sizeof(TValue)535455/*56** macro to adjust 'pause': 'pause' is actually used like57** 'pause / PAUSEADJ' (value chosen by tests)58*/59#define PAUSEADJ 100606162/* mask with all color bits */63#define maskcolors (bitmask(BLACKBIT) | WHITEBITS)6465/* mask with all GC bits */66#define maskgcbits (maskcolors | AGEBITS)676869/* macro to erase all color bits then set only the current white bit */70#define makewhite(g,x) \71(x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g)))7273/* make an object gray (neither white nor black) */74#define set2gray(x) resetbits(x->marked, maskcolors)757677/* make an object black (coming from any color) */78#define set2black(x) \79(x->marked = cast_byte((x->marked & ~WHITEBITS) | bitmask(BLACKBIT)))808182#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))8384#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))858687/*88** Protected access to objects in values89*/90#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)919293#define markvalue(g,o) { checkliveness(g->mainthread,o); \94if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }9596#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }9798#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }99100/*101** mark an object that can be NULL (either because it is really optional,102** or it was stripped as debug info, or inside an uncompleted structure)103*/104#define markobjectN(g,t) { if (t) markobject(g,t); }105106static void reallymarkobject (global_State *g, GCObject *o);107static lu_mem atomic (lua_State *L);108static void entersweep (lua_State *L);109110111/*112** {======================================================113** Generic functions114** =======================================================115*/116117118/*119** one after last element in a hash array120*/121#define gnodelast(h) gnode(h, cast_sizet(sizenode(h)))122123124static GCObject **getgclist (GCObject *o) {125switch (o->tt) {126case LUA_VTABLE: return &gco2t(o)->gclist;127case LUA_VLCL: return &gco2lcl(o)->gclist;128case LUA_VCCL: return &gco2ccl(o)->gclist;129case LUA_VTHREAD: return &gco2th(o)->gclist;130case LUA_VPROTO: return &gco2p(o)->gclist;131case LUA_VUSERDATA: {132Udata *u = gco2u(o);133lua_assert(u->nuvalue > 0);134return &u->gclist;135}136default: lua_assert(0); return 0;137}138}139140141/*142** Link a collectable object 'o' with a known type into the list 'p'.143** (Must be a macro to access the 'gclist' field in different types.)144*/145#define linkgclist(o,p) linkgclist_(obj2gco(o), &(o)->gclist, &(p))146147static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) {148lua_assert(!isgray(o)); /* cannot be in a gray list */149*pnext = *list;150*list = o;151set2gray(o); /* now it is */152}153154155/*156** Link a generic collectable object 'o' into the list 'p'.157*/158#define linkobjgclist(o,p) linkgclist_(obj2gco(o), getgclist(o), &(p))159160161162/*163** Clear keys for empty entries in tables. If entry is empty, mark its164** entry as dead. This allows the collection of the key, but keeps its165** entry in the table: its removal could break a chain and could break166** a table traversal. Other places never manipulate dead keys, because167** its associated empty value is enough to signal that the entry is168** logically empty.169*/170static void clearkey (Node *n) {171lua_assert(isempty(gval(n)));172if (keyiscollectable(n))173setdeadkey(n); /* unused key; remove it */174}175176177/*178** tells whether a key or value can be cleared from a weak179** table. Non-collectable objects are never removed from weak180** tables. Strings behave as 'values', so are never removed too. for181** other objects: if really collected, cannot keep them; for objects182** being finalized, keep them in keys, but not in values183*/184static int iscleared (global_State *g, const GCObject *o) {185if (o == NULL) return 0; /* non-collectable value */186else if (novariant(o->tt) == LUA_TSTRING) {187markobject(g, o); /* strings are 'values', so are never weak */188return 0;189}190else return iswhite(o);191}192193194/*195** Barrier that moves collector forward, that is, marks the white object196** 'v' being pointed by the black object 'o'. In the generational197** mode, 'v' must also become old, if 'o' is old; however, it cannot198** be changed directly to OLD, because it may still point to non-old199** objects. So, it is marked as OLD0. In the next cycle it will become200** OLD1, and in the next it will finally become OLD (regular old). By201** then, any object it points to will also be old. If called in the202** incremental sweep phase, it clears the black object to white (sweep203** it) to avoid other barrier calls for this same object. (That cannot204** be done is generational mode, as its sweep does not distinguish205** whites from deads.)206*/207void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {208global_State *g = G(L);209lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));210if (keepinvariant(g)) { /* must keep invariant? */211reallymarkobject(g, v); /* restore invariant */212if (isold(o)) {213lua_assert(!isold(v)); /* white object could not be old */214setage(v, G_OLD0); /* restore generational invariant */215}216}217else { /* sweep phase */218lua_assert(issweepphase(g));219if (g->gckind == KGC_INC) /* incremental mode? */220makewhite(g, o); /* mark 'o' as white to avoid other barriers */221}222}223224225/*226** barrier that moves collector backward, that is, mark the black object227** pointing to a white object as gray again.228*/229void luaC_barrierback_ (lua_State *L, GCObject *o) {230global_State *g = G(L);231lua_assert(isblack(o) && !isdead(g, o));232lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1));233if (getage(o) == G_TOUCHED2) /* already in gray list? */234set2gray(o); /* make it gray to become touched1 */235else /* link it in 'grayagain' and paint it gray */236linkobjgclist(o, g->grayagain);237if (isold(o)) /* generational mode? */238setage(o, G_TOUCHED1); /* touched in current cycle */239}240241242void luaC_fix (lua_State *L, GCObject *o) {243global_State *g = G(L);244lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */245set2gray(o); /* they will be gray forever */246setage(o, G_OLD); /* and old forever */247g->allgc = o->next; /* remove object from 'allgc' list */248o->next = g->fixedgc; /* link it to 'fixedgc' list */249g->fixedgc = o;250}251252253/*254** create a new collectable object (with given type, size, and offset)255** and link it to 'allgc' list.256*/257GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {258global_State *g = G(L);259char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));260GCObject *o = cast(GCObject *, p + offset);261o->marked = luaC_white(g);262o->tt = tt;263o->next = g->allgc;264g->allgc = o;265return o;266}267268269GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {270return luaC_newobjdt(L, tt, sz, 0);271}272273/* }====================================================== */274275276277/*278** {======================================================279** Mark functions280** =======================================================281*/282283284/*285** Mark an object. Userdata with no user values, strings, and closed286** upvalues are visited and turned black here. Open upvalues are287** already indirectly linked through their respective threads in the288** 'twups' list, so they don't go to the gray list; nevertheless, they289** are kept gray to avoid barriers, as their values will be revisited290** by the thread or by 'remarkupvals'. Other objects are added to the291** gray list to be visited (and turned black) later. Both userdata and292** upvalues can call this function recursively, but this recursion goes293** for at most two levels: An upvalue cannot refer to another upvalue294** (only closures can), and a userdata's metatable must be a table.295*/296static void reallymarkobject (global_State *g, GCObject *o) {297switch (o->tt) {298case LUA_VSHRSTR:299case LUA_VLNGSTR: {300set2black(o); /* nothing to visit */301break;302}303case LUA_VUPVAL: {304UpVal *uv = gco2upv(o);305if (upisopen(uv))306set2gray(uv); /* open upvalues are kept gray */307else308set2black(uv); /* closed upvalues are visited here */309markvalue(g, uv->v.p); /* mark its content */310break;311}312case LUA_VUSERDATA: {313Udata *u = gco2u(o);314if (u->nuvalue == 0) { /* no user values? */315markobjectN(g, u->metatable); /* mark its metatable */316set2black(u); /* nothing else to mark */317break;318}319/* else... */320} /* FALLTHROUGH */321case LUA_VLCL: case LUA_VCCL: case LUA_VTABLE:322case LUA_VTHREAD: case LUA_VPROTO: {323linkobjgclist(o, g->gray); /* to be visited later */324break;325}326default: lua_assert(0); break;327}328}329330331/*332** mark metamethods for basic types333*/334static void markmt (global_State *g) {335int i;336for (i=0; i < LUA_NUMTAGS; i++)337markobjectN(g, g->mt[i]);338}339340341/*342** mark all objects in list of being-finalized343*/344static lu_mem markbeingfnz (global_State *g) {345GCObject *o;346lu_mem count = 0;347for (o = g->tobefnz; o != NULL; o = o->next) {348count++;349markobject(g, o);350}351return count;352}353354355/*356** For each non-marked thread, simulates a barrier between each open357** upvalue and its value. (If the thread is collected, the value will be358** assigned to the upvalue, but then it can be too late for the barrier359** to act. The "barrier" does not need to check colors: A non-marked360** thread must be young; upvalues cannot be older than their threads; so361** any visited upvalue must be young too.) Also removes the thread from362** the list, as it was already visited. Removes also threads with no363** upvalues, as they have nothing to be checked. (If the thread gets an364** upvalue later, it will be linked in the list again.)365*/366static int remarkupvals (global_State *g) {367lua_State *thread;368lua_State **p = &g->twups;369int work = 0; /* estimate of how much work was done here */370while ((thread = *p) != NULL) {371work++;372if (!iswhite(thread) && thread->openupval != NULL)373p = &thread->twups; /* keep marked thread with upvalues in the list */374else { /* thread is not marked or without upvalues */375UpVal *uv;376lua_assert(!isold(thread) || thread->openupval == NULL);377*p = thread->twups; /* remove thread from the list */378thread->twups = thread; /* mark that it is out of list */379for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {380lua_assert(getage(uv) <= getage(thread));381work++;382if (!iswhite(uv)) { /* upvalue already visited? */383lua_assert(upisopen(uv) && isgray(uv));384markvalue(g, uv->v.p); /* mark its value */385}386}387}388}389return work;390}391392393static void cleargraylists (global_State *g) {394g->gray = g->grayagain = NULL;395g->weak = g->allweak = g->ephemeron = NULL;396}397398399/*400** mark root set and reset all gray lists, to start a new collection401*/402static void restartcollection (global_State *g) {403cleargraylists(g);404markobject(g, g->mainthread);405markvalue(g, &g->l_registry);406markmt(g);407markbeingfnz(g); /* mark any finalizing object left from previous cycle */408}409410/* }====================================================== */411412413/*414** {======================================================415** Traverse functions416** =======================================================417*/418419420/*421** Check whether object 'o' should be kept in the 'grayagain' list for422** post-processing by 'correctgraylist'. (It could put all old objects423** in the list and leave all the work to 'correctgraylist', but it is424** more efficient to avoid adding elements that will be removed.) Only425** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go426** back to a gray list, but then it must become OLD. (That is what427** 'correctgraylist' does when it finds a TOUCHED2 object.)428*/429static void genlink (global_State *g, GCObject *o) {430lua_assert(isblack(o));431if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */432linkobjgclist(o, g->grayagain); /* link it back in 'grayagain' */433} /* everything else do not need to be linked back */434else if (getage(o) == G_TOUCHED2)435changeage(o, G_TOUCHED2, G_OLD); /* advance age */436}437438439/*440** Traverse a table with weak values and link it to proper list. During441** propagate phase, keep it in 'grayagain' list, to be revisited in the442** atomic phase. In the atomic phase, if table has any white value,443** put it in 'weak' list, to be cleared.444*/445static void traverseweakvalue (global_State *g, Table *h) {446Node *n, *limit = gnodelast(h);447/* if there is array part, assume it may have white values (it is not448worth traversing it now just to check) */449int hasclears = (h->alimit > 0);450for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */451if (isempty(gval(n))) /* entry is empty? */452clearkey(n); /* clear its key */453else {454lua_assert(!keyisnil(n));455markkey(g, n);456if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */457hasclears = 1; /* table will have to be cleared */458}459}460if (g->gcstate == GCSatomic && hasclears)461linkgclist(h, g->weak); /* has to be cleared later */462else463linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */464}465466467/*468** Traverse an ephemeron table and link it to proper list. Returns true469** iff any object was marked during this traversal (which implies that470** convergence has to continue). During propagation phase, keep table471** in 'grayagain' list, to be visited again in the atomic phase. In472** the atomic phase, if table has any white->white entry, it has to473** be revisited during ephemeron convergence (as that key may turn474** black). Otherwise, if it has any white key, table has to be cleared475** (in the atomic phase). In generational mode, some tables476** must be kept in some gray list for post-processing; this is done477** by 'genlink'.478*/479static int traverseephemeron (global_State *g, Table *h, int inv) {480int marked = 0; /* true if an object is marked in this traversal */481int hasclears = 0; /* true if table has white keys */482int hasww = 0; /* true if table has entry "white-key -> white-value" */483unsigned int i;484unsigned int asize = luaH_realasize(h);485unsigned int nsize = sizenode(h);486/* traverse array part */487for (i = 0; i < asize; i++) {488if (valiswhite(&h->array[i])) {489marked = 1;490reallymarkobject(g, gcvalue(&h->array[i]));491}492}493/* traverse hash part; if 'inv', traverse descending494(see 'convergeephemerons') */495for (i = 0; i < nsize; i++) {496Node *n = inv ? gnode(h, nsize - 1 - i) : gnode(h, i);497if (isempty(gval(n))) /* entry is empty? */498clearkey(n); /* clear its key */499else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */500hasclears = 1; /* table must be cleared */501if (valiswhite(gval(n))) /* value not marked yet? */502hasww = 1; /* white-white entry */503}504else if (valiswhite(gval(n))) { /* value not marked yet? */505marked = 1;506reallymarkobject(g, gcvalue(gval(n))); /* mark it now */507}508}509/* link table into proper list */510if (g->gcstate == GCSpropagate)511linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */512else if (hasww) /* table has white->white entries? */513linkgclist(h, g->ephemeron); /* have to propagate again */514else if (hasclears) /* table has white keys? */515linkgclist(h, g->allweak); /* may have to clean white keys */516else517genlink(g, obj2gco(h)); /* check whether collector still needs to see it */518return marked;519}520521522static void traversestrongtable (global_State *g, Table *h) {523Node *n, *limit = gnodelast(h);524unsigned int i;525unsigned int asize = luaH_realasize(h);526for (i = 0; i < asize; i++) /* traverse array part */527markvalue(g, &h->array[i]);528for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */529if (isempty(gval(n))) /* entry is empty? */530clearkey(n); /* clear its key */531else {532lua_assert(!keyisnil(n));533markkey(g, n);534markvalue(g, gval(n));535}536}537genlink(g, obj2gco(h));538}539540541static lu_mem traversetable (global_State *g, Table *h) {542const char *weakkey, *weakvalue;543const TValue *mode = gfasttm(g, h->metatable, TM_MODE);544TString *smode;545markobjectN(g, h->metatable);546if (mode && ttisshrstring(mode) && /* is there a weak mode? */547(cast_void(smode = tsvalue(mode)),548cast_void(weakkey = strchr(getshrstr(smode), 'k')),549cast_void(weakvalue = strchr(getshrstr(smode), 'v')),550(weakkey || weakvalue))) { /* is really weak? */551if (!weakkey) /* strong keys? */552traverseweakvalue(g, h);553else if (!weakvalue) /* strong values? */554traverseephemeron(g, h, 0);555else /* all weak */556linkgclist(h, g->allweak); /* nothing to traverse now */557}558else /* not weak */559traversestrongtable(g, h);560return 1 + h->alimit + 2 * allocsizenode(h);561}562563564static int traverseudata (global_State *g, Udata *u) {565int i;566markobjectN(g, u->metatable); /* mark its metatable */567for (i = 0; i < u->nuvalue; i++)568markvalue(g, &u->uv[i].uv);569genlink(g, obj2gco(u));570return 1 + u->nuvalue;571}572573574/*575** Traverse a prototype. (While a prototype is being build, its576** arrays can be larger than needed; the extra slots are filled with577** NULL, so the use of 'markobjectN')578*/579static int traverseproto (global_State *g, Proto *f) {580int i;581markobjectN(g, f->source);582for (i = 0; i < f->sizek; i++) /* mark literals */583markvalue(g, &f->k[i]);584for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */585markobjectN(g, f->upvalues[i].name);586for (i = 0; i < f->sizep; i++) /* mark nested protos */587markobjectN(g, f->p[i]);588for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */589markobjectN(g, f->locvars[i].varname);590return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;591}592593594static int traverseCclosure (global_State *g, CClosure *cl) {595int i;596for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */597markvalue(g, &cl->upvalue[i]);598return 1 + cl->nupvalues;599}600601/*602** Traverse a Lua closure, marking its prototype and its upvalues.603** (Both can be NULL while closure is being created.)604*/605static int traverseLclosure (global_State *g, LClosure *cl) {606int i;607markobjectN(g, cl->p); /* mark its prototype */608for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */609UpVal *uv = cl->upvals[i];610markobjectN(g, uv); /* mark upvalue */611}612return 1 + cl->nupvalues;613}614615616/*617** Traverse a thread, marking the elements in the stack up to its top618** and cleaning the rest of the stack in the final traversal. That619** ensures that the entire stack have valid (non-dead) objects.620** Threads have no barriers. In gen. mode, old threads must be visited621** at every cycle, because they might point to young objects. In inc.622** mode, the thread can still be modified before the end of the cycle,623** and therefore it must be visited again in the atomic phase. To ensure624** these visits, threads must return to a gray list if they are not new625** (which can only happen in generational mode) or if the traverse is in626** the propagate phase (which can only happen in incremental mode).627*/628static int traversethread (global_State *g, lua_State *th) {629UpVal *uv;630StkId o = th->stack.p;631if (isold(th) || g->gcstate == GCSpropagate)632linkgclist(th, g->grayagain); /* insert into 'grayagain' list */633if (o == NULL)634return 1; /* stack not completely built yet */635lua_assert(g->gcstate == GCSatomic ||636th->openupval == NULL || isintwups(th));637for (; o < th->top.p; o++) /* mark live elements in the stack */638markvalue(g, s2v(o));639for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)640markobject(g, uv); /* open upvalues cannot be collected */641if (g->gcstate == GCSatomic) { /* final traversal? */642if (!g->gcemergency)643luaD_shrinkstack(th); /* do not change stack in emergency cycle */644for (o = th->top.p; o < th->stack_last.p + EXTRA_STACK; o++)645setnilvalue(s2v(o)); /* clear dead stack slice */646/* 'remarkupvals' may have removed thread from 'twups' list */647if (!isintwups(th) && th->openupval != NULL) {648th->twups = g->twups; /* link it back to the list */649g->twups = th;650}651}652return 1 + stacksize(th);653}654655656/*657** traverse one gray object, turning it to black.658*/659static lu_mem propagatemark (global_State *g) {660GCObject *o = g->gray;661nw2black(o);662g->gray = *getgclist(o); /* remove from 'gray' list */663switch (o->tt) {664case LUA_VTABLE: return traversetable(g, gco2t(o));665case LUA_VUSERDATA: return traverseudata(g, gco2u(o));666case LUA_VLCL: return traverseLclosure(g, gco2lcl(o));667case LUA_VCCL: return traverseCclosure(g, gco2ccl(o));668case LUA_VPROTO: return traverseproto(g, gco2p(o));669case LUA_VTHREAD: return traversethread(g, gco2th(o));670default: lua_assert(0); return 0;671}672}673674675static lu_mem propagateall (global_State *g) {676lu_mem tot = 0;677while (g->gray)678tot += propagatemark(g);679return tot;680}681682683/*684** Traverse all ephemeron tables propagating marks from keys to values.685** Repeat until it converges, that is, nothing new is marked. 'dir'686** inverts the direction of the traversals, trying to speed up687** convergence on chains in the same table.688**689*/690static void convergeephemerons (global_State *g) {691int changed;692int dir = 0;693do {694GCObject *w;695GCObject *next = g->ephemeron; /* get ephemeron list */696g->ephemeron = NULL; /* tables may return to this list when traversed */697changed = 0;698while ((w = next) != NULL) { /* for each ephemeron table */699Table *h = gco2t(w);700next = h->gclist; /* list is rebuilt during loop */701nw2black(h); /* out of the list (for now) */702if (traverseephemeron(g, h, dir)) { /* marked some value? */703propagateall(g); /* propagate changes */704changed = 1; /* will have to revisit all ephemeron tables */705}706}707dir = !dir; /* invert direction next time */708} while (changed); /* repeat until no more changes */709}710711/* }====================================================== */712713714/*715** {======================================================716** Sweep Functions717** =======================================================718*/719720721/*722** clear entries with unmarked keys from all weaktables in list 'l'723*/724static void clearbykeys (global_State *g, GCObject *l) {725for (; l; l = gco2t(l)->gclist) {726Table *h = gco2t(l);727Node *limit = gnodelast(h);728Node *n;729for (n = gnode(h, 0); n < limit; n++) {730if (iscleared(g, gckeyN(n))) /* unmarked key? */731setempty(gval(n)); /* remove entry */732if (isempty(gval(n))) /* is entry empty? */733clearkey(n); /* clear its key */734}735}736}737738739/*740** clear entries with unmarked values from all weaktables in list 'l' up741** to element 'f'742*/743static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {744for (; l != f; l = gco2t(l)->gclist) {745Table *h = gco2t(l);746Node *n, *limit = gnodelast(h);747unsigned int i;748unsigned int asize = luaH_realasize(h);749for (i = 0; i < asize; i++) {750TValue *o = &h->array[i];751if (iscleared(g, gcvalueN(o))) /* value was collected? */752setempty(o); /* remove entry */753}754for (n = gnode(h, 0); n < limit; n++) {755if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */756setempty(gval(n)); /* remove entry */757if (isempty(gval(n))) /* is entry empty? */758clearkey(n); /* clear its key */759}760}761}762763764static void freeupval (lua_State *L, UpVal *uv) {765if (upisopen(uv))766luaF_unlinkupval(uv);767luaM_free(L, uv);768}769770771static void freeobj (lua_State *L, GCObject *o) {772switch (o->tt) {773case LUA_VPROTO:774luaF_freeproto(L, gco2p(o));775break;776case LUA_VUPVAL:777freeupval(L, gco2upv(o));778break;779case LUA_VLCL: {780LClosure *cl = gco2lcl(o);781luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));782break;783}784case LUA_VCCL: {785CClosure *cl = gco2ccl(o);786luaM_freemem(L, cl, sizeCclosure(cl->nupvalues));787break;788}789case LUA_VTABLE:790luaH_free(L, gco2t(o));791break;792case LUA_VTHREAD:793luaE_freethread(L, gco2th(o));794break;795case LUA_VUSERDATA: {796Udata *u = gco2u(o);797luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));798break;799}800case LUA_VSHRSTR: {801TString *ts = gco2ts(o);802luaS_remove(L, ts); /* remove it from hash table */803luaM_freemem(L, ts, sizelstring(ts->shrlen));804break;805}806case LUA_VLNGSTR: {807TString *ts = gco2ts(o);808luaM_freemem(L, ts, sizelstring(ts->u.lnglen));809break;810}811default: lua_assert(0);812}813}814815816/*817** sweep at most 'countin' elements from a list of GCObjects erasing dead818** objects, where a dead object is one marked with the old (non current)819** white; change all non-dead objects back to white, preparing for next820** collection cycle. Return where to continue the traversal or NULL if821** list is finished. ('*countout' gets the number of elements traversed.)822*/823static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,824int *countout) {825global_State *g = G(L);826int ow = otherwhite(g);827int i;828int white = luaC_white(g); /* current white */829for (i = 0; *p != NULL && i < countin; i++) {830GCObject *curr = *p;831int marked = curr->marked;832if (isdeadm(ow, marked)) { /* is 'curr' dead? */833*p = curr->next; /* remove 'curr' from list */834freeobj(L, curr); /* erase 'curr' */835}836else { /* change mark to 'white' */837curr->marked = cast_byte((marked & ~maskgcbits) | white);838p = &curr->next; /* go to next element */839}840}841if (countout)842*countout = i; /* number of elements traversed */843return (*p == NULL) ? NULL : p;844}845846847/*848** sweep a list until a live object (or end of list)849*/850static GCObject **sweeptolive (lua_State *L, GCObject **p) {851GCObject **old = p;852do {853p = sweeplist(L, p, 1, NULL);854} while (p == old);855return p;856}857858/* }====================================================== */859860861/*862** {======================================================863** Finalization864** =======================================================865*/866867/*868** If possible, shrink string table.869*/870static void checkSizes (lua_State *L, global_State *g) {871if (!g->gcemergency) {872if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */873l_mem olddebt = g->GCdebt;874luaS_resize(L, g->strt.size / 2);875g->GCestimate += g->GCdebt - olddebt; /* correct estimate */876}877}878}879880881/*882** Get the next udata to be finalized from the 'tobefnz' list, and883** link it back into the 'allgc' list.884*/885static GCObject *udata2finalize (global_State *g) {886GCObject *o = g->tobefnz; /* get first element */887lua_assert(tofinalize(o));888g->tobefnz = o->next; /* remove it from 'tobefnz' list */889o->next = g->allgc; /* return it to 'allgc' list */890g->allgc = o;891resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */892if (issweepphase(g))893makewhite(g, o); /* "sweep" object */894else if (getage(o) == G_OLD1)895g->firstold1 = o; /* it is the first OLD1 object in the list */896return o;897}898899900static void dothecall (lua_State *L, void *ud) {901UNUSED(ud);902luaD_callnoyield(L, L->top.p - 2, 0);903}904905906static void GCTM (lua_State *L) {907global_State *g = G(L);908const TValue *tm;909TValue v;910lua_assert(!g->gcemergency);911setgcovalue(L, &v, udata2finalize(g));912tm = luaT_gettmbyobj(L, &v, TM_GC);913if (!notm(tm)) { /* is there a finalizer? */914int status;915lu_byte oldah = L->allowhook;916int oldgcstp = g->gcstp;917g->gcstp |= GCSTPGC; /* avoid GC steps */918L->allowhook = 0; /* stop debug hooks during GC metamethod */919setobj2s(L, L->top.p++, tm); /* push finalizer... */920setobj2s(L, L->top.p++, &v); /* ... and its argument */921L->ci->callstatus |= CIST_FIN; /* will run a finalizer */922status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0);923L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */924L->allowhook = oldah; /* restore hooks */925g->gcstp = oldgcstp; /* restore state */926if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */927luaE_warnerror(L, "__gc");928L->top.p--; /* pops error object */929}930}931}932933934/*935** Call a few finalizers936*/937static int runafewfinalizers (lua_State *L, int n) {938global_State *g = G(L);939int i;940for (i = 0; i < n && g->tobefnz; i++)941GCTM(L); /* call one finalizer */942return i;943}944945946/*947** call all pending finalizers948*/949static void callallpendingfinalizers (lua_State *L) {950global_State *g = G(L);951while (g->tobefnz)952GCTM(L);953}954955956/*957** find last 'next' field in list 'p' list (to add elements in its end)958*/959static GCObject **findlast (GCObject **p) {960while (*p != NULL)961p = &(*p)->next;962return p;963}964965966/*967** Move all unreachable objects (or 'all' objects) that need968** finalization from list 'finobj' to list 'tobefnz' (to be finalized).969** (Note that objects after 'finobjold1' cannot be white, so they970** don't need to be traversed. In incremental mode, 'finobjold1' is NULL,971** so the whole list is traversed.)972*/973static void separatetobefnz (global_State *g, int all) {974GCObject *curr;975GCObject **p = &g->finobj;976GCObject **lastnext = findlast(&g->tobefnz);977while ((curr = *p) != g->finobjold1) { /* traverse all finalizable objects */978lua_assert(tofinalize(curr));979if (!(iswhite(curr) || all)) /* not being collected? */980p = &curr->next; /* don't bother with it */981else {982if (curr == g->finobjsur) /* removing 'finobjsur'? */983g->finobjsur = curr->next; /* correct it */984*p = curr->next; /* remove 'curr' from 'finobj' list */985curr->next = *lastnext; /* link at the end of 'tobefnz' list */986*lastnext = curr;987lastnext = &curr->next;988}989}990}991992993/*994** If pointer 'p' points to 'o', move it to the next element.995*/996static void checkpointer (GCObject **p, GCObject *o) {997if (o == *p)998*p = o->next;999}100010011002/*1003** Correct pointers to objects inside 'allgc' list when1004** object 'o' is being removed from the list.1005*/1006static void correctpointers (global_State *g, GCObject *o) {1007checkpointer(&g->survival, o);1008checkpointer(&g->old1, o);1009checkpointer(&g->reallyold, o);1010checkpointer(&g->firstold1, o);1011}101210131014/*1015** if object 'o' has a finalizer, remove it from 'allgc' list (must1016** search the list to find it) and link it in 'finobj' list.1017*/1018void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {1019global_State *g = G(L);1020if (tofinalize(o) || /* obj. is already marked... */1021gfasttm(g, mt, TM_GC) == NULL || /* or has no finalizer... */1022(g->gcstp & GCSTPCLS)) /* or closing state? */1023return; /* nothing to be done */1024else { /* move 'o' to 'finobj' list */1025GCObject **p;1026if (issweepphase(g)) {1027makewhite(g, o); /* "sweep" object 'o' */1028if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */1029g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */1030}1031else1032correctpointers(g, o);1033/* search for pointer pointing to 'o' */1034for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }1035*p = o->next; /* remove 'o' from 'allgc' list */1036o->next = g->finobj; /* link it in 'finobj' list */1037g->finobj = o;1038l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */1039}1040}10411042/* }====================================================== */104310441045/*1046** {======================================================1047** Generational Collector1048** =======================================================1049*/105010511052/*1053** Set the "time" to wait before starting a new GC cycle; cycle will1054** start when memory use hits the threshold of ('estimate' * pause /1055** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero,1056** because Lua cannot even start with less than PAUSEADJ bytes).1057*/1058static void setpause (global_State *g) {1059l_mem threshold, debt;1060int pause = getgcparam(g->gcpause);1061l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */1062lua_assert(estimate > 0);1063threshold = (pause < MAX_LMEM / estimate) /* overflow? */1064? estimate * pause /* no overflow */1065: MAX_LMEM; /* overflow; truncate to maximum */1066debt = gettotalbytes(g) - threshold;1067if (debt > 0) debt = 0;1068luaE_setdebt(g, debt);1069}107010711072/*1073** Sweep a list of objects to enter generational mode. Deletes dead1074** objects and turns the non dead to old. All non-dead threads---which1075** are now old---must be in a gray list. Everything else is not in a1076** gray list. Open upvalues are also kept gray.1077*/1078static void sweep2old (lua_State *L, GCObject **p) {1079GCObject *curr;1080global_State *g = G(L);1081while ((curr = *p) != NULL) {1082if (iswhite(curr)) { /* is 'curr' dead? */1083lua_assert(isdead(g, curr));1084*p = curr->next; /* remove 'curr' from list */1085freeobj(L, curr); /* erase 'curr' */1086}1087else { /* all surviving objects become old */1088setage(curr, G_OLD);1089if (curr->tt == LUA_VTHREAD) { /* threads must be watched */1090lua_State *th = gco2th(curr);1091linkgclist(th, g->grayagain); /* insert into 'grayagain' list */1092}1093else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr)))1094set2gray(curr); /* open upvalues are always gray */1095else /* everything else is black */1096nw2black(curr);1097p = &curr->next; /* go to next element */1098}1099}1100}110111021103/*1104** Sweep for generational mode. Delete dead objects. (Because the1105** collection is not incremental, there are no "new white" objects1106** during the sweep. So, any white object must be dead.) For1107** non-dead objects, advance their ages and clear the color of1108** new objects. (Old objects keep their colors.)1109** The ages of G_TOUCHED1 and G_TOUCHED2 objects cannot be advanced1110** here, because these old-generation objects are usually not swept1111** here. They will all be advanced in 'correctgraylist'. That function1112** will also remove objects turned white here from any gray list.1113*/1114static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,1115GCObject *limit, GCObject **pfirstold1) {1116static const lu_byte nextage[] = {1117G_SURVIVAL, /* from G_NEW */1118G_OLD1, /* from G_SURVIVAL */1119G_OLD1, /* from G_OLD0 */1120G_OLD, /* from G_OLD1 */1121G_OLD, /* from G_OLD (do not change) */1122G_TOUCHED1, /* from G_TOUCHED1 (do not change) */1123G_TOUCHED2 /* from G_TOUCHED2 (do not change) */1124};1125int white = luaC_white(g);1126GCObject *curr;1127while ((curr = *p) != limit) {1128if (iswhite(curr)) { /* is 'curr' dead? */1129lua_assert(!isold(curr) && isdead(g, curr));1130*p = curr->next; /* remove 'curr' from list */1131freeobj(L, curr); /* erase 'curr' */1132}1133else { /* correct mark and age */1134if (getage(curr) == G_NEW) { /* new objects go back to white */1135int marked = curr->marked & ~maskgcbits; /* erase GC bits */1136curr->marked = cast_byte(marked | G_SURVIVAL | white);1137}1138else { /* all other objects will be old, and so keep their color */1139setage(curr, nextage[getage(curr)]);1140if (getage(curr) == G_OLD1 && *pfirstold1 == NULL)1141*pfirstold1 = curr; /* first OLD1 object in the list */1142}1143p = &curr->next; /* go to next element */1144}1145}1146return p;1147}114811491150/*1151** Traverse a list making all its elements white and clearing their1152** age. In incremental mode, all objects are 'new' all the time,1153** except for fixed strings (which are always old).1154*/1155static void whitelist (global_State *g, GCObject *p) {1156int white = luaC_white(g);1157for (; p != NULL; p = p->next)1158p->marked = cast_byte((p->marked & ~maskgcbits) | white);1159}116011611162/*1163** Correct a list of gray objects. Return pointer to where rest of the1164** list should be linked.1165** Because this correction is done after sweeping, young objects might1166** be turned white and still be in the list. They are only removed.1167** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list;1168** Non-white threads also remain on the list; 'TOUCHED2' objects become1169** regular old; they and anything else are removed from the list.1170*/1171static GCObject **correctgraylist (GCObject **p) {1172GCObject *curr;1173while ((curr = *p) != NULL) {1174GCObject **next = getgclist(curr);1175if (iswhite(curr))1176goto remove; /* remove all white objects */1177else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */1178lua_assert(isgray(curr));1179nw2black(curr); /* make it black, for next barrier */1180changeage(curr, G_TOUCHED1, G_TOUCHED2);1181goto remain; /* keep it in the list and go to next element */1182}1183else if (curr->tt == LUA_VTHREAD) {1184lua_assert(isgray(curr));1185goto remain; /* keep non-white threads on the list */1186}1187else { /* everything else is removed */1188lua_assert(isold(curr)); /* young objects should be white here */1189if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */1190changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */1191nw2black(curr); /* make object black (to be removed) */1192goto remove;1193}1194remove: *p = *next; continue;1195remain: p = next; continue;1196}1197return p;1198}119912001201/*1202** Correct all gray lists, coalescing them into 'grayagain'.1203*/1204static void correctgraylists (global_State *g) {1205GCObject **list = correctgraylist(&g->grayagain);1206*list = g->weak; g->weak = NULL;1207list = correctgraylist(list);1208*list = g->allweak; g->allweak = NULL;1209list = correctgraylist(list);1210*list = g->ephemeron; g->ephemeron = NULL;1211correctgraylist(list);1212}121312141215/*1216** Mark black 'OLD1' objects when starting a new young collection.1217** Gray objects are already in some gray list, and so will be visited1218** in the atomic step.1219*/1220static void markold (global_State *g, GCObject *from, GCObject *to) {1221GCObject *p;1222for (p = from; p != to; p = p->next) {1223if (getage(p) == G_OLD1) {1224lua_assert(!iswhite(p));1225changeage(p, G_OLD1, G_OLD); /* now they are old */1226if (isblack(p))1227reallymarkobject(g, p);1228}1229}1230}123112321233/*1234** Finish a young-generation collection.1235*/1236static void finishgencycle (lua_State *L, global_State *g) {1237correctgraylists(g);1238checkSizes(L, g);1239g->gcstate = GCSpropagate; /* skip restart */1240if (!g->gcemergency)1241callallpendingfinalizers(L);1242}124312441245/*1246** Does a young collection. First, mark 'OLD1' objects. Then does the1247** atomic step. Then, sweep all lists and advance pointers. Finally,1248** finish the collection.1249*/1250static void youngcollection (lua_State *L, global_State *g) {1251GCObject **psurvival; /* to point to first non-dead survival object */1252GCObject *dummy; /* dummy out parameter to 'sweepgen' */1253lua_assert(g->gcstate == GCSpropagate);1254if (g->firstold1) { /* are there regular OLD1 objects? */1255markold(g, g->firstold1, g->reallyold); /* mark them */1256g->firstold1 = NULL; /* no more OLD1 objects (for now) */1257}1258markold(g, g->finobj, g->finobjrold);1259markold(g, g->tobefnz, NULL);1260atomic(L);12611262/* sweep nursery and get a pointer to its last live element */1263g->gcstate = GCSswpallgc;1264psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1);1265/* sweep 'survival' */1266sweepgen(L, g, psurvival, g->old1, &g->firstold1);1267g->reallyold = g->old1;1268g->old1 = *psurvival; /* 'survival' survivals are old now */1269g->survival = g->allgc; /* all news are survivals */12701271/* repeat for 'finobj' lists */1272dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */1273psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy);1274/* sweep 'survival' */1275sweepgen(L, g, psurvival, g->finobjold1, &dummy);1276g->finobjrold = g->finobjold1;1277g->finobjold1 = *psurvival; /* 'survival' survivals are old now */1278g->finobjsur = g->finobj; /* all news are survivals */12791280sweepgen(L, g, &g->tobefnz, NULL, &dummy);1281finishgencycle(L, g);1282}128312841285/*1286** Clears all gray lists, sweeps objects, and prepare sublists to enter1287** generational mode. The sweeps remove dead objects and turn all1288** surviving objects to old. Threads go back to 'grayagain'; everything1289** else is turned black (not in any gray list).1290*/1291static void atomic2gen (lua_State *L, global_State *g) {1292cleargraylists(g);1293/* sweep all elements making them old */1294g->gcstate = GCSswpallgc;1295sweep2old(L, &g->allgc);1296/* everything alive now is old */1297g->reallyold = g->old1 = g->survival = g->allgc;1298g->firstold1 = NULL; /* there are no OLD1 objects anywhere */12991300/* repeat for 'finobj' lists */1301sweep2old(L, &g->finobj);1302g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj;13031304sweep2old(L, &g->tobefnz);13051306g->gckind = KGC_GEN;1307g->lastatomic = 0;1308g->GCestimate = gettotalbytes(g); /* base for memory control */1309finishgencycle(L, g);1310}131113121313/*1314** Set debt for the next minor collection, which will happen when1315** memory grows 'genminormul'%.1316*/1317static void setminordebt (global_State *g) {1318luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul));1319}132013211322/*1323** Enter generational mode. Must go until the end of an atomic cycle1324** to ensure that all objects are correctly marked and weak tables1325** are cleared. Then, turn all objects into old and finishes the1326** collection.1327*/1328static lu_mem entergen (lua_State *L, global_State *g) {1329lu_mem numobjs;1330luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */1331luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */1332numobjs = atomic(L); /* propagates all and then do the atomic stuff */1333atomic2gen(L, g);1334setminordebt(g); /* set debt assuming next cycle will be minor */1335return numobjs;1336}133713381339/*1340** Enter incremental mode. Turn all objects white, make all1341** intermediate lists point to NULL (to avoid invalid pointers),1342** and go to the pause state.1343*/1344static void enterinc (global_State *g) {1345whitelist(g, g->allgc);1346g->reallyold = g->old1 = g->survival = NULL;1347whitelist(g, g->finobj);1348whitelist(g, g->tobefnz);1349g->finobjrold = g->finobjold1 = g->finobjsur = NULL;1350g->gcstate = GCSpause;1351g->gckind = KGC_INC;1352g->lastatomic = 0;1353}135413551356/*1357** Change collector mode to 'newmode'.1358*/1359void luaC_changemode (lua_State *L, int newmode) {1360global_State *g = G(L);1361if (newmode != g->gckind) {1362if (newmode == KGC_GEN) /* entering generational mode? */1363entergen(L, g);1364else1365enterinc(g); /* entering incremental mode */1366}1367g->lastatomic = 0;1368}136913701371/*1372** Does a full collection in generational mode.1373*/1374static lu_mem fullgen (lua_State *L, global_State *g) {1375enterinc(g);1376return entergen(L, g);1377}137813791380/*1381** Does a major collection after last collection was a "bad collection".1382**1383** When the program is building a big structure, it allocates lots of1384** memory but generates very little garbage. In those scenarios,1385** the generational mode just wastes time doing small collections, and1386** major collections are frequently what we call a "bad collection", a1387** collection that frees too few objects. To avoid the cost of switching1388** between generational mode and the incremental mode needed for full1389** (major) collections, the collector tries to stay in incremental mode1390** after a bad collection, and to switch back to generational mode only1391** after a "good" collection (one that traverses less than 9/8 objects1392** of the previous one).1393** The collector must choose whether to stay in incremental mode or to1394** switch back to generational mode before sweeping. At this point, it1395** does not know the real memory in use, so it cannot use memory to1396** decide whether to return to generational mode. Instead, it uses the1397** number of objects traversed (returned by 'atomic') as a proxy. The1398** field 'g->lastatomic' keeps this count from the last collection.1399** ('g->lastatomic != 0' also means that the last collection was bad.)1400*/1401static void stepgenfull (lua_State *L, global_State *g) {1402lu_mem newatomic; /* count of traversed objects */1403lu_mem lastatomic = g->lastatomic; /* count from last collection */1404if (g->gckind == KGC_GEN) /* still in generational mode? */1405enterinc(g); /* enter incremental mode */1406luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */1407newatomic = atomic(L); /* mark everybody */1408if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */1409atomic2gen(L, g); /* return to generational mode */1410setminordebt(g);1411}1412else { /* another bad collection; stay in incremental mode */1413g->GCestimate = gettotalbytes(g); /* first estimate */1414entersweep(L);1415luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */1416setpause(g);1417g->lastatomic = newatomic;1418}1419}142014211422/*1423** Does a generational "step".1424** Usually, this means doing a minor collection and setting the debt to1425** make another collection when memory grows 'genminormul'% larger.1426**1427** However, there are exceptions. If memory grows 'genmajormul'%1428** larger than it was at the end of the last major collection (kept1429** in 'g->GCestimate'), the function does a major collection. At the1430** end, it checks whether the major collection was able to free a1431** decent amount of memory (at least half the growth in memory since1432** previous major collection). If so, the collector keeps its state,1433** and the next collection will probably be minor again. Otherwise,1434** we have what we call a "bad collection". In that case, set the field1435** 'g->lastatomic' to signal that fact, so that the next collection will1436** go to 'stepgenfull'.1437**1438** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;1439** in that case, do a minor collection.1440*/1441static void genstep (lua_State *L, global_State *g) {1442if (g->lastatomic != 0) /* last collection was a bad one? */1443stepgenfull(L, g); /* do a full step */1444else {1445lu_mem majorbase = g->GCestimate; /* memory after last major collection */1446lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul);1447if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) {1448lu_mem numobjs = fullgen(L, g); /* do a major collection */1449if (gettotalbytes(g) < majorbase + (majorinc / 2)) {1450/* collected at least half of memory growth since last major1451collection; keep doing minor collections. */1452lua_assert(g->lastatomic == 0);1453}1454else { /* bad collection */1455g->lastatomic = numobjs; /* signal that last collection was bad */1456setpause(g); /* do a long wait for next (major) collection */1457}1458}1459else { /* regular case; do a minor collection */1460youngcollection(L, g);1461setminordebt(g);1462g->GCestimate = majorbase; /* preserve base value */1463}1464}1465lua_assert(isdecGCmodegen(g));1466}14671468/* }====================================================== */146914701471/*1472** {======================================================1473** GC control1474** =======================================================1475*/147614771478/*1479** Enter first sweep phase.1480** The call to 'sweeptolive' makes the pointer point to an object1481** inside the list (instead of to the header), so that the real sweep do1482** not need to skip objects created between "now" and the start of the1483** real sweep.1484*/1485static void entersweep (lua_State *L) {1486global_State *g = G(L);1487g->gcstate = GCSswpallgc;1488lua_assert(g->sweepgc == NULL);1489g->sweepgc = sweeptolive(L, &g->allgc);1490}149114921493/*1494** Delete all objects in list 'p' until (but not including) object1495** 'limit'.1496*/1497static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {1498while (p != limit) {1499GCObject *next = p->next;1500freeobj(L, p);1501p = next;1502}1503}150415051506/*1507** Call all finalizers of the objects in the given Lua state, and1508** then free all objects, except for the main thread.1509*/1510void luaC_freeallobjects (lua_State *L) {1511global_State *g = G(L);1512g->gcstp = GCSTPCLS; /* no extra finalizers after here */1513luaC_changemode(L, KGC_INC);1514separatetobefnz(g, 1); /* separate all objects with finalizers */1515lua_assert(g->finobj == NULL);1516callallpendingfinalizers(L);1517deletelist(L, g->allgc, obj2gco(g->mainthread));1518lua_assert(g->finobj == NULL); /* no new finalizers */1519deletelist(L, g->fixedgc, NULL); /* collect fixed objects */1520lua_assert(g->strt.nuse == 0);1521}152215231524static lu_mem atomic (lua_State *L) {1525global_State *g = G(L);1526lu_mem work = 0;1527GCObject *origweak, *origall;1528GCObject *grayagain = g->grayagain; /* save original list */1529g->grayagain = NULL;1530lua_assert(g->ephemeron == NULL && g->weak == NULL);1531lua_assert(!iswhite(g->mainthread));1532g->gcstate = GCSatomic;1533markobject(g, L); /* mark running thread */1534/* registry and global metatables may be changed by API */1535markvalue(g, &g->l_registry);1536markmt(g); /* mark global metatables */1537work += propagateall(g); /* empties 'gray' list */1538/* remark occasional upvalues of (maybe) dead threads */1539work += remarkupvals(g);1540work += propagateall(g); /* propagate changes */1541g->gray = grayagain;1542work += propagateall(g); /* traverse 'grayagain' list */1543convergeephemerons(g);1544/* at this point, all strongly accessible objects are marked. */1545/* Clear values from weak tables, before checking finalizers */1546clearbyvalues(g, g->weak, NULL);1547clearbyvalues(g, g->allweak, NULL);1548origweak = g->weak; origall = g->allweak;1549separatetobefnz(g, 0); /* separate objects to be finalized */1550work += markbeingfnz(g); /* mark objects that will be finalized */1551work += propagateall(g); /* remark, to propagate 'resurrection' */1552convergeephemerons(g);1553/* at this point, all resurrected objects are marked. */1554/* remove dead objects from weak tables */1555clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */1556clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */1557/* clear values from resurrected weak tables */1558clearbyvalues(g, g->weak, origweak);1559clearbyvalues(g, g->allweak, origall);1560luaS_clearcache(g);1561g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */1562lua_assert(g->gray == NULL);1563return work; /* estimate of slots marked by 'atomic' */1564}156515661567static int sweepstep (lua_State *L, global_State *g,1568int nextstate, GCObject **nextlist) {1569if (g->sweepgc) {1570l_mem olddebt = g->GCdebt;1571int count;1572g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);1573g->GCestimate += g->GCdebt - olddebt; /* update estimate */1574return count;1575}1576else { /* enter next state */1577g->gcstate = nextstate;1578g->sweepgc = nextlist;1579return 0; /* no work done */1580}1581}158215831584static lu_mem singlestep (lua_State *L) {1585global_State *g = G(L);1586lu_mem work;1587lua_assert(!g->gcstopem); /* collector is not reentrant */1588g->gcstopem = 1; /* no emergency collections while collecting */1589switch (g->gcstate) {1590case GCSpause: {1591restartcollection(g);1592g->gcstate = GCSpropagate;1593work = 1;1594break;1595}1596case GCSpropagate: {1597if (g->gray == NULL) { /* no more gray objects? */1598g->gcstate = GCSenteratomic; /* finish propagate phase */1599work = 0;1600}1601else1602work = propagatemark(g); /* traverse one gray object */1603break;1604}1605case GCSenteratomic: {1606work = atomic(L); /* work is what was traversed by 'atomic' */1607entersweep(L);1608g->GCestimate = gettotalbytes(g); /* first estimate */1609break;1610}1611case GCSswpallgc: { /* sweep "regular" objects */1612work = sweepstep(L, g, GCSswpfinobj, &g->finobj);1613break;1614}1615case GCSswpfinobj: { /* sweep objects with finalizers */1616work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz);1617break;1618}1619case GCSswptobefnz: { /* sweep objects to be finalized */1620work = sweepstep(L, g, GCSswpend, NULL);1621break;1622}1623case GCSswpend: { /* finish sweeps */1624checkSizes(L, g);1625g->gcstate = GCScallfin;1626work = 0;1627break;1628}1629case GCScallfin: { /* call remaining finalizers */1630if (g->tobefnz && !g->gcemergency) {1631g->gcstopem = 0; /* ok collections during finalizers */1632work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST;1633}1634else { /* emergency mode or no more finalizers */1635g->gcstate = GCSpause; /* finish collection */1636work = 0;1637}1638break;1639}1640default: lua_assert(0); return 0;1641}1642g->gcstopem = 0;1643return work;1644}164516461647/*1648** advances the garbage collector until it reaches a state allowed1649** by 'statemask'1650*/1651void luaC_runtilstate (lua_State *L, int statesmask) {1652global_State *g = G(L);1653while (!testbit(statesmask, g->gcstate))1654singlestep(L);1655}1656165716581659/*1660** Performs a basic incremental step. The debt and step size are1661** converted from bytes to "units of work"; then the function loops1662** running single steps until adding that many units of work or1663** finishing a cycle (pause state). Finally, it sets the debt that1664** controls when next step will be performed.1665*/1666static void incstep (lua_State *L, global_State *g) {1667int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */1668l_mem debt = (g->GCdebt / WORK2MEM) * stepmul;1669l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))1670? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul1671: MAX_LMEM; /* overflow; keep maximum value */1672do { /* repeat until pause or enough "credit" (negative debt) */1673lu_mem work = singlestep(L); /* perform one single step */1674debt -= work;1675} while (debt > -stepsize && g->gcstate != GCSpause);1676if (g->gcstate == GCSpause)1677setpause(g); /* pause until next cycle */1678else {1679debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */1680luaE_setdebt(g, debt);1681}1682}16831684/*1685** Performs a basic GC step if collector is running. (If collector is1686** not running, set a reasonable debt to avoid it being called at1687** every single check.)1688*/1689void luaC_step (lua_State *L) {1690global_State *g = G(L);1691if (!gcrunning(g)) /* not running? */1692luaE_setdebt(g, -2000);1693else {1694if(isdecGCmodegen(g))1695genstep(L, g);1696else1697incstep(L, g);1698}1699}170017011702/*1703** Perform a full collection in incremental mode.1704** Before running the collection, check 'keepinvariant'; if it is true,1705** there may be some objects marked as black, so the collector has1706** to sweep all objects to turn them back to white (as white has not1707** changed, nothing will be collected).1708*/1709static void fullinc (lua_State *L, global_State *g) {1710if (keepinvariant(g)) /* black objects? */1711entersweep(L); /* sweep everything to turn them back to white */1712/* finish any pending sweep phase to start a new cycle */1713luaC_runtilstate(L, bitmask(GCSpause));1714luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */1715g->gcstate = GCSenteratomic; /* go straight to atomic phase */1716luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */1717/* estimate must be correct after a full GC cycle */1718lua_assert(g->GCestimate == gettotalbytes(g));1719luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */1720setpause(g);1721}172217231724/*1725** Performs a full GC cycle; if 'isemergency', set a flag to avoid1726** some operations which could change the interpreter state in some1727** unexpected ways (running finalizers and shrinking some structures).1728*/1729void luaC_fullgc (lua_State *L, int isemergency) {1730global_State *g = G(L);1731lua_assert(!g->gcemergency);1732g->gcemergency = isemergency; /* set flag */1733if (g->gckind == KGC_INC)1734fullinc(L, g);1735else1736fullgen(L, g);1737g->gcemergency = 0;1738}17391740/* }====================================================== */17411742174317441745