diff --git a/lgc.c b/lgc.c index bf36d025..dd6af6c5 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.97 2010/06/02 18:36:58 roberto Exp roberto $ +** $Id: lgc.c,v 2.98 2010/06/04 13:25:10 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -157,14 +157,24 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) { /* -** barrier for prototypes +** barrier for prototypes. When creating first closure (cache is +** NULL), use a forward barrier; this may be the only closure of the +** prototype (if it is a "regular" function, with a single instance) +** and the prototype may be big, so it is better to avoid traversing +** it again. Otherwise, use a backward barrier, to avoid marking all +** possible instances. */ -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p) { +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { global_State *g = G(L); - lua_assert(isblack(p)); - black2gray(p); /* make object gray (again) */ - gco2p(p)->gclist = g->clearcache; - g->clearcache = p; + lua_assert(isblack(obj2gco(p))); + if (p->cache == NULL) { /* first time? */ + luaC_objbarrier(L, p, c); + } + else { /* use a backward barrier */ + black2gray(obj2gco(p)); /* make prototype gray (again) */ + p->gclist = g->grayagain; + g->grayagain = obj2gco(p); + } } @@ -312,7 +322,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 = g->clearcache = NULL; + g->weak = g->allweak = g->ephemeron = NULL; markobject(g, g->mainthread); markvalue(g, &g->l_registry); markmt(g); @@ -422,19 +432,10 @@ 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); + if (f->cache && iswhite(obj2gco(f->cache))) + f->cache = NULL; /* allow cache to be collected */ stringmark(f->source); for (i = 0; i < f->sizek; i++) /* mark literals */ markvalue(g, &f->k[i]); @@ -557,14 +558,6 @@ 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' @@ -878,7 +871,6 @@ 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 */ diff --git a/lgc.h b/lgc.h index fa007969..191adfeb 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.41 2010/05/10 18:23:45 roberto Exp roberto $ +** $Id: lgc.h,v 2.42 2010/06/04 13:25:10 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -124,8 +124,8 @@ #define luaC_objbarrierback(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } -#define luaC_barrierproto(L,p) \ - { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p); } +#define luaC_barrierproto(L,p,c) \ + { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } LUAI_FUNC void luaC_separateudata (lua_State *L, int all); LUAI_FUNC void luaC_freeallobjects (lua_State *L); @@ -136,7 +136,7 @@ LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, int offset); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p); +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); LUAI_FUNC void luaC_changemode (lua_State *L, int mode); diff --git a/lvm.c b/lvm.c index 3a66e0aa..8361d3dd 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.120 2010/05/13 19:53:05 roberto Exp roberto $ +** $Id: lvm.c,v 2.121 2010/06/04 13:25:10 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -368,7 +368,9 @@ static Closure *getcached (Proto *p, UpVal **encup, StkId base) { /* ** create a new Lua closure, push it in the stack, and initialize -** its upvalues +** its upvalues. Note that the call to 'luaC_barrierproto' must come +** before the assignment to 'p->cache', as the function needs the +** orginal value of that field. */ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, StkId ra) { @@ -383,8 +385,8 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, else /* get upvalue from enclosing function */ ncl->l.upvals[i] = encup[uv[i].idx]; } - p->cache = ncl; /* save it on cache, so it can be reused */ - luaC_barrierproto(L, obj2gco(p)); + luaC_barrierproto(L, p, ncl); + p->cache = ncl; /* save it on cache for reuse */ }