lgc.cpp

Go to the documentation of this file.
00001 /*
00002 ** $Id: lgc.c,v 2.38 2006/05/24 14:34:06 roberto Exp $
00003 ** Garbage Collector
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 #include <string.h>
00008 
00009 #define lgc_c
00010 #define LUA_CORE
00011 
00012 #include "lua.h"
00013 
00014 #include "ldebug.h"
00015 #include "ldo.h"
00016 #include "lfunc.h"
00017 #include "lgc.h"
00018 #include "lmem.h"
00019 #include "lobject.h"
00020 #include "lstate.h"
00021 #include "lstring.h"
00022 #include "ltable.h"
00023 #include "ltm.h"
00024 
00025 
00026 #define GCSTEPSIZE      1024u
00027 #define GCSWEEPMAX      40
00028 #define GCSWEEPCOST     10
00029 #define GCFINALIZECOST  100
00030 
00031 
00032 #define maskmarks       cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
00033 
00034 #define makewhite(g,x)  \
00035    ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
00036 
00037 #define white2gray(x)   reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
00038 #define black2gray(x)   resetbit((x)->gch.marked, BLACKBIT)
00039 
00040 #define stringmark(s)   reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
00041 
00042 
00043 #define isfinalized(u)          testbit((u)->marked, FINALIZEDBIT)
00044 #define markfinalized(u)        l_setbit((u)->marked, FINALIZEDBIT)
00045 
00046 
00047 #define KEYWEAK         bitmask(KEYWEAKBIT)
00048 #define VALUEWEAK       bitmask(VALUEWEAKBIT)
00049 
00050 
00051 
00052 #define markvalue(g,o) { checkconsistency(o); \
00053   if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
00054 
00055 #define markobject(g,t) { if (iswhite(obj2gco(t))) \
00056                 reallymarkobject(g, obj2gco(t)); }
00057 
00058 
00059 #define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)
00060 
00061 
00062 static void removeentry (Node *n) {
00063   lua_assert(ttisnil(gval(n)));
00064   if (iscollectable(gkey(n)))
00065     setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */
00066 }
00067 
00068 
00069 static void reallymarkobject (global_State *g, GCObject *o) {
00070   lua_assert(iswhite(o) && !isdead(g, o));
00071   white2gray(o);
00072   switch (o->gch.tt) {
00073     case LUA_TSTRING: {
00074       return;
00075     }
00076     case LUA_TUSERDATA: {
00077       Table *mt = gco2u(o)->metatable;
00078       gray2black(o);  /* udata are never gray */
00079       if (mt) markobject(g, mt);
00080       markobject(g, gco2u(o)->env);
00081       return;
00082     }
00083     case LUA_TUPVAL: {
00084       UpVal *uv = gco2uv(o);
00085       markvalue(g, uv->v);
00086       if (uv->v == &uv->u.value)  /* closed? */
00087         gray2black(o);  /* open upvalues are never black */
00088       return;
00089     }
00090     case LUA_TFUNCTION: {
00091       gco2cl(o)->c.gclist = g->gray;
00092       g->gray = o;
00093       break;
00094     }
00095     case LUA_TTABLE: {
00096       gco2h(o)->gclist = g->gray;
00097       g->gray = o;
00098       break;
00099     }
00100     case LUA_TTHREAD: {
00101       gco2th(o)->gclist = g->gray;
00102       g->gray = o;
00103       break;
00104     }
00105     case LUA_TPROTO: {
00106       gco2p(o)->gclist = g->gray;
00107       g->gray = o;
00108       break;
00109     }
00110     default: lua_assert(0);
00111   }
00112 }
00113 
00114 
00115 static void marktmu (global_State *g) {
00116   GCObject *u = g->tmudata;
00117   if (u) {
00118     do {
00119       u = u->gch.next;
00120       makewhite(g, u);  /* may be marked, if left from previous GC */
00121       reallymarkobject(g, u);
00122     } while (u != g->tmudata);
00123   }
00124 }
00125 
00126 
00127 /* move `dead' udata that need finalization to list `tmudata' */
00128 size_t luaC_separateudata (lua_State *L, int all) {
00129   global_State *g = G(L);
00130   size_t deadmem = 0;
00131   GCObject **p = &g->mainthread->next;
00132   GCObject *curr;
00133   while ((curr = *p) != NULL) {
00134     if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
00135       p = &curr->gch.next;  /* don't bother with them */
00136     else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
00137       markfinalized(gco2u(curr));  /* don't need finalization */
00138       p = &curr->gch.next;
00139     }
00140     else {  /* must call its gc method */
00141       deadmem += sizeudata(gco2u(curr));
00142       markfinalized(gco2u(curr));
00143       *p = curr->gch.next;
00144       /* link `curr' at the end of `tmudata' list */
00145       if (g->tmudata == NULL)  /* list is empty? */
00146         g->tmudata = curr->gch.next = curr;  /* creates a circular list */
00147       else {
00148         curr->gch.next = g->tmudata->gch.next;
00149         g->tmudata->gch.next = curr;
00150         g->tmudata = curr;
00151       }
00152     }
00153   }
00154   return deadmem;
00155 }
00156 
00157 
00158 static int traversetable (global_State *g, Table *h) {
00159   int i;
00160   int weakkey = 0;
00161   int weakvalue = 0;
00162   const TValue *mode;
00163   if (h->metatable)
00164     markobject(g, h->metatable);
00165   mode = gfasttm(g, h->metatable, TM_MODE);
00166   if (mode && ttisstring(mode)) {  /* is there a weak mode? */
00167     weakkey = (strchr(svalue(mode), 'k') != NULL);
00168     weakvalue = (strchr(svalue(mode), 'v') != NULL);
00169     if (weakkey || weakvalue) {  /* is really weak? */
00170       h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */
00171       h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
00172                              (weakvalue << VALUEWEAKBIT));
00173       h->gclist = g->weak;  /* must be cleared after GC, ... */
00174       g->weak = obj2gco(h);  /* ... so put in the appropriate list */
00175     }
00176   }
00177   if (weakkey && weakvalue) return 1;
00178   if (!weakvalue) {
00179     i = h->sizearray;
00180     while (i--)
00181       markvalue(g, &h->array[i]);
00182   }
00183   i = sizenode(h);
00184   while (i--) {
00185     Node *n = gnode(h, i);
00186     lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
00187     if (ttisnil(gval(n)))
00188       removeentry(n);  /* remove empty entries */
00189     else {
00190       lua_assert(!ttisnil(gkey(n)));
00191       if (!weakkey) markvalue(g, gkey(n));
00192       if (!weakvalue) markvalue(g, gval(n));
00193     }
00194   }
00195   return weakkey || weakvalue;
00196 }
00197 
00198 
00199 /*
00200 ** All marks are conditional because a GC may happen while the
00201 ** prototype is still being created
00202 */
00203 static void traverseproto (global_State *g, Proto *f) {
00204   int i;
00205   if (f->source) stringmark(f->source);
00206   for (i=0; i<f->sizek; i++)  /* mark literals */
00207     markvalue(g, &f->k[i]);
00208   for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */
00209     if (f->upvalues[i])
00210       stringmark(f->upvalues[i]);
00211   }
00212   for (i=0; i<f->sizep; i++) {  /* mark nested protos */
00213     if (f->p[i])
00214       markobject(g, f->p[i]);
00215   }
00216   for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */
00217     if (f->locvars[i].varname)
00218       stringmark(f->locvars[i].varname);
00219   }
00220 }
00221 
00222 
00223 
00224 static void traverseclosure (global_State *g, Closure *cl) {
00225   markobject(g, cl->c.env);
00226   if (cl->c.isC) {
00227     int i;
00228     for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */
00229       markvalue(g, &cl->c.upvalue[i]);
00230   }
00231   else {
00232     int i;
00233     lua_assert(cl->l.nupvalues == cl->l.p->nups);
00234     markobject(g, cl->l.p);
00235     for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */
00236       markobject(g, cl->l.upvals[i]);
00237   }
00238 }
00239 
00240 
00241 static void checkstacksizes (lua_State *L, StkId max) {
00242   int ci_used = cast_int(L->ci - L->base_ci);  /* number of `ci' in use */
00243   int s_used = cast_int(max - L->stack);  /* part of stack in use */
00244   if (L->size_ci > LUAI_MAXCALLS)  /* handling overflow? */
00245     return;  /* do not touch the stacks */
00246   if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
00247     luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */
00248   condhardstacktests(luaD_reallocCI(L, ci_used + 1));
00249   if (4*s_used < L->stacksize &&
00250       2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
00251     luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */
00252   condhardstacktests(luaD_reallocstack(L, s_used));
00253 }
00254 
00255 
00256 static void traversestack (global_State *g, lua_State *l) {
00257   StkId o, lim;
00258   CallInfo *ci;
00259   markvalue(g, gt(l));
00260   lim = l->top;
00261   for (ci = l->base_ci; ci <= l->ci; ci++) {
00262     lua_assert(ci->top <= l->stack_last);
00263     if (lim < ci->top) lim = ci->top;
00264   }
00265   for (o = l->stack; o < l->top; o++)
00266     markvalue(g, o);
00267   for (; o <= lim; o++)
00268     setnilvalue(o);
00269   checkstacksizes(l, lim);
00270 }
00271 
00272 
00273 /*
00274 ** traverse one gray object, turning it to black.
00275 ** Returns `quantity' traversed.
00276 */
00277 static l_mem propagatemark (global_State *g) {
00278   GCObject *o = g->gray;
00279   lua_assert(isgray(o));
00280   gray2black(o);
00281   switch (o->gch.tt) {
00282     case LUA_TTABLE: {
00283       Table *h = gco2h(o);
00284       g->gray = h->gclist;
00285       if (traversetable(g, h))  /* table is weak? */
00286         black2gray(o);  /* keep it gray */
00287       return sizeof(Table) + sizeof(TValue) * h->sizearray +
00288                              sizeof(Node) * sizenode(h);
00289     }
00290     case LUA_TFUNCTION: {
00291       Closure *cl = gco2cl(o);
00292       g->gray = cl->c.gclist;
00293       traverseclosure(g, cl);
00294       return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
00295                            sizeLclosure(cl->l.nupvalues);
00296     }
00297     case LUA_TTHREAD: {
00298       lua_State *th = gco2th(o);
00299       g->gray = th->gclist;
00300       th->gclist = g->grayagain;
00301       g->grayagain = o;
00302       black2gray(o);
00303       traversestack(g, th);
00304       return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
00305                                  sizeof(CallInfo) * th->size_ci;
00306     }
00307     case LUA_TPROTO: {
00308       Proto *p = gco2p(o);
00309       g->gray = p->gclist;
00310       traverseproto(g, p);
00311       return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
00312                              sizeof(Proto *) * p->sizep +
00313                              sizeof(TValue) * p->sizek + 
00314                              sizeof(int) * p->sizelineinfo +
00315                              sizeof(LocVar) * p->sizelocvars +
00316                              sizeof(TString *) * p->sizeupvalues;
00317     }
00318     default: lua_assert(0); return 0;
00319   }
00320 }
00321 
00322 
00323 static size_t propagateall (global_State *g) {
00324   size_t m = 0;
00325   while (g->gray) m += propagatemark(g);
00326   return m;
00327 }
00328 
00329 
00330 /*
00331 ** The next function tells whether a key or value can be cleared from
00332 ** a weak table. Non-collectable objects are never removed from weak
00333 ** tables. Strings behave as `values', so are never removed too. for
00334 ** other objects: if really collected, cannot keep them; for userdata
00335 ** being finalized, keep them in keys, but not in values
00336 */
00337 static int iscleared (const TValue *o, int iskey) {
00338   if (!iscollectable(o)) return 0;
00339   if (ttisstring(o)) {
00340     stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */
00341     return 0;
00342   }
00343   return iswhite(gcvalue(o)) ||
00344     (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
00345 }
00346 
00347 
00348 /*
00349 ** clear collected entries from weaktables
00350 */
00351 static void cleartable (GCObject *l) {
00352   while (l) {
00353     Table *h = gco2h(l);
00354     int i = h->sizearray;
00355     lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
00356                testbit(h->marked, KEYWEAKBIT));
00357     if (testbit(h->marked, VALUEWEAKBIT)) {
00358       while (i--) {
00359         TValue *o = &h->array[i];
00360         if (iscleared(o, 0))  /* value was collected? */
00361           setnilvalue(o);  /* remove value */
00362       }
00363     }
00364     i = sizenode(h);
00365     while (i--) {
00366       Node *n = gnode(h, i);
00367       if (!ttisnil(gval(n)) &&  /* non-empty entry? */
00368           (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
00369         setnilvalue(gval(n));  /* remove value ... */
00370         removeentry(n);  /* remove entry from table */
00371       }
00372     }
00373     l = h->gclist;
00374   }
00375 }
00376 
00377 
00378 static void freeobj (lua_State *L, GCObject *o) {
00379   switch (o->gch.tt) {
00380     case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
00381     case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
00382     case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
00383     case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
00384     case LUA_TTHREAD: {
00385       lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
00386       luaE_freethread(L, gco2th(o));
00387       break;
00388     }
00389     case LUA_TSTRING: {
00390       G(L)->strt.nuse--;
00391       luaM_freemem(L, o, sizestring(gco2ts(o)));
00392       break;
00393     }
00394     case LUA_TUSERDATA: {
00395       luaM_freemem(L, o, sizeudata(gco2u(o)));
00396       break;
00397     }
00398     default: lua_assert(0);
00399   }
00400 }
00401 
00402 
00403 
00404 #define sweepwholelist(L,p)     sweeplist(L,p,MAX_LUMEM)
00405 
00406 
00407 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
00408   GCObject *curr;
00409   global_State *g = G(L);
00410   int deadmask = otherwhite(g);
00411   while ((curr = *p) != NULL && count-- > 0) {
00412     if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */
00413       sweepwholelist(L, &gco2th(curr)->openupval);
00414     if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */
00415       lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
00416       makewhite(g, curr);  /* make it white (for next cycle) */
00417       p = &curr->gch.next;
00418     }
00419     else {  /* must erase `curr' */
00420       lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
00421       *p = curr->gch.next;
00422       if (curr == g->rootgc)  /* is the first element of the list? */
00423         g->rootgc = curr->gch.next;  /* adjust first */
00424       freeobj(L, curr);
00425     }
00426   }
00427   return p;
00428 }
00429 
00430 
00431 static void checkSizes (lua_State *L) {
00432   global_State *g = G(L);
00433   /* check size of string hash */
00434   if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
00435       g->strt.size > MINSTRTABSIZE*2)
00436     luaS_resize(L, g->strt.size/2);  /* table is too big */
00437   /* check size of buffer */
00438   if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */
00439     size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
00440     luaZ_resizebuffer(L, &g->buff, newsize);
00441   }
00442 }
00443 
00444 
00445 static void GCTM (lua_State *L) {
00446   global_State *g = G(L);
00447   GCObject *o = g->tmudata->gch.next;  /* get first element */
00448   Udata *udata = rawgco2u(o);
00449   const TValue *tm;
00450   /* remove udata from `tmudata' */
00451   if (o == g->tmudata)  /* last element? */
00452     g->tmudata = NULL;
00453   else
00454     g->tmudata->gch.next = udata->uv.next;
00455   udata->uv.next = g->mainthread->next;  /* return it to `root' list */
00456   g->mainthread->next = o;
00457   makewhite(g, o);
00458   tm = fasttm(L, udata->uv.metatable, TM_GC);
00459   if (tm != NULL) {
00460     lu_byte oldah = L->allowhook;
00461     lu_mem oldt = g->GCthreshold;
00462     L->allowhook = 0;  /* stop debug hooks during GC tag method */
00463     g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */
00464     setobj2s(L, L->top, tm);
00465     setuvalue(L, L->top+1, udata);
00466     L->top += 2;
00467     luaD_call(L, L->top - 2, 0);
00468     L->allowhook = oldah;  /* restore hooks */
00469     g->GCthreshold = oldt;  /* restore threshold */
00470   }
00471 }
00472 
00473 
00474 /*
00475 ** Call all GC tag methods
00476 */
00477 void luaC_callGCTM (lua_State *L) {
00478   while (G(L)->tmudata)
00479     GCTM(L);
00480 }
00481 
00482 
00483 void luaC_freeall (lua_State *L) {
00484   global_State *g = G(L);
00485   int i;
00486   g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */
00487   sweepwholelist(L, &g->rootgc);
00488   for (i = 0; i < g->strt.size; i++)  /* free all string lists */
00489     sweepwholelist(L, &g->strt.hash[i]);
00490 }
00491 
00492 
00493 static void markmt (global_State *g) {
00494   int i;
00495   for (i=0; i<NUM_TAGS; i++)
00496     if (g->mt[i]) markobject(g, g->mt[i]);
00497 }
00498 
00499 
00500 /* mark root set */
00501 static void markroot (lua_State *L) {
00502   global_State *g = G(L);
00503   g->gray = NULL;
00504   g->grayagain = NULL;
00505   g->weak = NULL;
00506   markobject(g, g->mainthread);
00507   /* make global table be traversed before main stack */
00508   markvalue(g, gt(g->mainthread));
00509   markvalue(g, registry(L));
00510   markmt(g);
00511   g->gcstate = GCSpropagate;
00512 }
00513 
00514 
00515 static void remarkupvals (global_State *g) {
00516   UpVal *uv;
00517   for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
00518     lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
00519     if (isgray(obj2gco(uv)))
00520       markvalue(g, uv->v);
00521   }
00522 }
00523 
00524 
00525 static void atomic (lua_State *L) {
00526   global_State *g = G(L);
00527   size_t udsize;  /* total size of userdata to be finalized */
00528   /* remark occasional upvalues of (maybe) dead threads */
00529   remarkupvals(g);
00530   /* traverse objects cautch by write barrier and by 'remarkupvals' */
00531   propagateall(g);
00532   /* remark weak tables */
00533   g->gray = g->weak;
00534   g->weak = NULL;
00535   lua_assert(!iswhite(obj2gco(g->mainthread)));
00536   markobject(g, L);  /* mark running thread */
00537   markmt(g);  /* mark basic metatables (again) */
00538   propagateall(g);
00539   /* remark gray again */
00540   g->gray = g->grayagain;
00541   g->grayagain = NULL;
00542   propagateall(g);
00543   udsize = luaC_separateudata(L, 0);  /* separate userdata to be finalized */
00544   marktmu(g);  /* mark `preserved' userdata */
00545   udsize += propagateall(g);  /* remark, to propagate `preserveness' */
00546   cleartable(g->weak);  /* remove collected objects from weak tables */
00547   /* flip current white */
00548   g->currentwhite = cast_byte(otherwhite(g));
00549   g->sweepstrgc = 0;
00550   g->sweepgc = &g->rootgc;
00551   g->gcstate = GCSsweepstring;
00552   g->estimate = g->totalbytes - udsize;  /* first estimate */
00553 }
00554 
00555 
00556 static l_mem singlestep (lua_State *L) {
00557   global_State *g = G(L);
00558   /*lua_checkmemory(L);*/
00559   switch (g->gcstate) {
00560     case GCSpause: {
00561       markroot(L);  /* start a new collection */
00562       return 0;
00563     }
00564     case GCSpropagate: {
00565       if (g->gray)
00566         return propagatemark(g);
00567       else {  /* no more `gray' objects */
00568         atomic(L);  /* finish mark phase */
00569         return 0;
00570       }
00571     }
00572     case GCSsweepstring: {
00573       lu_mem old = g->totalbytes;
00574       sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
00575       if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */
00576         g->gcstate = GCSsweep;  /* end sweep-string phase */
00577       lua_assert(old >= g->totalbytes);
00578       g->estimate -= old - g->totalbytes;
00579       return GCSWEEPCOST;
00580     }
00581     case GCSsweep: {
00582       lu_mem old = g->totalbytes;
00583       g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
00584       if (*g->sweepgc == NULL) {  /* nothing more to sweep? */
00585         checkSizes(L);
00586         g->gcstate = GCSfinalize;  /* end sweep phase */
00587       }
00588       lua_assert(old >= g->totalbytes);
00589       g->estimate -= old - g->totalbytes;
00590       return GCSWEEPMAX*GCSWEEPCOST;
00591     }
00592     case GCSfinalize: {
00593       if (g->tmudata) {
00594         GCTM(L);
00595         if (g->estimate > GCFINALIZECOST)
00596           g->estimate -= GCFINALIZECOST;
00597         return GCFINALIZECOST;
00598       }
00599       else {
00600         g->gcstate = GCSpause;  /* end collection */
00601         g->gcdept = 0;
00602         return 0;
00603       }
00604     }
00605     default: lua_assert(0); return 0;
00606   }
00607 }
00608 
00609 
00610 void luaC_step (lua_State *L) {
00611   global_State *g = G(L);
00612   l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
00613   if (lim == 0)
00614     lim = (MAX_LUMEM-1)/2;  /* no limit */
00615   g->gcdept += g->totalbytes - g->GCthreshold;
00616   do {
00617     lim -= singlestep(L);
00618     if (g->gcstate == GCSpause)
00619       break;
00620   } while (lim > 0);
00621   if (g->gcstate != GCSpause) {
00622     if (g->gcdept < GCSTEPSIZE)
00623       g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/
00624     else {
00625       g->gcdept -= GCSTEPSIZE;
00626       g->GCthreshold = g->totalbytes;
00627     }
00628   }
00629   else {
00630     lua_assert(g->totalbytes >= g->estimate);
00631     setthreshold(g);
00632   }
00633 }
00634 
00635 
00636 void luaC_fullgc (lua_State *L) {
00637   global_State *g = G(L);
00638   if (g->gcstate <= GCSpropagate) {
00639     /* reset sweep marks to sweep all elements (returning them to white) */
00640     g->sweepstrgc = 0;
00641     g->sweepgc = &g->rootgc;
00642     /* reset other collector lists */
00643     g->gray = NULL;
00644     g->grayagain = NULL;
00645     g->weak = NULL;
00646     g->gcstate = GCSsweepstring;
00647   }
00648   lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
00649   /* finish any pending sweep phase */
00650   while (g->gcstate != GCSfinalize) {
00651     lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
00652     singlestep(L);
00653   }
00654   markroot(L);
00655   while (g->gcstate != GCSpause) {
00656     singlestep(L);
00657   }
00658   setthreshold(g);
00659 }
00660 
00661 
00662 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
00663   global_State *g = G(L);
00664   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
00665   lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
00666   lua_assert(ttype(&o->gch) != LUA_TTABLE);
00667   /* must keep invariant? */
00668   if (g->gcstate == GCSpropagate)
00669     reallymarkobject(g, v);  /* restore invariant */
00670   else  /* don't mind */
00671     makewhite(g, o);  /* mark as white just to avoid other barriers */
00672 }
00673 
00674 
00675 void luaC_barrierback (lua_State *L, Table *t) {
00676   global_State *g = G(L);
00677   GCObject *o = obj2gco(t);
00678   lua_assert(isblack(o) && !isdead(g, o));
00679   lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
00680   black2gray(o);  /* make table gray (again) */
00681   t->gclist = g->grayagain;
00682   g->grayagain = o;
00683 }
00684 
00685 
00686 void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
00687   global_State *g = G(L);
00688   o->gch.next = g->rootgc;
00689   g->rootgc = o;
00690   o->gch.marked = luaC_white(g);
00691   o->gch.tt = tt;
00692 }
00693 
00694 
00695 void luaC_linkupval (lua_State *L, UpVal *uv) {
00696   global_State *g = G(L);
00697   GCObject *o = obj2gco(uv);
00698   o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */
00699   g->rootgc = o;
00700   if (isgray(o)) { 
00701     if (g->gcstate == GCSpropagate) {
00702       gray2black(o);  /* closed upvalues need barrier */
00703       luaC_barrier(L, uv, uv->v);
00704     }
00705     else {  /* sweep phase: sweep it (turning it into white) */
00706       makewhite(g, o);
00707       lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
00708     }
00709   }
00710 }
00711 

Generated on Mon Feb 16 15:14:50 2009 for Scorched3D by  doxygen 1.5.3