diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-04-11 11:42:41 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-04-11 11:42:41 -0300 |
commit | 0e0e4a480e6d9b0125a96ca982a3e9571578a037 (patch) | |
tree | 21f13f032e9e337879168c74871d0d4bb2534248 /lgc.c | |
parent | 2a501882692afaa08ecc38af3052e9b4f60f6e85 (diff) | |
download | lua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.tar.gz lua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.tar.bz2 lua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.zip |
first implementation for weak tables
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 59 |
1 files changed, 44 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.94 2001/03/07 18:09:25 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -38,9 +38,6 @@ typedef struct GCState { | |||
38 | 38 | ||
39 | 39 | ||
40 | 40 | ||
41 | static void markobject (GCState *st, TObject *o); | ||
42 | |||
43 | |||
44 | /* mark a string; marks larger than 1 cannot be changed */ | 41 | /* mark a string; marks larger than 1 cannot be changed */ |
45 | #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} | 42 | #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} |
46 | 43 | ||
@@ -144,22 +141,30 @@ static void traverseclosure (GCState *st, Closure *f) { | |||
144 | } | 141 | } |
145 | 142 | ||
146 | 143 | ||
144 | static void removekey (Node *n) { | ||
145 | if (ttype_key(n) != LUA_TNIL && ttype_key(n) != LUA_TNUMBER) | ||
146 | n->key_value.ts = NULL; /* dead key; remove it */ | ||
147 | } | ||
148 | |||
149 | |||
147 | static void traversetable (GCState *st, Hash *h) { | 150 | static void traversetable (GCState *st, Hash *h) { |
148 | int i; | 151 | int i; |
152 | int mode = h->weakmode; | ||
153 | if (mode == (LUA_WEAK_KEY | LUA_WEAK_VALUE)) | ||
154 | return; /* avoid traversing if both keys and values are weak */ | ||
149 | for (i=0; i<h->size; i++) { | 155 | for (i=0; i<h->size; i++) { |
150 | Node *n = node(h, i); | 156 | Node *n = node(h, i); |
151 | if (ttype(val(n)) == LUA_TNIL) { | 157 | if (ttype(val(n)) == LUA_TNIL) |
152 | if (ttype_key(n) != LUA_TNIL) | 158 | removekey(n); |
153 | n->key_value.ts = NULL; /* dead key; remove it */ | ||
154 | } | ||
155 | else { | 159 | else { |
156 | lua_assert(ttype_key(n) != LUA_TNIL); | 160 | lua_assert(ttype_key(n) != LUA_TNIL); |
157 | if (ttype_key(n) != LUA_TNUMBER) { | 161 | if (ttype_key(n) != LUA_TNUMBER && !(mode & LUA_WEAK_KEY)) { |
158 | TObject o; | 162 | TObject k; |
159 | setkey2obj(&o, n); | 163 | setkey2obj(&k, n); |
160 | markobject(st, &o); | 164 | markobject(st, &k); |
161 | } | 165 | } |
162 | markobject(st, &n->val); | 166 | if (!(mode & LUA_WEAK_VALUE)) |
167 | markobject(st, &n->val); | ||
163 | } | 168 | } |
164 | } | 169 | } |
165 | } | 170 | } |
@@ -190,7 +195,6 @@ static void markall (lua_State *L) { | |||
190 | 195 | ||
191 | 196 | ||
192 | static int hasmark (const TObject *o) { | 197 | static int hasmark (const TObject *o) { |
193 | /* valid only for locked objects */ | ||
194 | switch (ttype(o)) { | 198 | switch (ttype(o)) { |
195 | case LUA_TSTRING: case LUA_TUSERDATA: | 199 | case LUA_TSTRING: case LUA_TUSERDATA: |
196 | return tsvalue(o)->marked; | 200 | return tsvalue(o)->marked; |
@@ -198,7 +202,7 @@ static int hasmark (const TObject *o) { | |||
198 | return ismarked(hvalue(o)); | 202 | return ismarked(hvalue(o)); |
199 | case LUA_TFUNCTION: | 203 | case LUA_TFUNCTION: |
200 | return ismarked(clvalue(o)); | 204 | return ismarked(clvalue(o)); |
201 | default: /* number */ | 205 | default: /* number, nil */ |
202 | return 1; | 206 | return 1; |
203 | } | 207 | } |
204 | } | 208 | } |
@@ -224,6 +228,30 @@ static void invalidaterefs (global_State *G) { | |||
224 | } | 228 | } |
225 | 229 | ||
226 | 230 | ||
231 | static void invalidatetable (Hash *h) { | ||
232 | int i; | ||
233 | for (i=0; i<h->size; i++) { | ||
234 | Node *n = node(h, i); | ||
235 | TObject k; | ||
236 | if (ttype(val(n)) == LUA_TNIL) continue; /* empty node */ | ||
237 | setkey2obj(&k, n); | ||
238 | if (!hasmark(val(n)) || !hasmark(&k)) { | ||
239 | setnilvalue(val(n)); /* remove value */ | ||
240 | removekey(n); | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | |||
246 | static void invalidatetables (global_State *G) { | ||
247 | Hash *h; | ||
248 | for (h = G->roottable; h; h = h->next) { | ||
249 | if (ismarked(h) && h->weakmode) | ||
250 | invalidatetable(h); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | |||
227 | 255 | ||
228 | static void collectproto (lua_State *L) { | 256 | static void collectproto (lua_State *L) { |
229 | Proto **p = &G(L)->rootproto; | 257 | Proto **p = &G(L)->rootproto; |
@@ -381,6 +409,7 @@ void luaC_collect (lua_State *L, int all) { | |||
381 | void luaC_collectgarbage (lua_State *L) { | 409 | void luaC_collectgarbage (lua_State *L) { |
382 | markall(L); | 410 | markall(L); |
383 | invalidaterefs(G(L)); /* check unlocked references */ | 411 | invalidaterefs(G(L)); /* check unlocked references */ |
412 | invalidatetables(G(L)); | ||
384 | luaC_collect(L, 0); | 413 | luaC_collect(L, 0); |
385 | checkMbuffer(L); | 414 | checkMbuffer(L); |
386 | G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */ | 415 | G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */ |