more generic way to handle 'gclist'

This commit is contained in:
Roberto Ierusalimschy 2018-02-19 17:06:56 -03:00
parent 422318f677
commit 1afd5a152d
6 changed files with 63 additions and 75 deletions

8
lapi.c
View File

@ -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 ** Lua API
** See Copyright Notice in lua.h ** 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)); slot = luaH_set(L, hvalue(o), s2v(L->top - 2));
setobj2t(L, slot, s2v(L->top - 1)); setobj2t(L, slot, s2v(L->top - 1));
invalidateTMcache(hvalue(o)); invalidateTMcache(hvalue(o));
luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); luaC_barrierback(L, gcvalue(o), s2v(L->top - 1));
L->top -= 2; L->top -= 2;
lua_unlock(L); lua_unlock(L);
} }
@ -841,7 +841,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
o = index2value(L, idx); o = index2value(L, idx);
api_check(L, ttistable(o), "table expected"); api_check(L, ttistable(o), "table expected");
luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); 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--; L->top--;
lua_unlock(L); 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)); setpvalue(&k, cast_voidp(p));
slot = luaH_set(L, hvalue(o), &k); slot = luaH_set(L, hvalue(o), &k);
setobj2t(L, slot, s2v(L->top - 1)); 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--; L->top--;
lua_unlock(L); lua_unlock(L);
} }

112
lgc.c
View File

@ -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 ** Garbage Collector
** See Copyright Notice in lua.h ** 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))) #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)) #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 ** 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 ** 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 ** 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.
*/ */
void luaC_barrierback_ (lua_State *L, Table *t) { void luaC_barrierback_ (lua_State *L, GCObject *o) {
global_State *g = G(L); global_State *g = G(L);
lua_assert(isblack(t) && !isdead(g, t)); lua_assert(isblack(o) && !isdead(g, o));
lua_assert(g->gckind != KGC_GEN || (isold(t) && getage(t) != G_TOUCHED1)); lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1));
if (getage(t) != G_TOUCHED2) /* not already in gray list? */ if (getage(o) != G_TOUCHED2) /* not already in gray list? */
linkgclist(t, g->grayagain); /* link it in 'grayagain' */ linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
black2gray(t); /* make table gray (again) */ black2gray(o); /* make table gray (again) */
setage(t, G_TOUCHED1); /* touched in current cycle */ 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 */ markvalue(g, uv->v); /* mark its content */
break; break;
} }
case LUA_TLCL: { case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE:
linkgclist(gco2lcl(o), g->gray); case LUA_TTHREAD: case LUA_TPROTO: {
break; linkobjgclist(o, g->gray);
}
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);
break; break;
} }
default: lua_assert(0); 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) { static lu_mem propagatemark (global_State *g) {
GCObject *o = g->gray; GCObject *o = g->gray;
gray2black(o); gray2black(o);
g->gray = *getgclist(o); /* remove from 'gray' list */
switch (o->tt) { switch (o->tt) {
case LUA_TTABLE: { case LUA_TTABLE: return traversetable(g, gco2t(o));
Table *h = gco2t(o); case LUA_TLCL: return traverseLclosure(g, gco2lcl(o));
g->gray = h->gclist; /* remove from 'gray' list */ case LUA_TCCL: return traverseCclosure(g, gco2ccl(o));
return traversetable(g, h); case LUA_TPROTO: return traverseproto(g, gco2p(o));
}
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_TTHREAD: { case LUA_TTHREAD: {
lua_State *th = gco2th(o); lua_State *th = gco2th(o);
g->gray = th->gclist; /* remove from 'gray' list */
linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
black2gray(o); black2gray(o);
return traversethread(g, th); 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; 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 ** Correct a list of gray objects. Because this correction is
** done after sweeping, young objects can be white and still ** done after sweeping, young objects can be white and still
** be in the list. They are only removed. ** be in the list. They are only removed.
** For tables, advance 'touched1' to 'touched2'; 'touched2' objects ** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2'
** become regular old and are removed from the list. ** objects become regular old and are removed from the list.
** For threads, just remove white ones from the list. ** For threads, just remove white ones from the list.
*/ */
static GCObject **correctgraylist (GCObject **p) { static GCObject **correctgraylist (GCObject **p) {
@ -1078,21 +1066,21 @@ static GCObject **correctgraylist (GCObject **p) {
while ((curr = *p) != NULL) { while ((curr = *p) != NULL) {
switch (curr->tt) { switch (curr->tt) {
case LUA_TTABLE: { case LUA_TTABLE: {
Table *h = gco2t(curr); GCObject **next = getgclist(curr);
if (getage(h) == G_TOUCHED1) { /* touched in this cycle? */ if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */
lua_assert(isgray(h)); lua_assert(isgray(curr));
gray2black(h); /* make it black, for next barrier */ gray2black(curr); /* make it black, for next barrier */
changeage(h, G_TOUCHED1, G_TOUCHED2); changeage(curr, G_TOUCHED1, G_TOUCHED2);
p = &h->gclist; /* go to next element */ p = next; /* go to next element */
} }
else { else {
if (!iswhite(h)) { if (!iswhite(curr)) {
lua_assert(isold(h)); lua_assert(isold(curr));
if (getage(h) == G_TOUCHED2) if (getage(curr) == G_TOUCHED2)
changeage(h, G_TOUCHED2, G_OLD); changeage(curr, G_TOUCHED2, G_OLD);
gray2black(h); /* make it black */ gray2black(curr); /* make it black */
} }
*p = h->gclist; /* remove 'curr' from gray list */ *p = *next; /* remove 'curr' from gray list */
} }
break; break;
} }

4
lgc.h
View File

@ -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 ** Garbage Collector
** See Copyright Notice in lua.h ** 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 void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); 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_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_protobarrier_ (lua_State *L, Proto *p);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);

View File

@ -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) ** Lua tables (hash)
** See Copyright Notice in lua.h ** 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); setnodekey(L, mp, key);
luaC_barrierback(L, t, key); luaC_barrierback(L, obj2gco(t), key);
lua_assert(ttisnil(gval(mp))); lua_assert(ttisnil(gval(mp)));
return gval(mp); return gval(mp);
} }

6
lvm.c
View File

@ -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 ** Lua virtual machine
** See Copyright Notice in lua.h ** 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 */ /* no metamethod and (now) there is an entry with given key */
setobj2t(L, cast(TValue *, slot), val); /* set its new value */ setobj2t(L, cast(TValue *, slot), val); /* set its new value */
invalidateTMcache(h); invalidateTMcache(h);
luaC_barrierback(L, h, val); luaC_barrierback(L, obj2gco(h), val);
return; return;
} }
/* else will try the metamethod */ /* else will try the metamethod */
@ -1691,7 +1691,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *val = s2v(ra + n); TValue *val = s2v(ra + n);
setobj2t(L, &h->array[last - 1], val); setobj2t(L, &h->array[last - 1], val);
last--; last--;
luaC_barrierback(L, h, val); luaC_barrierback(L, obj2gco(h), val);
} }
vmbreak; vmbreak;
} }

4
lvm.h
View File

@ -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 ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -96,7 +96,7 @@
*/ */
#define luaV_finishfastset(L,t,slot,v) \ #define luaV_finishfastset(L,t,slot,v) \
{ setobj2t(L, cast(TValue *,slot), v); \ { setobj2t(L, cast(TValue *,slot), v); \
luaC_barrierback(L, hvalue(t), v); } luaC_barrierback(L, gcvalue(t), v); }