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:
parent
d77898597e
commit
d2ea5b00b7
55
lgc.c
55
lgc.c
@ -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));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user