lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 0e961ad47acbe2d67b72c90cc1ba0040f3907b75
parent c06cc609466d4527848bbf87268ec714942d554a
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Mon, 29 Oct 2007 14:50:57 -0200

some changes toward ephemerons

Diffstat:
Mlgc.c | 135++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mlgc.h | 6+-----
Mlstate.c | 6++++--
Mlstate.h | 6++++--
4 files changed, 98 insertions(+), 55 deletions(-)

diff --git a/lgc.c b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.39 2006/07/11 15:53:29 roberto Exp roberto $ +** $Id: lgc.c,v 2.40 2006/09/11 14:07:24 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -44,10 +44,6 @@ #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) -#define KEYWEAK bitmask(KEYWEAKBIT) -#define VALUEWEAK bitmask(VALUEWEAKBIT) - - #define markvalue(g,o) { checkconsistency(o); \ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } @@ -59,6 +55,12 @@ #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) +static void linktable (Table *h, GCObject **p) { + h->gclist = *p; + *p = obj2gco(h); +} + + static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); if (iscollectable(gkey(n))) @@ -93,8 +95,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { break; } case LUA_TTABLE: { - gco2h(o)->gclist = g->gray; - g->gray = o; + linktable(gco2h(o), &g->gray); break; } case LUA_TTHREAD: { @@ -155,30 +156,48 @@ size_t luaC_separateudata (lua_State *L, int all) { } -static int traversetable (global_State *g, Table *h) { +static void traverseweakvalue (global_State *g, Table *h) { int i; - int weakkey = 0; - int weakvalue = 0; - const TValue *mode; - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); - if (mode && ttisstring(mode)) { /* is there a weak mode? */ - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); - if (weakkey || weakvalue) { /* is really weak? */ - h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ - h->marked |= cast_byte((weakkey << KEYWEAKBIT) | - (weakvalue << VALUEWEAKBIT)); - h->gclist = g->weak; /* must be cleared after GC, ... */ - g->weak = obj2gco(h); /* ... so put in the appropriate list */ + linktable(h, &g->weakvalue); + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); } } - if (weakkey && weakvalue) return 1; - if (!weakvalue) { - i = h->sizearray; - while (i--) - markvalue(g, &h->array[i]); +} + + +static void traverseephemeron (global_State *g, Table *h) { + int i; + linktable(h, &g->weakkey); + i = h->sizearray; + while (i--) /* mark array part (numeric keys are 'strong') */ + markvalue(g, &h->array[i]); + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gval(n)); + } } +} + + +static void traversestrongtable (global_State *g, Table *h) { + int i; + i = h->sizearray; + while (i--) + markvalue(g, &h->array[i]); i = sizenode(h); while (i--) { Node *n = gnode(h, i); @@ -187,11 +206,33 @@ static int traversetable (global_State *g, Table *h) { removeentry(n); /* remove empty entries */ else { lua_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); + markvalue(g, gkey(n)); + markvalue(g, gval(n)); } } - return weakkey || weakvalue; +} + + +static void traversetable (global_State *g, Table *h) { + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobject(g, h->metatable); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + int weakkey = (strchr(svalue(mode), 'k') != NULL); + int weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + black2gray(obj2gco(h)); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else { + lua_assert(weakkey && weakvalue); /* nothing to traverse now */ + linktable(h, &g->weakkeyvalue); + } + return; + } /* else go through */ + } + traversestrongtable(g, h); } @@ -282,8 +323,7 @@ static l_mem propagatemark (global_State *g) { case LUA_TTABLE: { Table *h = gco2h(o); g->gray = h->gclist; - if (traversetable(g, h)) /* table is weak? */ - black2gray(o); /* keep it gray */ + traversetable(g, h); return sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(Node) * sizenode(h); } @@ -352,14 +392,10 @@ static void cleartable (GCObject *l) { while (l) { Table *h = gco2h(l); int i = h->sizearray; - lua_assert(testbit(h->marked, VALUEWEAKBIT) || - testbit(h->marked, KEYWEAKBIT)); - if (testbit(h->marked, VALUEWEAKBIT)) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } + while (i--) { + TValue *o = &h->array[i]; + if (iscleared(o, 0)) /* value was collected? */ + setnilvalue(o); /* remove value */ } i = sizenode(h); while (i--) { @@ -516,7 +552,7 @@ static void markroot (lua_State *L) { global_State *g = G(L); g->gray = NULL; g->grayagain = NULL; - g->weak = NULL; + g->weakvalue = g->weakkey = g->weakkeyvalue = NULL; markobject(g, g->mainthread); /* make global table be traversed before main stack */ markvalue(g, gt(g->mainthread)); @@ -543,13 +579,17 @@ static void atomic (lua_State *L) { remarkupvals(g); /* traverse objects cautch by write barrier and by 'remarkupvals' */ propagateall(g); - /* remark weak tables */ - g->gray = g->weak; - g->weak = NULL; + /* remark value-weak tables */ + g->gray = g->weakvalue; + g->weakvalue = NULL; lua_assert(!iswhite(obj2gco(g->mainthread))); markobject(g, L); /* mark running thread */ markmt(g); /* mark basic metatables (again) */ propagateall(g); + /* remark key-weak tables */ + g->gray = g->weakkey; + g->weakkey = NULL; + propagateall(g); /* remark gray again */ g->gray = g->grayagain; g->grayagain = NULL; @@ -557,7 +597,10 @@ static void atomic (lua_State *L) { udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ marktmu(g); /* mark `preserved' userdata */ udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ + /* remove collected objects from weak tables */ + cleartable(g->weakvalue); + cleartable(g->weakkey); + cleartable(g->weakkeyvalue); /* flip current white */ g->currentwhite = cast_byte(otherwhite(g)); g->sweepstrgc = 0; @@ -656,7 +699,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { /* reset other collector lists */ g->gray = NULL; g->grayagain = NULL; - g->weak = NULL; + g->weakvalue = g->weakkey = g->weakkeyvalue = NULL; g->gcstate = GCSsweepstring; } lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); diff --git a/lgc.h b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp roberto $ +** $Id: lgc.h,v 2.16 2006/07/11 15:53:29 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -44,8 +44,6 @@ ** bit 1 - object is white (type 1) ** bit 2 - object is black ** bit 3 - for userdata: has been finalized -** bit 3 - for tables: has weak keys -** bit 4 - for tables: has weak values ** bit 5 - object is fixed (should not be collected) ** bit 6 - object is "super" fixed (only the main thread) */ @@ -55,8 +53,6 @@ #define WHITE1BIT 1 #define BLACKBIT 2 #define FINALIZEDBIT 3 -#define KEYWEAKBIT 3 -#define VALUEWEAKBIT 4 #define FIXEDBIT 5 #define SFIXEDBIT 6 #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) diff --git a/lstate.c b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.39 2006/09/11 14:07:24 roberto Exp roberto $ +** $Id: lstate.c,v 2.40 2006/10/10 17:40:17 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -182,7 +182,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->sweepgc = &g->rootgc; g->gray = NULL; g->grayagain = NULL; - g->weak = NULL; + g->weakvalue = NULL; + g->weakkey = NULL; + g->weakkeyvalue = NULL; g->tmudata = NULL; g->totalbytes = sizeof(LG); g->gcpause = LUAI_GCPAUSE; diff --git a/lstate.h b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.27 2006/09/19 13:57:50 roberto Exp roberto $ +** $Id: lstate.h,v 2.28 2007/02/07 17:48:52 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -78,7 +78,9 @@ typedef struct global_State { GCObject **sweepgc; /* position of sweep in `rootgc' */ GCObject *gray; /* list of gray objects */ GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of weak tables (to be cleared) */ + GCObject *weakvalue; /* list of value-weak tables */ + GCObject *weakkey; /* list of key-weak tables */ + GCObject *weakkeyvalue; /* list of all-weak tables */ GCObject *tmudata; /* last element of list of userdata to be GC */ Mbuffer buff; /* temporary buffer for string concatentation */ lu_mem GCthreshold;