mirror of https://github.com/rusefi/lua.git
small bug in error handling of finalizers (cannot call lua_tostring
inside the core) + small bug in luaC_checkfinalizer (when avoiding remove object being sweeped from sweep list) + small changes in GC pace control (for the atomic part)
This commit is contained in:
parent
01e5f358bd
commit
ab2c3d5cde
72
lgc.c
72
lgc.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 2.130 2012/05/29 17:52:17 roberto Exp roberto $
|
** $Id: lgc.c,v 2.131 2012/05/30 16:01:10 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -753,6 +753,18 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
|
||||||
return (*p == NULL) ? NULL : p;
|
return (*p == NULL) ? NULL : p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** sweep a list until a live object (or end of list)
|
||||||
|
*/
|
||||||
|
static GCObject **sweeptolive (lua_State *L, GCObject **p) {
|
||||||
|
GCObject ** old = p;
|
||||||
|
do {
|
||||||
|
p = sweeplist(L, p, 1);
|
||||||
|
} while (p == old);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
@ -812,12 +824,14 @@ static void GCTM (lua_State *L, int propagateerrors) {
|
||||||
L->allowhook = oldah; /* restore hooks */
|
L->allowhook = oldah; /* restore hooks */
|
||||||
g->gcrunning = running; /* restore state */
|
g->gcrunning = running; /* restore state */
|
||||||
if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
|
if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
|
||||||
if (status == LUA_ERRRUN) { /* is there an error msg.? */
|
if (status == LUA_ERRRUN) { /* is there an error object? */
|
||||||
luaO_pushfstring(L, "error in __gc metamethod (%s)",
|
const char *msg = (ttisstring(L->top - 1))
|
||||||
lua_tostring(L, -1));
|
? svalue(L->top - 1)
|
||||||
|
: "no message";
|
||||||
|
luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
|
||||||
status = LUA_ERRGCMM; /* error in __gc metamethod */
|
status = LUA_ERRGCMM; /* error in __gc metamethod */
|
||||||
}
|
}
|
||||||
luaD_throw(L, status); /* re-send error */
|
luaD_throw(L, status); /* re-throw error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,11 +878,9 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
||||||
else { /* move 'o' to 'finobj' list */
|
else { /* move 'o' to 'finobj' list */
|
||||||
GCObject **p;
|
GCObject **p;
|
||||||
GCheader *ho = gch(o);
|
GCheader *ho = gch(o);
|
||||||
lua_assert(!isdead(g, o));
|
if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */
|
||||||
/* avoid removing current sweep object */
|
lua_assert(issweepphase(g));
|
||||||
if (g->sweepgc == &ho->next) {
|
g->sweepgc = sweeptolive(L, g->sweepgc);
|
||||||
/* step to next object in the list */
|
|
||||||
g->sweepgc = sweeplist(L, g->sweepgc, 1);
|
|
||||||
}
|
}
|
||||||
/* search for pointer pointing to 'o' */
|
/* search for pointer pointing to 'o' */
|
||||||
for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
|
for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
|
||||||
|
@ -899,18 +911,19 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** enter first sweep phase (strings) and prepare pointers for other
|
** enter first sweep phase (strings) and prepare pointers for other
|
||||||
** sweep phases. The calls to 'sweeplist' attempt to make pointers
|
** sweep phases. The calls to 'sweeptolive' make pointers point to an
|
||||||
** point to an object inside the list (instead of to the header), so
|
** object inside the list (instead of to the header), so that the real
|
||||||
** that the real sweep do not need to skip objects created between "now"
|
** sweep do not need to skip objects created between "now" and the start
|
||||||
** and the start of the real sweep.
|
** of the real sweep.
|
||||||
*/
|
*/
|
||||||
static void entersweep (lua_State *L) {
|
static void entersweep (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
g->gcstate = GCSsweepstring;
|
g->gcstate = GCSsweepstring;
|
||||||
lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
|
lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
|
||||||
g->sweepstrgc = 0; /* prepare to sweep strings, ... */
|
/* prepare to sweep strings, finalizable objects, and regular objects */
|
||||||
g->sweepfin = sweeplist(L, &g->finobj, 1); /* finalizable objects, ... */
|
g->sweepstrgc = 0;
|
||||||
g->sweepgc = sweeplist(L, &g->allgc, 1); /* and regular objects */
|
g->sweepfin = sweeptolive(L, &g->finobj);
|
||||||
|
g->sweepgc = sweeptolive(L, &g->allgc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -966,7 +979,7 @@ void luaC_freeallobjects (lua_State *L) {
|
||||||
|
|
||||||
static l_mem atomic (lua_State *L) {
|
static l_mem atomic (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
l_mem trav = -g->GCmemtrav; /* start counting work */
|
l_mem work = -g->GCmemtrav; /* start counting work */
|
||||||
GCObject *origweak, *origall;
|
GCObject *origweak, *origall;
|
||||||
lua_assert(!iswhite(obj2gco(g->mainthread)));
|
lua_assert(!iswhite(obj2gco(g->mainthread)));
|
||||||
markobject(g, L); /* mark running thread */
|
markobject(g, L); /* mark running thread */
|
||||||
|
@ -976,20 +989,21 @@ static l_mem atomic (lua_State *L) {
|
||||||
/* remark occasional upvalues of (maybe) dead threads */
|
/* remark occasional upvalues of (maybe) dead threads */
|
||||||
remarkupvals(g);
|
remarkupvals(g);
|
||||||
propagateall(g); /* propagate changes */
|
propagateall(g); /* propagate changes */
|
||||||
trav += g->GCmemtrav; /* count work done til now */
|
work += g->GCmemtrav; /* stop counting (do not (re)count grays) */
|
||||||
/* traverse objects caught by write barrier and by 'remarkupvals' */
|
/* traverse objects caught by write barrier and by 'remarkupvals' */
|
||||||
retraversegrays(g);
|
retraversegrays(g);
|
||||||
|
work -= g->GCmemtrav; /* restart counting */
|
||||||
convergeephemerons(g);
|
convergeephemerons(g);
|
||||||
/* at this point, all strongly accessible objects are marked. */
|
/* at this point, all strongly accessible objects are marked. */
|
||||||
/* clear values from weak tables, before checking finalizers */
|
/* clear values from weak tables, before checking finalizers */
|
||||||
clearvalues(g, g->weak, NULL);
|
clearvalues(g, g->weak, NULL);
|
||||||
clearvalues(g, g->allweak, NULL);
|
clearvalues(g, g->allweak, NULL);
|
||||||
origweak = g->weak; origall = g->allweak;
|
origweak = g->weak; origall = g->allweak;
|
||||||
trav -= g->GCmemtrav; /* restart counting work */
|
work += g->GCmemtrav; /* stop counting (objects being finalized) */
|
||||||
separatetobefnz(L, 0); /* separate objects to be finalized */
|
separatetobefnz(L, 0); /* separate objects to be finalized */
|
||||||
markbeingfnz(g); /* mark objects that will be finalized */
|
markbeingfnz(g); /* mark objects that will be finalized */
|
||||||
propagateall(g); /* remark, to propagate `preserveness' */
|
propagateall(g); /* remark, to propagate `preserveness' */
|
||||||
trav += g->GCmemtrav; /* add work done til now */
|
work -= g->GCmemtrav; /* restart counting */
|
||||||
convergeephemerons(g);
|
convergeephemerons(g);
|
||||||
/* at this point, all resurrected objects are marked. */
|
/* at this point, all resurrected objects are marked. */
|
||||||
/* remove dead objects from weak tables */
|
/* remove dead objects from weak tables */
|
||||||
|
@ -999,8 +1013,8 @@ static l_mem atomic (lua_State *L) {
|
||||||
clearvalues(g, g->weak, origweak);
|
clearvalues(g, g->weak, origweak);
|
||||||
clearvalues(g, g->allweak, origall);
|
clearvalues(g, g->allweak, origall);
|
||||||
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
||||||
entersweep(L); /* prepare to sweep strings */
|
work += g->GCmemtrav; /* complete counting */
|
||||||
return trav; /* estimate of the objects marked by 'atomic' */
|
return work; /* estimate of memory marked by 'atomic' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1024,9 +1038,13 @@ static lu_mem singlestep (lua_State *L) {
|
||||||
return g->GCmemtrav - oldtrav; /* memory traversed in this step */
|
return g->GCmemtrav - oldtrav; /* memory traversed in this step */
|
||||||
}
|
}
|
||||||
else { /* no more `gray' objects */
|
else { /* no more `gray' objects */
|
||||||
|
lu_mem work;
|
||||||
g->gcstate = GCSatomic; /* finish mark phase */
|
g->gcstate = GCSatomic; /* finish mark phase */
|
||||||
g->GCestimate = g->GCmemtrav; /* save what was counted */
|
g->GCestimate = g->GCmemtrav; /* save what was counted */;
|
||||||
return atomic(L);
|
work = atomic(L); /* add what was traversed by 'atomic' */
|
||||||
|
g->GCestimate += work; /* estimate of total memory traversed */
|
||||||
|
entersweep(L);
|
||||||
|
return work + 2 * GCSWEEPCOST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case GCSsweepstring: {
|
case GCSsweepstring: {
|
||||||
|
@ -1095,7 +1113,7 @@ static void generationalcollection (lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void step (lua_State *L) {
|
static void incstep (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
l_mem debt = g->GCdebt;
|
l_mem debt = g->GCdebt;
|
||||||
int stepmul = g->gcstepmul;
|
int stepmul = g->gcstepmul;
|
||||||
|
@ -1122,7 +1140,7 @@ void luaC_forcestep (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
int i;
|
int i;
|
||||||
if (isgenerational(g)) generationalcollection(L);
|
if (isgenerational(g)) generationalcollection(L);
|
||||||
else step(L);
|
else incstep(L);
|
||||||
/* run a few finalizers (or all of them at the end of a collect cycle) */
|
/* run a few finalizers (or all of them at the end of a collect cycle) */
|
||||||
for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
|
for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
|
||||||
GCTM(L, 1); /* call one finalizer */
|
GCTM(L, 1); /* call one finalizer */
|
||||||
|
|
Loading…
Reference in New Issue