From 50955e27f592441a223c6267956e470f98eeb3c0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 23 Aug 2013 10:34:54 -0300 Subject: C functions and strings now go to the local list; first version of the local collector --- lgc.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 8 deletions(-) (limited to 'lgc.c') diff --git a/lgc.c b/lgc.c index fddc43cf..c261bd73 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.149 2013/08/21 19:21:16 roberto Exp roberto $ +** $Id: lgc.c,v 2.150 2013/08/21 20:09:51 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -24,6 +24,12 @@ +/* +** How memory to allocate before a new local collection +*/ +#define GCLOCALPAUSE 8000 + + /* ** cost of sweeping one element (the size of a small object divided ** by some adjust for the sweep speed) @@ -191,9 +197,9 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { void luaC_fix (lua_State *L, GCObject *o) { global_State *g = G(L); - lua_assert(g->allgc == o); + lua_assert(g->localgc == o); white2gray(o); - g->allgc = o->gch.next; /* remove object from 'allgc' list */ + g->localgc = o->gch.next; /* remove object from 'localgc' list */ o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ g->fixedgc = o; } @@ -873,6 +879,72 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { /* }====================================================== */ +/* +** {====================================================== +** Local Collection +** ======================================================= +*/ + +/* +** Traverse a thread, local marking all its collectable objects +*/ +static void localmarkthread (lua_State *l) { + StkId o = l->stack; + if (o == NULL) + return; /* stack not completely built yet */ + for (; o < l->top; o++) { /* mark live elements in the stack */ + if (iscollectable(o)) + l_setbit(gcvalue(o)->gch.marked, LOCALBLACK); + } +} + + +/* +** Mark all that is locally accessible (accessible directly from +** a thread) +*/ +static void localmark (global_State *g) { + GCObject *thread = hvalue(&g->l_registry)->next; + for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ + localmarkthread(gco2th(thread)); + localmarkthread(g->mainthread); +} + + +static void localsweep (lua_State *L, global_State *g) { + GCObject **p = &g->localgc; + while (*p != NULL) { + GCObject *curr = *p; + if (!islocal(curr)) { /* is 'curr' no more local? */ + *p = curr->gch.next; /* remove 'curr' from list */ + curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ + g->allgc = curr; + } + else { /* still local */ + if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ + resetbit(curr->gch.marked, LOCALBLACK); + p = &curr->gch.next; /* go to next element */ + } + else { /* object is dead */ + *p = curr->gch.next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + } + } +} + + +static void luaC_localcollection (lua_State *L) { + global_State *g = G(L); + lua_assert(g->gcstate == GCSpause); + localmark(g); + localsweep(L, g); +} + +/* }====================================================== */ + + + /* ** {====================================================== ** GC control @@ -885,13 +957,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** cycle will start when memory use hits threshold */ static void setpause (global_State *g, l_mem estimate) { - l_mem debt, threshold; + l_mem threshold; estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ ? estimate * g->gcpause /* no overflow */ : MAX_LMEM; /* overflow; truncate to maximum */ - debt = -cast(l_mem, threshold - gettotalbytes(g)); - luaE_setdebt(g, debt); + g->GCthreshold = threshold; + luaE_setdebt(g, -GCLOCALPAUSE); } @@ -936,6 +1008,7 @@ void luaC_freeallobjects (lua_State *L) { g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->gckind = KGC_NORMAL; sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ + sweepwholelist(L, &g->localgc); sweepwholelist(L, &g->allgc); sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ lua_assert(g->strt.nuse == 0); @@ -1017,8 +1090,9 @@ static lu_mem singlestep (lua_State *L) { return GCSWEEPMAX*GCSWEEPCOST; } else { + sweepwholelist(L, &g->localgc); g->gcstate = GCSsweep; - return 0; + return GCLOCALPAUSE / 4; /* some magic for now */ } } case GCSsweep: { @@ -1090,7 +1164,19 @@ void luaC_forcestep (lua_State *L) { */ void luaC_step (lua_State *L) { global_State *g = G(L); - if (g->gcrunning) luaC_forcestep(L); + if (g->gcrunning) { + if (g->gcstate != GCSpause) { + luaC_forcestep(L); + } + else { + luaC_localcollection(L); + if (gettotalbytes(g) > g->GCthreshold) { + luaC_forcestep(L); /* restart collection */ + } + else + luaE_setdebt(g, -GCLOCALPAUSE); + } + } else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ } -- cgit v1.2.3-55-g6feb