C functions and strings now go to the local list; first version
of the local collector
This commit is contained in:
102
lgc.c
102
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 */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user