|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
** $Id: lgc.c,v 2.183 2014/05/25 19:08:32 roberto Exp roberto $ |
|
|
|
** $Id: lgc.c,v 2.184 2014/06/30 19:48:08 roberto Exp roberto $ |
|
|
|
** Garbage Collector |
|
|
|
** See Copyright Notice in lua.h |
|
|
|
*/ |
|
|
@ -62,10 +62,10 @@ |
|
|
|
*/ |
|
|
|
#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) |
|
|
|
#define makewhite(g,x) \ |
|
|
|
(gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) |
|
|
|
(x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) |
|
|
|
|
|
|
|
#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) |
|
|
|
#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) |
|
|
|
#define white2gray(x) resetbits(x->marked, WHITEBITS) |
|
|
|
#define black2gray(x) resetbit(x->marked, BLACKBIT) |
|
|
|
|
|
|
|
|
|
|
|
#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) |
|
|
@ -141,7 +141,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
|
|
|
global_State *g = G(L); |
|
|
|
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
|
|
|
lua_assert(g->gcstate != GCSpause); |
|
|
|
lua_assert(gch(o)->tt != LUA_TTABLE); /* tables use a back barrier */ |
|
|
|
lua_assert(o->tt != LUA_TTABLE); /* tables use a back barrier */ |
|
|
|
if (keepinvariant(g)) /* must keep invariant? */ |
|
|
|
reallymarkobject(g, v); /* restore invariant */ |
|
|
|
else { /* sweep phase */ |
|
|
@ -159,7 +159,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
|
|
|
*/ |
|
|
|
void luaC_barrierback_ (lua_State *L, GCObject *o) { |
|
|
|
global_State *g = G(L); |
|
|
|
lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); |
|
|
|
lua_assert(isblack(o) && !isdead(g, o) && o->tt == LUA_TTABLE); |
|
|
|
black2gray(o); /* make object gray (again) */ |
|
|
|
gco2t(o)->gclist = g->grayagain; |
|
|
|
g->grayagain = o; |
|
|
@ -185,8 +185,8 @@ void luaC_fix (lua_State *L, GCObject *o) { |
|
|
|
global_State *g = G(L); |
|
|
|
lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ |
|
|
|
white2gray(o); /* they will be gray forever */ |
|
|
|
g->allgc = o->gch.next; /* remove object from 'allgc' list */ |
|
|
|
o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ |
|
|
|
g->allgc = o->next; /* remove object from 'allgc' list */ |
|
|
|
o->next = g->fixedgc; /* link it to 'fixedgc' list */ |
|
|
|
g->fixedgc = o; |
|
|
|
} |
|
|
|
|
|
|
@ -198,9 +198,9 @@ void luaC_fix (lua_State *L, GCObject *o) { |
|
|
|
GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { |
|
|
|
global_State *g = G(L); |
|
|
|
GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); |
|
|
|
gch(o)->marked = luaC_white(g); |
|
|
|
gch(o)->tt = tt; |
|
|
|
gch(o)->next = g->allgc; |
|
|
|
o->marked = luaC_white(g); |
|
|
|
o->tt = tt; |
|
|
|
o->next = g->allgc; |
|
|
|
g->allgc = o; |
|
|
|
return o; |
|
|
|
} |
|
|
@ -225,7 +225,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { |
|
|
|
static void reallymarkobject (global_State *g, GCObject *o) { |
|
|
|
reentry: |
|
|
|
white2gray(o); |
|
|
|
switch (gch(o)->tt) { |
|
|
|
switch (o->tt) { |
|
|
|
case LUA_TSHRSTR: |
|
|
|
case LUA_TLNGSTR: { |
|
|
|
gray2black(o); |
|
|
@ -288,7 +288,7 @@ static void markmt (global_State *g) { |
|
|
|
*/ |
|
|
|
static void markbeingfnz (global_State *g) { |
|
|
|
GCObject *o; |
|
|
|
for (o = g->tobefnz; o != NULL; o = gch(o)->next) |
|
|
|
for (o = g->tobefnz; o != NULL; o = o->next) |
|
|
|
markobject(g, o); |
|
|
|
} |
|
|
|
|
|
|
@ -528,7 +528,7 @@ static void propagatemark (global_State *g) { |
|
|
|
GCObject *o = g->gray; |
|
|
|
lua_assert(isgray(o)); |
|
|
|
gray2black(o); |
|
|
|
switch (gch(o)->tt) { |
|
|
|
switch (o->tt) { |
|
|
|
case LUA_TTABLE: { |
|
|
|
Table *h = gco2t(o); |
|
|
|
g->gray = h->gclist; /* remove from 'gray' list */ |
|
|
@ -685,7 +685,7 @@ static void freeLclosure (lua_State *L, LClosure *cl) { |
|
|
|
|
|
|
|
|
|
|
|
static void freeobj (lua_State *L, GCObject *o) { |
|
|
|
switch (gch(o)->tt) { |
|
|
|
switch (o->tt) { |
|
|
|
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
|
|
|
case LUA_TLCL: { |
|
|
|
freeLclosure(L, gco2lcl(o)); |
|
|
@ -727,14 +727,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
|
|
|
int white = luaC_white(g); /* current white */ |
|
|
|
while (*p != NULL && count-- > 0) { |
|
|
|
GCObject *curr = *p; |
|
|
|
int marked = gch(curr)->marked; |
|
|
|
int marked = curr->marked; |
|
|
|
if (isdeadm(ow, marked)) { /* is 'curr' dead? */ |
|
|
|
*p = gch(curr)->next; /* remove 'curr' from list */ |
|
|
|
*p = curr->next; /* remove 'curr' from list */ |
|
|
|
freeobj(L, curr); /* erase 'curr' */ |
|
|
|
} |
|
|
|
else { /* update marks */ |
|
|
|
gch(curr)->marked = cast_byte((marked & maskcolors) | white); |
|
|
|
p = &gch(curr)->next; /* go to next element */ |
|
|
|
curr->marked = cast_byte((marked & maskcolors) | white); |
|
|
|
p = &curr->next; /* go to next element */ |
|
|
|
} |
|
|
|
} |
|
|
|
return (*p == NULL) ? NULL : p; |
|
|
@ -781,10 +781,10 @@ static void checkSizes (lua_State *L, global_State *g) { |
|
|
|
static GCObject *udata2finalize (global_State *g) { |
|
|
|
GCObject *o = g->tobefnz; /* get first element */ |
|
|
|
lua_assert(tofinalize(o)); |
|
|
|
g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
|
|
|
gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
|
|
|
g->tobefnz = o->next; /* remove it from 'tobefnz' list */ |
|
|
|
o->next = g->allgc; /* return it to 'allgc' list */ |
|
|
|
g->allgc = o; |
|
|
|
resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ |
|
|
|
resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ |
|
|
|
if (issweepphase(g)) |
|
|
|
makewhite(g, o); /* "sweep" object */ |
|
|
|
return o; |
|
|
@ -859,7 +859,7 @@ static void callallpendingfinalizers (lua_State *L, int propagateerrors) { |
|
|
|
*/ |
|
|
|
static GCObject **findlast (GCObject **p) { |
|
|
|
while (*p != NULL) |
|
|
|
p = &gch(*p)->next; |
|
|
|
p = &(*p)->next; |
|
|
|
return p; |
|
|
|
} |
|
|
|
|
|
|
@ -875,12 +875,12 @@ static void separatetobefnz (global_State *g, int all) { |
|
|
|
while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
|
|
|
lua_assert(tofinalize(curr)); |
|
|
|
if (!(iswhite(curr) || all)) /* not being collected? */ |
|
|
|
p = &gch(curr)->next; /* don't bother with it */ |
|
|
|
p = &curr->next; /* don't bother with it */ |
|
|
|
else { |
|
|
|
*p = gch(curr)->next; /* remove 'curr' from "fin" list */ |
|
|
|
gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
|
|
|
*p = curr->next; /* remove 'curr' from "fin" list */ |
|
|
|
curr->next = *lastnext; /* link at the end of 'tobefnz' list */ |
|
|
|
*lastnext = curr; |
|
|
|
lastnext = &gch(curr)->next; |
|
|
|
lastnext = &curr->next; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -899,15 +899,15 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { |
|
|
|
GCObject **p; |
|
|
|
if (issweepphase(g)) { |
|
|
|
makewhite(g, o); /* "sweep" object 'o' */ |
|
|
|
if (g->sweepgc == &o->gch.next) /* should not remove 'sweepgc' object */ |
|
|
|
if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ |
|
|
|
g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ |
|
|
|
} |
|
|
|
/* search for pointer pointing to 'o' */ |
|
|
|
for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } |
|
|
|
*p = o->gch.next; /* remove 'o' from 'allgc' list */ |
|
|
|
o->gch.next = g->finobj; /* link it in "fin" list */ |
|
|
|
for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } |
|
|
|
*p = o->next; /* remove 'o' from 'allgc' list */ |
|
|
|
o->next = g->finobj; /* link it in "fin" list */ |
|
|
|
g->finobj = o; |
|
|
|
l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ |
|
|
|
l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|