Lua closures are cached for reuse

This commit is contained in:
Roberto Ierusalimschy
2010-06-04 10:25:10 -03:00
parent 545f43065f
commit 575074fd85
5 changed files with 114 additions and 36 deletions

50
lgc.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.96 2010/05/17 20:39:31 roberto Exp roberto $
** $Id: lgc.c,v 2.97 2010/06/02 18:36:58 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -127,7 +127,7 @@ static int iscleared (const TValue *o, int iskey) {
** barrier that moves collector forward, that is, mark the white object
** being pointed by a black object.
*/
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
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(isgenerational(g) || g->gcstate != GCSpause);
@@ -143,18 +143,31 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
/*
** barrier that moves collector backward, that is, mark the black object
** pointing to a white object as gray again.
** pointing to a white object as gray again. (Current implementation
** only works for tables; access to 'gclist' is not uniform across
** different types.)
*/
void luaC_barrierback (lua_State *L, Table *t) {
void luaC_barrierback_ (lua_State *L, GCObject *o) {
global_State *g = G(L);
GCObject *o = obj2gco(t);
lua_assert(isblack(o) && !isdead(g, o));
black2gray(o); /* make table gray (again) */
t->gclist = g->grayagain;
black2gray(o); /* make object gray (again) */
gco2t(o)->gclist = g->grayagain;
g->grayagain = o;
}
/*
** barrier for prototypes
*/
LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p) {
global_State *g = G(L);
lua_assert(isblack(p));
black2gray(p); /* make object gray (again) */
gco2p(p)->gclist = g->clearcache;
g->clearcache = p;
}
/*
** check color (and invariants) for an upvalue that was closed,
** i.e., moved into the 'allgc' list
@@ -299,7 +312,7 @@ static void remarkupvals (global_State *g) {
static void markroot (lua_State *L) {
global_State *g = G(L);
g->gray = g->grayagain = NULL;
g->weak = g->allweak = g->ephemeron = NULL;
g->weak = g->allweak = g->ephemeron = g->clearcache = NULL;
markobject(g, g->mainthread);
markvalue(g, &g->l_registry);
markmt(g);
@@ -409,8 +422,19 @@ static int traversetable (global_State *g, Table *h) {
}
/*
** if prototype's cached closure is not marked, erase it so it
** can be collected
*/
static void checkcache (Proto *p) {
if (p->cache && iswhite(obj2gco(p->cache)))
p->cache = NULL; /* allow cache to be collected */
}
static int traverseproto (global_State *g, Proto *f) {
int i;
checkcache(f);
stringmark(f->source);
for (i = 0; i < f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
@@ -533,6 +557,15 @@ static void convergeephemerons (global_State *g) {
** =======================================================
*/
/*
** clear cache field in all prototypes in list 'l'
*/
static void clearproto (GCObject *l) {
for (; l != NULL; l = gco2p(l)->gclist)
checkcache(gco2p(l));
}
/*
** clear collected entries from all weaktables in list 'l'
*/
@@ -845,6 +878,7 @@ static void atomic (lua_State *L) {
cleartable(g->weak);
cleartable(g->ephemeron);
cleartable(g->allweak);
clearproto(g->clearcache);
g->sweepstrgc = 0; /* prepare to sweep strings */
g->gcstate = GCSsweepstring;
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */