From 0e0e4a480e6d9b0125a96ca982a3e9571578a037 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 11 Apr 2001 11:42:41 -0300 Subject: first implementation for weak tables --- lgc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 15 deletions(-) (limited to 'lgc.c') diff --git a/lgc.c b/lgc.c index 3a665660..a7f96f8c 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.94 2001/03/07 18:09:25 roberto Exp roberto $ +** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -38,9 +38,6 @@ typedef struct GCState { -static void markobject (GCState *st, TObject *o); - - /* mark a string; marks larger than 1 cannot be changed */ #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} @@ -144,22 +141,30 @@ static void traverseclosure (GCState *st, Closure *f) { } +static void removekey (Node *n) { + if (ttype_key(n) != LUA_TNIL && ttype_key(n) != LUA_TNUMBER) + n->key_value.ts = NULL; /* dead key; remove it */ +} + + static void traversetable (GCState *st, Hash *h) { int i; + int mode = h->weakmode; + if (mode == (LUA_WEAK_KEY | LUA_WEAK_VALUE)) + return; /* avoid traversing if both keys and values are weak */ for (i=0; isize; i++) { Node *n = node(h, i); - if (ttype(val(n)) == LUA_TNIL) { - if (ttype_key(n) != LUA_TNIL) - n->key_value.ts = NULL; /* dead key; remove it */ - } + if (ttype(val(n)) == LUA_TNIL) + removekey(n); else { lua_assert(ttype_key(n) != LUA_TNIL); - if (ttype_key(n) != LUA_TNUMBER) { - TObject o; - setkey2obj(&o, n); - markobject(st, &o); + if (ttype_key(n) != LUA_TNUMBER && !(mode & LUA_WEAK_KEY)) { + TObject k; + setkey2obj(&k, n); + markobject(st, &k); } - markobject(st, &n->val); + if (!(mode & LUA_WEAK_VALUE)) + markobject(st, &n->val); } } } @@ -190,7 +195,6 @@ static void markall (lua_State *L) { static int hasmark (const TObject *o) { - /* valid only for locked objects */ switch (ttype(o)) { case LUA_TSTRING: case LUA_TUSERDATA: return tsvalue(o)->marked; @@ -198,7 +202,7 @@ static int hasmark (const TObject *o) { return ismarked(hvalue(o)); case LUA_TFUNCTION: return ismarked(clvalue(o)); - default: /* number */ + default: /* number, nil */ return 1; } } @@ -224,6 +228,30 @@ static void invalidaterefs (global_State *G) { } +static void invalidatetable (Hash *h) { + int i; + for (i=0; isize; i++) { + Node *n = node(h, i); + TObject k; + if (ttype(val(n)) == LUA_TNIL) continue; /* empty node */ + setkey2obj(&k, n); + if (!hasmark(val(n)) || !hasmark(&k)) { + setnilvalue(val(n)); /* remove value */ + removekey(n); + } + } +} + + +static void invalidatetables (global_State *G) { + Hash *h; + for (h = G->roottable; h; h = h->next) { + if (ismarked(h) && h->weakmode) + invalidatetable(h); + } +} + + static void collectproto (lua_State *L) { Proto **p = &G(L)->rootproto; @@ -381,6 +409,7 @@ void luaC_collect (lua_State *L, int all) { void luaC_collectgarbage (lua_State *L) { markall(L); invalidaterefs(G(L)); /* check unlocked references */ + invalidatetables(G(L)); luaC_collect(L, 0); checkMbuffer(L); G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */ -- cgit v1.2.1