reuse `sweeplist' for all lists

This commit is contained in:
Roberto Ierusalimschy 2004-03-23 09:57:12 -03:00
parent 24f2d1183c
commit 178246062c

83
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.4 2004/03/09 17:34:35 roberto Exp roberto $ ** $Id: lgc.c,v 2.5 2004/03/15 21:04:33 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -25,6 +25,7 @@
#define GCSTEPSIZE (40*sizeof(TValue)) #define GCSTEPSIZE (40*sizeof(TValue))
#define GCFREECOST (sizeof(TValue)/2) #define GCFREECOST (sizeof(TValue)/2)
#define GCSWEEPCOST sizeof(TValue) #define GCSWEEPCOST sizeof(TValue)
#define GCFINALIZECOST (10*sizeof(TValue))
#define FIXEDMASK bitmask(FIXEDBIT) #define FIXEDMASK bitmask(FIXEDBIT)
@ -392,31 +393,22 @@ static void freeobj (lua_State *L, GCObject *o) {
} }
static void sweepupvalues (global_State *g, lua_State *l) { static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
GCObject *curr; lu_int32 *count);
for (curr = l->openupval; curr != NULL; curr = curr->gch.next)
makewhite(g, curr);
}
/*
** macros to test dead bit and optionally the fix bit
*/
#define makedeadmask(g,kf) (otherwhite(g) | ((kf) ? FIXEDMASK : 0))
#define notdead(mark,mask) ((((mark) ^ FIXEDMASK) & mask) != mask)
static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
l_mem *plim) { l_mem *plim, lu_int32 *count) {
GCObject *curr; GCObject *curr;
global_State *g = G(L); global_State *g = G(L);
l_mem lim = *plim; l_mem lim = *plim;
int deadmask = makedeadmask(g, keepfixed); int deadmask = otherwhite(g);
if (keepfixed) deadmask |= FIXEDMASK;
while ((curr = *p) != NULL) { while ((curr = *p) != NULL) {
if (notdead(curr->gch.marked, deadmask)) { if (((curr->gch.marked ^ FIXEDMASK) & deadmask) != deadmask) {
makewhite(g, curr); makewhite(g, curr);
if (curr->gch.tt == LUA_TTHREAD) if (curr->gch.tt == LUA_TTHREAD)
sweepupvalues(g, gco2th(curr)); lim -= sweepwholelist(L, &gco2th(curr)->openupval, keepfixed, count);
p = &curr->gch.next; p = &curr->gch.next;
lim -= GCSWEEPCOST; lim -= GCSWEEPCOST;
} }
@ -427,6 +419,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
g->rootgc = curr->gch.next; /* adjust first */ g->rootgc = curr->gch.next; /* adjust first */
freeobj(L, curr); freeobj(L, curr);
lim -= GCFREECOST; lim -= GCFREECOST;
if (count) (*count)--;
} }
if (lim <= 0) break; if (lim <= 0) break;
} }
@ -435,28 +428,20 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
} }
static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
lu_int32 *count) {
l_mem lim = MAXLMEM;
/* empty lists are quite common here, so avoid useless calls */
if (*p) sweeplist(L, p, keepfixed, &lim, count);
return MAXLMEM - lim;
}
static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) { static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) {
int i; int i;
global_State *g = G(L); global_State *g = G(L);
int deadmask = makedeadmask(g, keepfixed);
for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */
GCObject *curr; lim -= sweepwholelist(L, &G(L)->strt.hash[i], keepfixed, &g->strt.nuse);
GCObject **p = &G(L)->strt.hash[i];
while ((curr = *p) != NULL) {
lu_mem size = sizestring(gco2ts(curr)->len);
if (notdead(curr->gch.marked, deadmask)) {
makewhite(g, curr);
lua_assert(iswhite(curr) && !isdead(g, curr));
p = &curr->gch.next;
}
else {
lua_assert(iswhite(curr));
g->strt.nuse--;
*p = curr->gch.next;
luaM_free(L, curr, size);
}
lim -= size;
}
if (lim <= 0) break; if (lim <= 0) break;
} }
g->sweepstrgc = i+1; g->sweepstrgc = i+1;
@ -513,16 +498,15 @@ void luaC_sweepall (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
l_mem dummy = MAXLMEM; l_mem dummy = MAXLMEM;
/* finish (occasional) current sweep */ /* finish (occasional) current sweep */
markobject(g, g->mainthread); /* cannot collect main thread */
sweepstrings(L, 0, MAXLMEM); sweepstrings(L, 0, MAXLMEM);
sweeplist(L, &g->rootgc, 0, &dummy); sweeplist(L, &g->rootgc, 0, &dummy, NULL);
/* do a whole new sweep */ /* do a whole new sweep */
markobject(g, g->mainthread); /* cannot collect main thread */ markobject(g, g->mainthread); /* cannot collect main thread */
g->currentwhite = otherwhite(g); g->currentwhite = otherwhite(g);
g->sweepgc = &g->rootgc; g->sweepgc = &g->rootgc;
g->sweepstrgc = 0; g->sweepstrgc = 0;
sweepstrings(L, 0, MAXLMEM); sweepstrings(L, 0, MAXLMEM);
sweeplist(L, &g->rootgc, 0, &dummy); sweeplist(L, &g->rootgc, 0, &dummy, NULL);
} }
@ -532,10 +516,10 @@ static void markroot (lua_State *L) {
lua_assert(g->gray == NULL); lua_assert(g->gray == NULL);
g->grayagain = NULL; g->grayagain = NULL;
g->weak = NULL; g->weak = NULL;
makewhite(g, obj2gco(g->mainthread));
markobject(g, g->mainthread); markobject(g, g->mainthread);
/* make global table be traversed before main stack */
markvalue(g, gt(g->mainthread));
markvalue(g, registry(L)); markvalue(g, registry(L));
markobject(g, L); /* mark running thread */
g->gcstate = GCSpropagate; g->gcstate = GCSpropagate;
} }
@ -600,7 +584,7 @@ static l_mem singlestep (lua_State *L, l_mem lim) {
break; break;
} }
case GCSsweep: { case GCSsweep: {
g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim); g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim, NULL);
if (*g->sweepgc == NULL) { /* nothing more to sweep? */ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
checkSizes(L); checkSizes(L);
g->sweepgc = &g->rootgc; g->sweepgc = &g->rootgc;
@ -609,11 +593,14 @@ static l_mem singlestep (lua_State *L, l_mem lim) {
break; break;
} }
case GCSfinalize: { case GCSfinalize: {
if (g->tmudata) if (g->tmudata) {
GCTM(L); GCTM(L);
else /* no more `udata' to finalize */ lim -= GCFINALIZECOST;
}
else { /* no more `udata' to finalize */
markroot(L); /* may restart collection */ markroot(L); /* may restart collection */
lim = 0; lim = 0;
}
break; break;
} }
default: lua_assert(0); default: lua_assert(0);
@ -625,10 +612,12 @@ static l_mem singlestep (lua_State *L, l_mem lim) {
void luaC_step (lua_State *L) { void luaC_step (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2; l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
/*printf("+ %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/ do {
while (lim > 0) lim = singlestep(L, lim); lim = singlestep(L, lim);
if (g->gcstate == GCSfinalize && g->tmudata == NULL)
break; /* do not start new collection */
} while (lim > 0);
g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
/*printf("- %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/
lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2); lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2);
} }