First version of incremental GC

This commit is contained in:
Roberto Ierusalimschy
2003-12-09 14:56:11 -02:00
parent fe595a45c2
commit df429f163a
9 changed files with 118 additions and 64 deletions

75
lgc.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 1.185 2003/12/04 17:22:42 roberto Exp roberto $
** $Id: lgc.c,v 1.186 2003/12/04 18:52:23 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -25,12 +25,8 @@
#define GCSTEPSIZE (20*sizeof(TObject))
#define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT))
#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define maskmarks \
cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
#define makewhite(g,x) \
@@ -47,7 +43,6 @@
#define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT)
#define KEYWEAK bitmask(KEYWEAKBIT)
#define VALUEWEAK bitmask(VALUEWEAKBIT)
@@ -110,7 +105,7 @@ static size_t objsize (GCObject *o) {
static void reallymarkobject (global_State *g, GCObject *o) {
lua_assert(iswhite(o));
lua_assert(!(o->gch.marked & otherwhite(g)));
lua_assert(!isdead(g, o));
white2gray(o);
switch (o->gch.tt) {
case LUA_TSTRING: {
@@ -118,6 +113,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
}
case LUA_TUSERDATA: {
Table *mt = gcotou(o)->uv.metatable;
gray2black(o); /* udata are never gray */
if (mt) markobject(g, mt);
return;
}
@@ -442,7 +438,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
int dead = otherwhite(g);
while ((curr = *p) != NULL) {
int mark = curr->gch.marked;
lua_assert(all || !(mark & g->currentwhite));
lim -= objsize(curr);
if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
makewhite(g, curr);
@@ -469,9 +464,9 @@ static l_mem sweepstrings (lua_State *L, int all, l_mem lim) {
while ((curr = *p) != NULL) {
int mark = curr->gch.marked;
lu_mem size = sizestring(gcotots(curr)->tsv.len);
lua_assert(all || !(mark & g->currentwhite));
if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
makewhite(g, curr);
lua_assert(iswhite(curr) && !isdead(g, curr));
p = &curr->gch.next;
}
else {
@@ -499,8 +494,6 @@ static void checkSizes (lua_State *L) {
size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
luaZ_resizebuffer(L, &g->buff, newsize);
}
lua_assert(g->nblocks > g->GCthreshold);
g->GCthreshold = 2*G(L)->nblocks - g->GCthreshold; /* new threshold */
}
@@ -562,11 +555,13 @@ static void markroot (lua_State *L) {
static void atomic (lua_State *L) {
global_State *g = G(L);
/* there may be some gray elements due to the write barrier */
propagatemarks(g, MAXLMEM); /* traverse them */
lua_assert(g->gray == NULL);
g->gray = g->grayagain;
g->grayagain = NULL;
propagatemarks(g, MAXLMEM);
g->GCthreshold = luaC_separateudata(L); /* separate userdata to be preserved */
luaC_separateudata(L); /* separate userdata to be preserved */
marktmu(g); /* mark `preserved' userdata */
propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
cleartable(g->weak); /* remove collected objects from weak tables */
@@ -597,30 +592,48 @@ static void sweepstep (lua_State *L) {
global_State *g = G(L);
l_mem lim = GCSTEPSIZE;
g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
if (lim == GCSTEPSIZE) /* nothing more to sweep? */
if (lim == GCSTEPSIZE) { /* nothing more to sweep? */
g->gcstate = GCSfinalize; /* end sweep phase */
checkSizes(L);
}
}
void luaC_collectgarbage (lua_State *L) {
void luaC_step (lua_State *L) {
global_State *g = G(L);
/* GCSroot */
markroot(L);
/* GCSpropagate */
while (g->gcstate == GCSpropagate)
propagatemarks(g, GCSTEPSIZE);
/* atomic */
atomic(L);
/* GCSsweepstring */
while (g->gcstate == GCSsweepstring)
sweepstringstep(L);
/* GCSsweep */
while (g->gcstate == GCSsweep)
sweepstep(L);
/* GCSfinalize */
checkSizes(L);
while (g->gcstate == GCSfinalize)
GCTM(L);
switch (g->gcstate) {
case GCSroot:
markroot(L);
break;
case GCSpropagate:
propagatemarks(g, GCSTEPSIZE);
break;
case GCSatomic:
atomic(L);
break;
case GCSsweepstring:
sweepstringstep(L);
break;
case GCSsweep:
sweepstep(L);
break;
case GCSfinalize:
GCTM(L);
break;
default: lua_assert(0);
}
g->GCthreshold = g->nblocks + GCSTEPSIZE;
}
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v));
lua_assert(!isdead(g, v) && !isdead(g, o));
if (g->gcstate > GCSatomic) /* sweeping phases? */
black2gray(o); /* just mark as gray to avoid other barriers */
else /* breaking invariant! */
reallymarkobject(g, v); /* restore it */
}