1
0
mirror of https://github.com/lua/lua.git synced 2025-02-04 06:13:04 +08:00

new function 'luaC_changemode' +

bug: objects entering the 'allgc' list must have their OLDBIT cleared
(upvalues being cleared) + bug: in 'checkSizes', KGC_EMERGENCY is
stored in 'gckind' field, not in 'gcstate' + current white changes when
entering sweep phase (so there are dead objects only in that phase)
This commit is contained in:
Roberto Ierusalimschy 2010-05-05 15:58:36 -03:00
parent d77898597e
commit d2ea5b00b7

55
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.87 2010/05/04 18:09:06 roberto Exp roberto $ ** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -170,6 +170,7 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
lua_assert(!isblack(o)); /* open upvalues are never black */ lua_assert(!isblack(o)); /* open upvalues are never black */
if (isgray(o)) { if (isgray(o)) {
if (keepinvariant(g)) { if (keepinvariant(g)) {
resetbit(o->gch.marked, OLDBIT);
gray2black(o); /* it is being visited now */ gray2black(o); /* it is being visited now */
markvalue(g, uv->v); markvalue(g, uv->v);
} }
@ -300,7 +301,8 @@ static void remarkupvals (global_State *g) {
/* /*
** mark root set ** mark root set and reset all gray lists, to start a new
** incremental (or full) collection
*/ */
static void markroot (lua_State *L) { static void markroot (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
@ -655,12 +657,12 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
static void checkSizes (lua_State *L) { static void checkSizes (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
int hs = g->strt.size / 2; /* half the size of the string table */ if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */
if (g->gcstate == KGC_EMERGENCY) return; int hs = g->strt.size / 2; /* half the size of the string table */
if (g->strt.nuse < cast(lu_int32, hs)) { /* using less than half its size? */ if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */
luaS_resize(L, hs); /* halve its size */ luaS_resize(L, hs); /* halve its size */
luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
} }
luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
} }
@ -668,6 +670,7 @@ static Udata *udata2finalize (global_State *g) {
GCObject *o = g->tobefnz; /* get first element */ GCObject *o = g->tobefnz; /* get first element */
Udata *u = rawgco2u(o); Udata *u = rawgco2u(o);
lua_assert(isfinalized(&u->uv)); lua_assert(isfinalized(&u->uv));
lua_assert(!testbit(u->uv.marked, OLDBIT));
g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */
u->uv.next = g->allgc; /* return it to 'allgc' list */ u->uv.next = g->allgc; /* return it to 'allgc' list */
g->allgc = o; g->allgc = o;
@ -769,6 +772,33 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) {
** ======================================================= ** =======================================================
*/ */
#define sweepphases \
(bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
/*
** change GC mode
*/
void luaC_changemode (lua_State *L, int mode) {
global_State *g = G(L);
if (mode == g->gckind) return; /* nothing to change */
if (mode == KGC_GEN) { /* change to generational mode */
/* make sure gray lists are consistent */
luaC_runtilstate(L, bitmask(GCSpropagate));
g->lastmajormem = g->totalbytes;
g->gckind = KGC_GEN;
}
else { /* change to incremental mode */
/* sweep all objects to turn them back to white
(as white has not changed, nothing extra will be collected) */
g->sweepstrgc = 0;
g->gcstate = GCSsweepstring;
g->gckind = KGC_NORMAL;
luaC_runtilstate(L, ~sweepphases);
}
}
/* /*
** call all pending finalizers */ ** call all pending finalizers */
static void callallpendingfinalizers (lua_State *L, int propagateerrors) { static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
@ -817,7 +847,8 @@ static void atomic (lua_State *L) {
cleartable(g->weak); cleartable(g->weak);
cleartable(g->ephemeron); cleartable(g->ephemeron);
cleartable(g->allweak); cleartable(g->allweak);
lua_checkmemory(L); g->sweepstrgc = 0; /* prepare to sweep strings */
g->gcstate = GCSsweepstring;
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
} }
@ -837,8 +868,6 @@ static l_mem singlestep (lua_State *L) {
else { /* no more `gray' objects */ else { /* no more `gray' objects */
g->gcstate = GCSatomic; /* finish mark phase */ g->gcstate = GCSatomic; /* finish mark phase */
atomic(L); atomic(L);
g->sweepstrgc = 0; /* prepare to sweep strings */
g->gcstate = GCSsweepstring;
return GCATOMICCOST; return GCATOMICCOST;
} }
} }
@ -933,7 +962,7 @@ void luaC_step (lua_State *L) {
/* /*
** performs a full GC cycle; if "isememrgency", does not call ** performs a full GC cycle; if "isemergency", does not call
** finalizers (which could change stack positions) ** finalizers (which could change stack positions)
*/ */
void luaC_fullgc (lua_State *L, int isemergency) { void luaC_fullgc (lua_State *L, int isemergency) {
@ -942,14 +971,14 @@ void luaC_fullgc (lua_State *L, int isemergency) {
lua_assert(origkind != KGC_EMERGENCY); lua_assert(origkind != KGC_EMERGENCY);
if (!isemergency) /* do not run finalizers during emergency GC */ if (!isemergency) /* do not run finalizers during emergency GC */
callallpendingfinalizers(L, 1); callallpendingfinalizers(L, 1);
g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; if (keepinvariant(g)) { /* marking phase? */
if (g->gcstate == GCSpropagate) { /* marking phase? */
/* must sweep all objects to turn them back to white /* must sweep all objects to turn them back to white
(as white has not changed, nothing will be collected) */ (as white has not changed, nothing will be collected) */
g->sweepstrgc = 0; g->sweepstrgc = 0;
g->gcstate = GCSsweepstring; g->gcstate = GCSsweepstring;
} }
/* finish any pending sweep phase */ g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
/* finish any pending sweep phase to start a new cycle */
luaC_runtilstate(L, bitmask(GCSpause)); luaC_runtilstate(L, bitmask(GCSpause));
/* run entire collector */ /* run entire collector */
luaC_runtilstate(L, ~bitmask(GCSpause)); luaC_runtilstate(L, ~bitmask(GCSpause));