From 1afd5a152dc8b3a304236dc4e07bca38ea5eb53a Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 19 Feb 2018 17:06:56 -0300 Subject: more generic way to handle 'gclist' --- lapi.c | 8 ++--- lgc.c | 112 ++++++++++++++++++++++++++++----------------------------------- lgc.h | 4 +-- ltable.c | 4 +-- lvm.c | 6 ++-- lvm.h | 4 +-- 6 files changed, 63 insertions(+), 75 deletions(-) diff --git a/lapi.c b/lapi.c index d4bf7e17..1ec649b0 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.282 2018/01/29 16:21:35 roberto Exp roberto $ +** $Id: lapi.c,v 2.283 2018/02/05 17:10:52 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -828,7 +828,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) { slot = luaH_set(L, hvalue(o), s2v(L->top - 2)); setobj2t(L, slot, s2v(L->top - 1)); invalidateTMcache(hvalue(o)); - luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); L->top -= 2; lua_unlock(L); } @@ -841,7 +841,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { o = index2value(L, idx); api_check(L, ttistable(o), "table expected"); luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); - luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); L->top--; lua_unlock(L); } @@ -857,7 +857,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { setpvalue(&k, cast_voidp(p)); slot = luaH_set(L, hvalue(o), &k); setobj2t(L, slot, s2v(L->top - 1)); - luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); L->top--; lua_unlock(L); } diff --git a/lgc.c b/lgc.c index 20397e48..77ccae0a 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.245 2018/01/28 15:13:26 roberto Exp roberto $ +** $Id: lgc.c,v 2.248 2018/02/19 16:02:25 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -110,12 +110,31 @@ static lu_mem atomic (lua_State *L); #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) +static GCObject **getgclist (GCObject *o) { + switch (o->tt) { + case LUA_TTABLE: return &gco2t(o)->gclist; + case LUA_TLCL: return &gco2lcl(o)->gclist; + case LUA_TCCL: return &gco2ccl(o)->gclist; + case LUA_TTHREAD: return &gco2th(o)->gclist; + case LUA_TPROTO: return &gco2p(o)->gclist; + default: lua_assert(0); return 0; + } +} + + /* -** link collectable object 'o' into list pointed by 'p' +** Link a collectable object 'o' with a known type into list pointed by 'p'. */ #define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) +/* +** Link a generic collectable object 'o' into list pointed by 'p'. +*/ +#define linkobjgclist(o,p) (*getgclist(o) = (p), (p) = obj2gco(o)) + + + /* ** Clear keys for empty entries in tables. If entry is empty ** and its key is not marked, mark its entry as dead. This allows the @@ -175,14 +194,14 @@ void luaC_barrier_ (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. */ -void luaC_barrierback_ (lua_State *L, Table *t) { +void luaC_barrierback_ (lua_State *L, GCObject *o) { global_State *g = G(L); - lua_assert(isblack(t) && !isdead(g, t)); - lua_assert(g->gckind != KGC_GEN || (isold(t) && getage(t) != G_TOUCHED1)); - if (getage(t) != G_TOUCHED2) /* not already in gray list? */ - linkgclist(t, g->grayagain); /* link it in 'grayagain' */ - black2gray(t); /* make table gray (again) */ - setage(t, G_TOUCHED1); /* touched in current cycle */ + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1)); + if (getage(o) != G_TOUCHED2) /* not already in gray list? */ + linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ + black2gray(o); /* make table gray (again) */ + setage(o, G_TOUCHED1); /* touched in current cycle */ } @@ -276,24 +295,9 @@ static void reallymarkobject (global_State *g, GCObject *o) { markvalue(g, uv->v); /* mark its content */ break; } - case LUA_TLCL: { - linkgclist(gco2lcl(o), g->gray); - break; - } - case LUA_TCCL: { - linkgclist(gco2ccl(o), g->gray); - break; - } - case LUA_TTABLE: { - linkgclist(gco2t(o), g->gray); - break; - } - case LUA_TTHREAD: { - linkgclist(gco2th(o), g->gray); - break; - } - case LUA_TPROTO: { - linkgclist(gco2p(o), g->gray); + case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: + case LUA_TTHREAD: case LUA_TPROTO: { + linkobjgclist(o, g->gray); break; } default: lua_assert(0); break; @@ -605,34 +609,18 @@ static int traversethread (global_State *g, lua_State *th) { static lu_mem propagatemark (global_State *g) { GCObject *o = g->gray; gray2black(o); + g->gray = *getgclist(o); /* remove from 'gray' list */ switch (o->tt) { - case LUA_TTABLE: { - Table *h = gco2t(o); - g->gray = h->gclist; /* remove from 'gray' list */ - return traversetable(g, h); - } - case LUA_TLCL: { - LClosure *cl = gco2lcl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - return traverseLclosure(g, cl); - } - case LUA_TCCL: { - CClosure *cl = gco2ccl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - return traverseCclosure(g, cl); - } + case LUA_TTABLE: return traversetable(g, gco2t(o)); + case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); + case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); + case LUA_TPROTO: return traverseproto(g, gco2p(o)); case LUA_TTHREAD: { lua_State *th = gco2th(o); - g->gray = th->gclist; /* remove from 'gray' list */ linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ black2gray(o); return traversethread(g, th); } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; /* remove from 'gray' list */ - return traverseproto(g, p); - } default: lua_assert(0); return 0; } } @@ -1069,8 +1057,8 @@ static void whitelist (global_State *g, GCObject *p) { ** Correct a list of gray objects. Because this correction is ** done after sweeping, young objects can be white and still ** be in the list. They are only removed. -** For tables, advance 'touched1' to 'touched2'; 'touched2' objects -** become regular old and are removed from the list. +** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2' +** objects become regular old and are removed from the list. ** For threads, just remove white ones from the list. */ static GCObject **correctgraylist (GCObject **p) { @@ -1078,21 +1066,21 @@ static GCObject **correctgraylist (GCObject **p) { while ((curr = *p) != NULL) { switch (curr->tt) { case LUA_TTABLE: { - Table *h = gco2t(curr); - if (getage(h) == G_TOUCHED1) { /* touched in this cycle? */ - lua_assert(isgray(h)); - gray2black(h); /* make it black, for next barrier */ - changeage(h, G_TOUCHED1, G_TOUCHED2); - p = &h->gclist; /* go to next element */ + GCObject **next = getgclist(curr); + if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ + lua_assert(isgray(curr)); + gray2black(curr); /* make it black, for next barrier */ + changeage(curr, G_TOUCHED1, G_TOUCHED2); + p = next; /* go to next element */ } else { - if (!iswhite(h)) { - lua_assert(isold(h)); - if (getage(h) == G_TOUCHED2) - changeage(h, G_TOUCHED2, G_OLD); - gray2black(h); /* make it black */ + if (!iswhite(curr)) { + lua_assert(isold(curr)); + if (getage(curr) == G_TOUCHED2) + changeage(curr, G_TOUCHED2, G_OLD); + gray2black(curr); /* make it black */ } - *p = h->gclist; /* remove 'curr' from gray list */ + *p = *next; /* remove 'curr' from gray list */ } break; } diff --git a/lgc.h b/lgc.h index fec0e5a7..fc62cfd8 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.100 2018/01/28 15:13:26 roberto Exp roberto $ +** $Id: lgc.h,v 2.102 2018/02/19 13:55:34 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -173,7 +173,7 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); diff --git a/ltable.c b/ltable.c index a8929961..dbe5e2ed 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.130 2017/12/29 15:58:23 roberto Exp roberto $ +** $Id: ltable.c,v 2.131 2018/01/28 15:13:26 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -600,7 +600,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { } } setnodekey(L, mp, key); - luaC_barrierback(L, t, key); + luaC_barrierback(L, obj2gco(t), key); lua_assert(ttisnil(gval(mp))); return gval(mp); } diff --git a/lvm.c b/lvm.c index 0ba6b4bc..0389352f 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.340 2018/02/15 15:34:29 roberto Exp roberto $ +** $Id: lvm.c,v 2.341 2018/02/17 19:20:00 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -223,7 +223,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, /* no metamethod and (now) there is an entry with given key */ setobj2t(L, cast(TValue *, slot), val); /* set its new value */ invalidateTMcache(h); - luaC_barrierback(L, h, val); + luaC_barrierback(L, obj2gco(h), val); return; } /* else will try the metamethod */ @@ -1691,7 +1691,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { TValue *val = s2v(ra + n); setobj2t(L, &h->array[last - 1], val); last--; - luaC_barrierback(L, h, val); + luaC_barrierback(L, obj2gco(h), val); } vmbreak; } diff --git a/lvm.h b/lvm.h index 0d2eed14..2cc4130a 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.47 2017/11/08 14:50:23 roberto Exp roberto $ +** $Id: lvm.h,v 2.48 2017/11/29 13:02:17 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -96,7 +96,7 @@ */ #define luaV_finishfastset(L,t,slot,v) \ { setobj2t(L, cast(TValue *,slot), v); \ - luaC_barrierback(L, hvalue(t), v); } + luaC_barrierback(L, gcvalue(t), v); } -- cgit v1.2.3-55-g6feb