no more local collection

This commit is contained in:
Roberto Ierusalimschy 2014-02-13 10:11:34 -02:00
parent 4a1ed6e6e5
commit 733c58595b
10 changed files with 69 additions and 263 deletions

9
lapi.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 2.192 2013/12/30 20:47:58 roberto Exp roberto $ ** $Id: lapi.c,v 2.193 2014/01/27 13:34:32 roberto Exp roberto $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -589,7 +589,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
while (n--) { while (n--) {
setobj2n(L, &cl->c.upvalue[n], L->top + n); setobj2n(L, &cl->c.upvalue[n], L->top + n);
/* does not need barrier because closure is white */ /* does not need barrier because closure is white */
valnolocal(L->top + n); /* but needs 'local barrier' */
} }
setclCvalue(L, L->top, cl); setclCvalue(L, L->top, cl);
} }
@ -864,7 +863,6 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
} }
default: { default: {
G(L)->mt[ttnov(obj)] = mt; G(L)->mt[ttnov(obj)] = mt;
if (mt) nolocal(obj2gco(mt));
break; break;
} }
} }
@ -1086,11 +1084,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
g->gcpause = data; g->gcpause = data;
break; break;
} }
case LUA_GCSETLOCALPAUSE: {
res = g->gclocalpause;
g->gclocalpause = data;
break;
}
case LUA_GCSETSTEPMUL: { case LUA_GCSETSTEPMUL: {
res = g->gcstepmul; res = g->gcstepmul;
g->gcstepmul = data; g->gcstepmul = data;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.281 2013/08/05 16:58:28 roberto Exp roberto $ ** $Id: lbaselib.c,v 1.282 2013/09/13 16:21:52 roberto Exp roberto $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -175,10 +175,10 @@ static int luaB_rawset (lua_State *L) {
static int luaB_collectgarbage (lua_State *L) { static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect", static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul", "count", "step", "setpause", "setstepmul",
"setlocalpause", "isrunning", NULL}; "isrunning", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCSETLOCALPAUSE, LUA_GCISRUNNING}; LUA_GCISRUNNING};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
int ex = luaL_optint(L, 2, 0); int ex = luaL_optint(L, 2, 0);
int res = lua_gc(L, o, ex); int res = lua_gc(L, o, ex);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lfunc.c,v 2.37 2013/08/27 20:04:00 roberto Exp roberto $ ** $Id: lfunc.c,v 2.38 2013/09/11 12:26:14 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures ** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -86,7 +86,6 @@ void luaF_close (lua_State *L, StkId level) {
Proto *luaF_newproto (lua_State *L) { Proto *luaF_newproto (lua_State *L) {
Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p; Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p;
nolocal(obj2gco(f)); /* prototypes are never local */
f->k = NULL; f->k = NULL;
f->sizek = 0; f->sizek = 0;
f->p = NULL; f->p = NULL;

182
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.169 2014/02/11 12:18:12 roberto Exp roberto $ ** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -72,18 +72,11 @@
lua_longassert(!iscollectable(obj) || righttt(obj)) lua_longassert(!iscollectable(obj) || righttt(obj))
#define marklocalvalue(g,o) { checkconsistency(o); \ #define markvalue(g,o) { checkconsistency(o); \
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
#define markvalue(g,o) { \
lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \
marklocalvalue(g,o); }
#define marklocalobject(g,t) \
{ if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
#define markobject(g,t) \ #define markobject(g,t) \
{ lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
static void reallymarkobject (global_State *g, GCObject *o); static void reallymarkobject (global_State *g, GCObject *o);
@ -178,7 +171,6 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
global_State *g = G(L); global_State *g = G(L);
GCObject *o = gcvalue(uv->v); GCObject *o = gcvalue(uv->v);
lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
nolocal(o);
if (keepinvariant(g)) if (keepinvariant(g))
markobject(g, o); markobject(g, o);
} }
@ -186,9 +178,9 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
void luaC_fix (lua_State *L, GCObject *o) { void luaC_fix (lua_State *L, GCObject *o) {
global_State *g = G(L); global_State *g = G(L);
lua_assert(g->localgc == o); lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
white2gray(o); white2gray(o); /* they will be gray forever */
g->localgc = o->gch.next; /* remove object from 'localgc' list */ g->allgc = o->gch.next; /* remove object from 'allgc' list */
o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */
g->fixedgc = o; g->fixedgc = o;
} }
@ -196,15 +188,15 @@ void luaC_fix (lua_State *L, GCObject *o) {
/* /*
** create a new collectable object (with given type and size) and link ** create a new collectable object (with given type and size) and link
** it to 'localgc' list. ** it to 'allgc' list.
*/ */
GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
global_State *g = G(L); global_State *g = G(L);
GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz));
gch(o)->marked = luaC_white(g); gch(o)->marked = luaC_white(g);
gch(o)->tt = tt; gch(o)->tt = tt;
gch(o)->next = g->localgc; gch(o)->next = g->allgc;
g->localgc = o; g->allgc = o;
return o; return o;
} }
@ -289,7 +281,7 @@ static void markmt (global_State *g) {
static void markbeingfnz (global_State *g) { static void markbeingfnz (global_State *g) {
GCObject *o; GCObject *o;
for (o = g->tobefnz; o != NULL; o = gch(o)->next) for (o = g->tobefnz; o != NULL; o = gch(o)->next)
marklocalobject(g, o); markobject(g, o);
} }
@ -306,7 +298,7 @@ static void remarkupvals (global_State *g) {
UpVal *uv = gco2th(thread)->openupval; UpVal *uv = gco2th(thread)->openupval;
for (; uv != NULL; uv = uv->u.op.next) { for (; uv != NULL; uv = uv->u.op.next) {
if (uv->u.op.touched) { if (uv->u.op.touched) {
marklocalvalue(g, uv->v); /* remark upvalue's value */ markvalue(g, uv->v); /* remark upvalue's value */
uv->u.op.touched = 0; uv->u.op.touched = 0;
} }
} }
@ -463,7 +455,7 @@ static int traverseproto (global_State *g, Proto *f) {
static lu_mem traverseCclosure (global_State *g, CClosure *cl) { static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
int i; int i;
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
marklocalvalue(g, &cl->upvalue[i]); markvalue(g, &cl->upvalue[i]);
return sizeCclosure(cl->nupvalues); return sizeCclosure(cl->nupvalues);
} }
@ -489,7 +481,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
if (o == NULL) if (o == NULL)
return 1; /* stack not completely built yet */ return 1; /* stack not completely built yet */
for (; o < th->top; o++) /* mark live elements in the stack */ for (; o < th->top; o++) /* mark live elements in the stack */
marklocalvalue(g, o); markvalue(g, o);
if (g->gcstate == GCSatomic) { /* final traversal? */ if (g->gcstate == GCSatomic) { /* final traversal? */
StkId lim = th->stack + th->stacksize; /* real end of stack */ StkId lim = th->stack + th->stacksize; /* real end of stack */
for (; o < lim; o++) /* clear not-marked stack slice */ for (; o < lim; o++) /* clear not-marked stack slice */
@ -769,16 +761,8 @@ static GCObject *udata2finalize (global_State *g) {
GCObject *o = g->tobefnz; /* get first element */ GCObject *o = g->tobefnz; /* get first element */
lua_assert(tofinalize(o)); lua_assert(tofinalize(o));
g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */
if (islocal(o)) { gch(o)->next = g->allgc; /* return it to 'allgc' list */
gch(o)->next = g->localgc; /* return it to 'localgc' list */
g->localgc = o;
resetbit(gch(o)->marked, LOCALMARK);
}
else { /* return it to 'allgc' list */
gch(o)->next = g->allgc;
g->allgc = o; g->allgc = o;
l_setbit(gch(o)->marked, LOCALMARK);
}
resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */
if (issweepphase(g)) if (issweepphase(g))
makewhite(g, o); /* "sweep" object */ makewhite(g, o); /* "sweep" object */
@ -882,8 +866,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
g->sweepgc = sweeptolive(L, g->sweepgc, NULL); g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
} }
/* search for pointer pointing to 'o' */ /* search for pointer pointing to 'o' */
p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
for (; *p != o; p = &gch(*p)->next) { /* empty */ }
*p = o->gch.next; /* remove 'o' from its list */ *p = o->gch.next; /* remove 'o' from its list */
o->gch.next = g->finobj; /* link it in "fin" list */ o->gch.next = g->finobj; /* link it in "fin" list */
g->finobj = o; g->finobj = o;
@ -896,105 +879,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
/* }====================================================== */ /* }====================================================== */
/*
** {======================================================
** Local Collection
** =======================================================
*/
/*
** Traverse a thread, local marking all its collectable objects
*/
static void localmarkthread (lua_State *l) {
StkId o = l->stack;
StkId lim = l->stack + l->stacksize; /* real end of stack */
if (o == NULL)
return; /* stack not completely built yet */
for (; o < l->top; o++) { /* mark live elements in the stack */
if (iscollectable(o))
l_setbit(gcvalue(o)->gch.marked, LOCALMARK);
}
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(o);
}
/*
** Mark all that is locally accessible (accessible directly from
** a thread)
*/
static void localmark (global_State *g) {
GCObject *thread = obj2gco(g->mainthread);
for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */
localmarkthread(gco2th(thread));
}
static void localsweep (lua_State *L, global_State *g) {
GCObject **p = &g->localgc;
while (*p != NULL) {
GCObject *curr = *p;
if (!islocal(curr)) { /* is 'curr' no more local? */
*p = curr->gch.next; /* remove 'curr' from list */
curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */
g->allgc = curr;
/* mark it as out of local list */
l_setbit(curr->gch.marked, LOCALMARK);
}
else { /* still local */
if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */
resetbit(curr->gch.marked, LOCALMARK);
p = &curr->gch.next; /* go to next element */
}
else { /* object is dead */
if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */
if (gco2lcl(curr)->p->cache == gco2cl(curr))
gco2lcl(curr)->p->cache = NULL; /* clear cache */
}
*p = curr->gch.next; /* remove 'curr' from list */
freeobj(L, curr); /* erase 'curr' */
}
}
}
}
static void separatelocal (global_State *g) {
GCObject **p = &g->finobj;
GCObject **lastnext = findlast(&g->tobefnz);
while (*p != NULL) {
GCObject *curr = *p;
if (!islocal(curr)) /* is 'curr' no more local? */
p = &curr->gch.next; /* go to next element */
else { /* still local */
if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */
resetbit(curr->gch.marked, LOCALMARK);
p = &curr->gch.next; /* go to next element */
}
else { /* object is "dead" */
*p = curr->gch.next; /* remove 'curr' from list */
curr->gch.next = *lastnext; /* link at the end of 'tobefnz' list */
*lastnext = curr;
lastnext = &curr->gch.next;
}
}
}
}
static void luaC_localcollection (lua_State *L) {
global_State *g = G(L);
lua_assert(g->gcstate == GCSpause);
localmark(g);
localsweep(L, g);
separatelocal(g);
callallpendingfinalizers(L, 1);
}
/* }====================================================== */
/* /*
** {====================================================== ** {======================================================
@ -1008,13 +892,13 @@ static void luaC_localcollection (lua_State *L) {
** cycle will start when memory use hits threshold ** cycle will start when memory use hits threshold
*/ */
static void setpause (global_State *g, l_mem estimate) { static void setpause (global_State *g, l_mem estimate) {
l_mem threshold; l_mem threshold, debt;
estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ estimate = estimate / PAUSEADJ; /* adjust 'estimate' */
threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
? estimate * g->gcpause /* no overflow */ ? estimate * g->gcpause /* no overflow */
: MAX_LMEM; /* overflow; truncate to maximum */ : MAX_LMEM; /* overflow; truncate to maximum */
g->GCthreshold = threshold; debt = gettotalbytes(g) - threshold;
luaE_setdebt(g, -g->gclocalpause); luaE_setdebt(g, debt);
} }
@ -1029,9 +913,9 @@ static void setpause (global_State *g, l_mem estimate) {
static int entersweep (lua_State *L) { static int entersweep (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
int n = 0; int n = 0;
g->gcstate = GCSswplocalgc; g->gcstate = GCSswpallgc;
lua_assert(g->sweepgc == NULL); lua_assert(g->sweepgc == NULL);
g->sweepgc = sweeptolive(L, &g->localgc, &n); g->sweepgc = sweeptolive(L, &g->allgc, &n);
return n; return n;
} }
@ -1044,7 +928,6 @@ void luaC_freeallobjects (lua_State *L) {
lua_assert(g->tobefnz == NULL); lua_assert(g->tobefnz == NULL);
g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
g->gckind = KGC_NORMAL; g->gckind = KGC_NORMAL;
sweepwholelist(L, &g->localgc);
sweepwholelist(L, &g->finobj); sweepwholelist(L, &g->finobj);
sweepwholelist(L, &g->allgc); sweepwholelist(L, &g->allgc);
sweepwholelist(L, &g->mainthread->next); sweepwholelist(L, &g->mainthread->next);
@ -1136,10 +1019,7 @@ static lu_mem singlestep (lua_State *L) {
sw = entersweep(L); sw = entersweep(L);
return work + sw * GCSWEEPCOST; return work + sw * GCSWEEPCOST;
} }
case GCSswplocalgc: { /* sweep local objects */ case GCSswpallgc: { /* sweep "regular" objects */
return sweepstep(L, g, GCSswpallgc, &g->allgc);
}
case GCSswpallgc: { /* sweep non-local objects */
return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); return sweepstep(L, g, GCSswpthreads, &g->mainthread->next);
} }
case GCSswpthreads: { /* sweep threads */ case GCSswpthreads: { /* sweep threads */
@ -1208,23 +1088,13 @@ void luaC_forcestep (lua_State *L) {
/* /*
** performs a basic GC step or a local collection when collector is running ** performs a basic GC step when collector is running
*/ */
void luaC_step (lua_State *L) { void luaC_step (lua_State *L) {
global_State *g = G(L); if (!G(L)->gcrunning)
if (!g->gcrunning) luaE_setdebt(G(L), -GCSTEPSIZE); /* avoid being called too often */
luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ else
else { luaC_forcestep(L);
if (g->gcstate != GCSpause) /* in the middle of a cycle? */
luaC_forcestep(L); /* continue it */
else {
luaC_localcollection(L); /* try a local collection */
if (gettotalbytes(g) <= g->GCthreshold) /* enough? */
luaE_setdebt(g, -g->gclocalpause);
else /* local collection did not collect enough memory */
luaC_forcestep(L); /* start a full collection */
}
}
} }

31
lgc.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.h,v 2.76 2013/09/11 20:15:31 roberto Exp roberto $ ** $Id: lgc.h,v 2.77 2014/02/11 12:18:12 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -38,17 +38,16 @@
*/ */
#define GCSpropagate 0 #define GCSpropagate 0
#define GCSatomic 1 #define GCSatomic 1
#define GCSswplocalgc 2 #define GCSswpallgc 2
#define GCSswpallgc 3 #define GCSswpthreads 3
#define GCSswpthreads 4 #define GCSswpfinobj 4
#define GCSswpfinobj 5 #define GCSswptobefnz 5
#define GCSswptobefnz 6 #define GCSswpend 6
#define GCSswpend 7 #define GCSpause 7
#define GCSpause 8
#define issweepphase(g) \ #define issweepphase(g) \
(GCSswplocalgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
/* /*
@ -80,8 +79,6 @@
#define WHITE1BIT 1 /* object is white (type 1) */ #define WHITE1BIT 1 /* object is white (type 1) */
#define BLACKBIT 2 /* object is black */ #define BLACKBIT 2 /* object is black */
#define FINALIZEDBIT 3 /* object has been marked for finalization */ #define FINALIZEDBIT 3 /* object has been marked for finalization */
#define NOLOCALBIT 4 /* object is not local */
#define LOCALMARK 5 /* object is 'locally marked' or out of local list */
/* bit 7 is currently used by tests (luaL_checkmemory) */ /* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
@ -91,7 +88,6 @@
#define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT)
#define isgray(x) /* neither white nor black */ \ #define isgray(x) /* neither white nor black */ \
(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
#define islocal(x) (!testbit((x)->gch.marked, NOLOCALBIT))
#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) #define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT)
@ -102,9 +98,6 @@
#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) #define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
#define nolocal(x) l_setbit((x)->gch.marked, NOLOCALBIT)
#define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); }
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
@ -114,17 +107,15 @@
#define luaC_barrier(L,p,v) { \ #define luaC_barrier(L,p,v) { \
if (iscollectable(v) && \ if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
luaC_barrier_(L,obj2gco(p),gcvalue(v)); } luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
#define luaC_barrierback(L,p,v) { \ #define luaC_barrierback(L,p,v) { \
if (iscollectable(v) && \ if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
luaC_barrierback_(L,obj2gco(p)); } luaC_barrierback_(L,obj2gco(p)); }
#define luaC_objbarrier(L,p,o) { \ #define luaC_objbarrier(L,p,o) { \
if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
luaC_barrier_(L,obj2gco(p),obj2gco(o)); } luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
#define luaC_upvalbarrier(L,uv) \ #define luaC_upvalbarrier(L,uv) \

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 2.116 2013/11/08 17:34:22 roberto Exp roberto $ ** $Id: lstate.c,v 2.117 2014/02/11 12:18:12 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -30,10 +30,6 @@
#define LUAI_GCPAUSE 200 /* 200% */ #define LUAI_GCPAUSE 200 /* 200% */
#endif #endif
#if !defined(LUAI_GCLOCALPAUSE)
#define LUAI_GCLOCALPAUSE (1000 * sizeof(TString))
#endif
#if !defined(LUAI_GCMUL) #if !defined(LUAI_GCMUL)
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
#endif #endif
@ -187,14 +183,12 @@ static void init_registry (lua_State *L, global_State *g) {
Table *registry = luaH_new(L); Table *registry = luaH_new(L);
sethvalue(L, &g->l_registry, registry); sethvalue(L, &g->l_registry, registry);
luaH_resize(L, registry, LUA_RIDX_LAST, 0); luaH_resize(L, registry, LUA_RIDX_LAST, 0);
nolocal(obj2gco(registry));
/* registry[LUA_RIDX_MAINTHREAD] = L */ /* registry[LUA_RIDX_MAINTHREAD] = L */
setthvalue(L, &temp, L); /* temp = L */ setthvalue(L, &temp, L); /* temp = L */
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
/* registry[LUA_RIDX_GLOBALS] = table of globals */ /* registry[LUA_RIDX_GLOBALS] = table of globals */
sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
valnolocal(&temp); /* keep local invariant */
} }
@ -263,7 +257,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
luaC_checkGC(L); luaC_checkGC(L);
/* create new thread */ /* create new thread */
L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
L1->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); L1->marked = luaC_white(g);
L1->tt = LUA_TTHREAD; L1->tt = LUA_TTHREAD;
/* link it on list of threads */ /* link it on list of threads */
L1->next = g->mainthread->next; L1->next = g->mainthread->next;
@ -303,7 +297,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
L->next = NULL; L->next = NULL;
L->tt = LUA_TTHREAD; L->tt = LUA_TTHREAD;
g->currentwhite = bitmask(WHITE0BIT); g->currentwhite = bitmask(WHITE0BIT);
L->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); L->marked = luaC_white(g);
g->gckind = KGC_NORMAL; g->gckind = KGC_NORMAL;
preinit_state(L, g); preinit_state(L, g);
g->frealloc = f; g->frealloc = f;
@ -312,7 +306,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->seed = makeseed(L); g->seed = makeseed(L);
g->gcrunning = 0; /* no GC while building state */ g->gcrunning = 0; /* no GC while building state */
g->GCestimate = 0; g->GCestimate = 0;
g->GCthreshold = 10000;
g->strt.size = g->strt.nuse = 0; g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL; g->strt.hash = NULL;
setnilvalue(&g->l_registry); setnilvalue(&g->l_registry);
@ -320,16 +313,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->panic = NULL; g->panic = NULL;
g->version = NULL; g->version = NULL;
g->gcstate = GCSpause; g->gcstate = GCSpause;
g->localgc = g->allgc = g->finobj = NULL; g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
g->tobefnz = NULL;
g->fixedgc = NULL;
g->sweepgc = NULL; g->sweepgc = NULL;
g->gray = g->grayagain = NULL; g->gray = g->grayagain = NULL;
g->weak = g->ephemeron = g->allweak = NULL; g->weak = g->ephemeron = g->allweak = NULL;
g->totalbytes = sizeof(LG); g->totalbytes = sizeof(LG);
g->GCdebt = 0; g->GCdebt = 0;
g->gcpause = LUAI_GCPAUSE; g->gcpause = LUAI_GCPAUSE;
g->gclocalpause = LUAI_GCLOCALPAUSE;
g->gcstepmul = LUAI_GCMUL; g->gcstepmul = LUAI_GCMUL;
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.97 2013/09/17 15:40:06 roberto Exp roberto $ ** $Id: lstate.h,v 2.98 2014/02/11 12:18:12 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -22,8 +22,7 @@
** the 'CommonHeader' for the link: ** the 'CommonHeader' for the link:
** **
** mainthread->next: all threads; ** mainthread->next: all threads;
** localgc: all local objects not marked for finalization; ** allgc: all objects not marked for finalization;
** allgc: all non local objects not marked for finalization;
** finobj: all objects marked for finalization; ** finobj: all objects marked for finalization;
** tobefnz: all objects ready to be finalized; ** tobefnz: all objects ready to be finalized;
** fixedgc: all objects that are not to be collected (currently ** fixedgc: all objects that are not to be collected (currently
@ -108,7 +107,6 @@ typedef struct global_State {
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCmemtrav; /* memory traversed by the GC */ lu_mem GCmemtrav; /* memory traversed by the GC */
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
lu_mem GCthreshold; /* threshold to start a new GC cycle */
stringtable strt; /* hash table for strings */ stringtable strt; /* hash table for strings */
TValue l_registry; TValue l_registry;
unsigned int seed; /* randomized seed for hashes */ unsigned int seed; /* randomized seed for hashes */
@ -117,7 +115,6 @@ typedef struct global_State {
lu_byte gckind; /* kind of GC running */ lu_byte gckind; /* kind of GC running */
lu_byte gcrunning; /* true if GC is running */ lu_byte gcrunning; /* true if GC is running */
GCObject *allgc; /* list of all collectable objects */ GCObject *allgc; /* list of all collectable objects */
GCObject *localgc; /* list of local objects */
GCObject **sweepgc; /* current position of sweep in list */ GCObject **sweepgc; /* current position of sweep in list */
GCObject *finobj; /* list of collectable objects with finalizers */ GCObject *finobj; /* list of collectable objects with finalizers */
GCObject *gray; /* list of gray objects */ GCObject *gray; /* list of gray objects */
@ -129,7 +126,6 @@ typedef struct global_State {
GCObject *fixedgc; /* list of objects not to be collected */ GCObject *fixedgc; /* list of objects not to be collected */
Mbuffer buff; /* temporary buffer for string concatenation */ Mbuffer buff; /* temporary buffer for string concatenation */
int gcpause; /* size of pause between successive GCs */ int gcpause; /* size of pause between successive GCs */
int gclocalpause; /* size of pause between local collections */
int gcstepmul; /* GC `granularity' */ int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */ lua_CFunction panic; /* to be called in unprotected errors */
struct lua_State *mainthread; struct lua_State *mainthread;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltests.c,v 2.162 2013/12/30 20:47:58 roberto Exp roberto $ ** $Id: ltests.c,v 2.163 2014/02/11 12:18:12 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation ** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -188,41 +188,23 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
} }
/*
** Check locality
*/
static int testobjref2 (GCObject *f, GCObject *t) {
/* not a local or pointed by a thread? */
if (!islocal(t) || gch(f)->tt == LUA_TTHREAD)
return 1; /* ok */
if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL)
return 1; /* cache from a prototype */
return 0;
}
static void printobj (global_State *g, GCObject *o) { static void printobj (global_State *g, GCObject *o) {
printf("||%s(%p)-%s-%c(%02X)||", printf("||%s(%p)-%c(%02X)||",
ttypename(novariant(gch(o)->tt)), (void *)o, ttypename(novariant(gch(o)->tt)), (void *)o,
islocal(o)?"L":"NL",
isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked);
} }
static int testobjref (global_State *g, GCObject *f, GCObject *t) { static int testobjref (global_State *g, GCObject *f, GCObject *t) {
int r1 = testobjref1(g,f,t); int r1 = testobjref1(g, f, t);
int r2 = testobjref2(f,t); if (!r1) {
if (!r1 || !r2) {
if (!r1)
printf("%d(%02X) - ", g->gcstate, g->currentwhite); printf("%d(%02X) - ", g->gcstate, g->currentwhite);
else
printf("local violation - ");
printobj(g, f); printobj(g, f);
printf(" -> "); printf(" -> ");
printobj(g, t); printobj(g, t);
printf("\n"); printf("\n");
} }
return r1 && r2; return r1;
} }
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) #define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
@ -349,7 +331,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
break; break;
} }
case LUA_TTHREAD: { case LUA_TTHREAD: {
lua_assert(!islocal(o));
checkstack(g, gco2th(o)); checkstack(g, gco2th(o));
break; break;
} }
@ -366,7 +347,10 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
break; break;
} }
case LUA_TSHRSTR: case LUA_TSHRSTR:
case LUA_TLNGSTR: break; case LUA_TLNGSTR: {
lua_assert(!isgray(o)); /* strings are never gray */
break;
}
default: lua_assert(0); default: lua_assert(0);
} }
} }
@ -431,28 +415,23 @@ int lua_checkmemory (lua_State *L) {
resetbit(g->mainthread->marked, TESTGRAYBIT); resetbit(g->mainthread->marked, TESTGRAYBIT);
lua_assert(g->sweepgc == NULL || issweepphase(g)); lua_assert(g->sweepgc == NULL || issweepphase(g));
markgrays(g); markgrays(g);
/* check 'localgc' list */ /* check 'fixedgc' list */
checkgray(g, g->localgc); for (o = g->fixedgc; o != NULL; o = gch(o)->next) {
maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswplocalgc); lua_assert(gch(o)->tt == LUA_TSHRSTR && isgray(o));
for (o = g->localgc; o != NULL; o = gch(o)->next) {
checkobject(g, o, maybedead);
lua_assert(!tofinalize(o) && !testbit(o->gch.marked, LOCALMARK));
} }
/* check 'allgc' list */ /* check 'allgc' list */
checkgray(g, g->allgc); checkgray(g, g->allgc);
maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc);
for (o = g->allgc; o != NULL; o = gch(o)->next) { for (o = g->allgc; o != NULL; o = gch(o)->next) {
checkobject(g, o, maybedead); checkobject(g, o, maybedead);
lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); lua_assert(!tofinalize(o));
lua_assert(testbit(o->gch.marked, NOLOCALBIT));
} }
/* check thread list */ /* check thread list */
checkgray(g, obj2gco(g->mainthread)); checkgray(g, obj2gco(g->mainthread));
maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads); maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads);
for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) {
checkobject(g, o, maybedead); checkobject(g, o, maybedead);
lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); lua_assert(!tofinalize(o));
lua_assert(testbit(o->gch.marked, NOLOCALBIT));
lua_assert(gch(o)->tt == LUA_TTHREAD); lua_assert(gch(o)->tt == LUA_TTHREAD);
} }
/* check 'finobj' list */ /* check 'finobj' list */
@ -460,7 +439,6 @@ int lua_checkmemory (lua_State *L) {
for (o = g->finobj; o != NULL; o = gch(o)->next) { for (o = g->finobj; o != NULL; o = gch(o)->next) {
checkobject(g, o, 0); checkobject(g, o, 0);
lua_assert(tofinalize(o)); lua_assert(tofinalize(o));
lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK));
lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE);
} }
/* check 'tobefnz' list */ /* check 'tobefnz' list */
@ -636,21 +614,12 @@ static int gc_color (lua_State *L) {
} }
static int gc_local (lua_State *L) {
TValue *o;
luaL_checkany(L, 1);
o = obj_at(L, 1);
lua_pushboolean(L, !iscollectable(o) || islocal(gcvalue(o)));
return 1;
}
static int gc_state (lua_State *L) { static int gc_state (lua_State *L) {
static const char *statenames[] = {"propagate", "atomic", static const char *statenames[] = {"propagate", "atomic",
"sweeplocalgc", "sweepallgc", "sweepthreads", "sweepfinobj", "sweepallgc", "sweepthreads", "sweepfinobj",
"sweeptobefnz", "sweepend", "pause", ""}; "sweeptobefnz", "sweepend", "pause", ""};
static const int states[] = {GCSpropagate, GCSatomic, static const int states[] = {GCSpropagate, GCSatomic,
GCSswplocalgc, GCSswpallgc, GCSswpthreads, GCSswpfinobj, GCSswpallgc, GCSswpthreads, GCSswpfinobj,
GCSswptobefnz, GCSswpend, GCSpause, -1}; GCSswptobefnz, GCSswpend, GCSpause, -1};
int option = states[luaL_checkoption(L, 1, "", statenames)]; int option = states[luaL_checkoption(L, 1, "", statenames)];
if (option == -1) { if (option == -1) {
@ -1459,7 +1428,6 @@ static const struct luaL_Reg tests_funcs[] = {
{"doonnewstack", doonnewstack}, {"doonnewstack", doonnewstack},
{"doremote", doremote}, {"doremote", doremote},
{"gccolor", gc_color}, {"gccolor", gc_color},
{"isgclocal", gc_local},
{"gcstate", gc_state}, {"gcstate", gc_state},
{"getref", getref}, {"getref", getref},
{"hash", hash_query}, {"hash", hash_query},
@ -1509,3 +1477,4 @@ int luaB_opentests (lua_State *L) {
} }
#endif #endif

3
lua.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.297 2013/12/18 14:12:03 roberto Exp roberto $ ** $Id: lua.h,v 1.298 2013/12/30 20:47:58 roberto Exp roberto $
** Lua - A Scripting Language ** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file ** See Copyright Notice at the end of this file
@ -294,7 +294,6 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCSTEP 5 #define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6 #define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7 #define LUA_GCSETSTEPMUL 7
#define LUA_GCSETLOCALPAUSE 8
#define LUA_GCISRUNNING 9 #define LUA_GCISRUNNING 9
LUA_API int (lua_gc) (lua_State *L, int what, int data); LUA_API int (lua_gc) (lua_State *L, int what, int data);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $ ** $Id: lundump.c,v 2.24 2013/08/16 18:55:49 roberto Exp roberto $
** load precompiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -88,7 +88,6 @@ static TString* LoadString(LoadState* S)
char* s=luaZ_openspace(S->L,S->b,size); char* s=luaZ_openspace(S->L,S->b,size);
LoadBlock(S,s,size*sizeof(char)); LoadBlock(S,s,size*sizeof(char));
ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */
return ts; return ts;
} }
} }