Avoid potential store-forwarding stalls in GC marking.

This commit is contained in:
Mike Pall 2012-06-09 20:30:27 +02:00
parent 1c8ed534b3
commit 9d7bd04fae

View File

@ -54,21 +54,22 @@
/* Mark a white GCobj. */
static void gc_mark(global_State *g, GCobj *o)
{
int gct = o->gch.gct;
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
if (LJ_UNLIKELY(o->gch.gct == ~LJ_TUDATA)) {
if (LJ_UNLIKELY(gct == ~LJ_TUDATA)) {
GCtab *mt = tabref(gco2ud(o)->metatable);
gray2black(o); /* Userdata are never gray. */
if (mt) gc_markobj(g, mt);
gc_markobj(g, tabref(gco2ud(o)->env));
} else if (LJ_UNLIKELY(o->gch.gct == ~LJ_TUPVAL)) {
} else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) {
GCupval *uv = gco2uv(o);
gc_marktv(g, uvval(uv));
if (uv->closed)
gray2black(o); /* Closed upvalues are never gray. */
} else if (o->gch.gct != ~LJ_TSTR && o->gch.gct != ~LJ_TCDATA) {
lua_assert(o->gch.gct == ~LJ_TFUNC || o->gch.gct == ~LJ_TTAB ||
o->gch.gct == ~LJ_TTHREAD || o->gch.gct == ~LJ_TPROTO);
} else if (gct != ~LJ_TSTR && gct != ~LJ_TCDATA) {
lua_assert(gct == ~LJ_TFUNC || gct == ~LJ_TTAB ||
gct == ~LJ_TTHREAD || gct == ~LJ_TPROTO);
setgcrefr(o->gch.gclist, g->gc.gray);
setgcref(g->gc.gray, o);
}
@ -298,25 +299,26 @@ static void gc_traverse_thread(global_State *g, lua_State *th)
static size_t propagatemark(global_State *g)
{
GCobj *o = gcref(g->gc.gray);
int gct = o->gch.gct;
lua_assert(isgray(o));
gray2black(o);
setgcrefr(g->gc.gray, o->gch.gclist); /* Remove from gray list. */
if (LJ_LIKELY(o->gch.gct == ~LJ_TTAB)) {
if (LJ_LIKELY(gct == ~LJ_TTAB)) {
GCtab *t = gco2tab(o);
if (gc_traverse_tab(g, t) > 0)
black2gray(o); /* Keep weak tables gray. */
return sizeof(GCtab) + sizeof(TValue) * t->asize +
sizeof(Node) * (t->hmask + 1);
} else if (LJ_LIKELY(o->gch.gct == ~LJ_TFUNC)) {
} else if (LJ_LIKELY(gct == ~LJ_TFUNC)) {
GCfunc *fn = gco2func(o);
gc_traverse_func(g, fn);
return isluafunc(fn) ? sizeLfunc((MSize)fn->l.nupvalues) :
sizeCfunc((MSize)fn->c.nupvalues);
} else if (LJ_LIKELY(o->gch.gct == ~LJ_TPROTO)) {
} else if (LJ_LIKELY(gct == ~LJ_TPROTO)) {
GCproto *pt = gco2pt(o);
gc_traverse_proto(g, pt);
return pt->sizept;
} else if (LJ_LIKELY(o->gch.gct == ~LJ_TTHREAD)) {
} else if (LJ_LIKELY(gct == ~LJ_TTHREAD)) {
lua_State *th = gco2th(o);
setgcrefr(th->gclist, g->gc.grayagain);
setgcref(g->gc.grayagain, o);