diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-01 14:06:58 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-01 14:06:58 -0300 |
commit | 9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2 (patch) | |
tree | 748e3f7b84f04d7ab438b9970ac42ef0efe95811 | |
parent | 5fabed21a17b133182a7e47712b7c7602ea87401 (diff) | |
download | lua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.tar.gz lua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.tar.bz2 lua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.zip |
weak keys are removed only after finalization
-rw-r--r-- | lgc.c | 54 | ||||
-rw-r--r-- | lobject.h | 5 | ||||
-rw-r--r-- | ltm.h | 9 |
3 files changed, 53 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.138 2002/06/24 17:19:43 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.139 2002/06/25 19:17:42 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 | */ |
@@ -31,6 +31,17 @@ typedef struct GCState { | |||
31 | #define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} | 31 | #define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} |
32 | 32 | ||
33 | 33 | ||
34 | /* unmarked tables are represented by pointing `mark' to themselves */ | ||
35 | #define ismarked(x) ((x)->mark != (x)) | ||
36 | |||
37 | |||
38 | /* `Table.flag' bits to indicate whether table is key-weak and/or value-weak */ | ||
39 | #define KEYWEAKBIT (TM_MODE+1) /* ORDER TM */ | ||
40 | #define VALUEWEAKBIT (TM_MODE+2) | ||
41 | #define KEYWEAK (1<<KEYWEAKBIT) | ||
42 | #define VALUEWEAK (1<<VALUEWEAKBIT) | ||
43 | |||
44 | |||
34 | /* mark tricks for userdata */ | 45 | /* mark tricks for userdata */ |
35 | #define isudmarked(u) (u->uv.len & 1) | 46 | #define isudmarked(u) (u->uv.len & 1) |
36 | #define markud(u) (u->uv.len |= 1) | 47 | #define markud(u) (u->uv.len |= 1) |
@@ -202,8 +213,8 @@ static void separateudata (lua_State *L) { | |||
202 | 213 | ||
203 | 214 | ||
204 | static void removekey (Node *n) { | 215 | static void removekey (Node *n) { |
205 | lua_assert(ttype(val(n)) == LUA_TNIL); | 216 | setnilvalue(val(n)); /* remove corresponding value ... */ |
206 | if (ttype(key(n)) != LUA_TNIL && ttype(key(n)) != LUA_TNUMBER) | 217 | if (ismarkable(key(n))) |
207 | setttype(key(n), LUA_TNONE); /* dead key; remove it */ | 218 | setttype(key(n), LUA_TNONE); /* dead key; remove it */ |
208 | } | 219 | } |
209 | 220 | ||
@@ -221,6 +232,8 @@ static void traversetable (GCState *st, Table *h) { | |||
221 | st->toclear = h; /* ...put in the appropriate list */ | 232 | st->toclear = h; /* ...put in the appropriate list */ |
222 | weakkey = (strchr(svalue(mode), 'k') != NULL); | 233 | weakkey = (strchr(svalue(mode), 'k') != NULL); |
223 | weakvalue = (strchr(svalue(mode), 'v') != NULL); | 234 | weakvalue = (strchr(svalue(mode), 'v') != NULL); |
235 | h->flags &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ | ||
236 | h->flags |= (weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT); | ||
224 | } | 237 | } |
225 | if (!weakvalue) { | 238 | if (!weakvalue) { |
226 | i = sizearray(h); | 239 | i = sizearray(h); |
@@ -265,11 +278,33 @@ static int hasmark (const TObject *o) { | |||
265 | 278 | ||
266 | 279 | ||
267 | /* | 280 | /* |
268 | ** clear (set to nil) keys and values from weaktables that were collected | 281 | ** clear collected keys from weaktables |
269 | */ | 282 | */ |
270 | static void cleartables (Table *h) { | 283 | static void cleartablekeys (GCState *st) { |
271 | for (; h; h = h->mark) { | 284 | Table *h; |
285 | for (h = st->toclear; h; h = h->mark) { | ||
272 | int i; | 286 | int i; |
287 | if (!(h->flags & KEYWEAK)) continue; | ||
288 | lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'k')); | ||
289 | i = sizenode(h); | ||
290 | while (i--) { | ||
291 | Node *n = node(h, i); | ||
292 | if (!hasmark(key(n))) | ||
293 | removekey(n); /* ... and key */ | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
298 | |||
299 | /* | ||
300 | ** clear collected values from weaktables | ||
301 | */ | ||
302 | static void cleartablevalues (GCState *st) { | ||
303 | Table *h; | ||
304 | for (h = st->toclear; h; h = h->mark) { | ||
305 | int i; | ||
306 | if (!(h->flags & VALUEWEAK)) continue; | ||
307 | lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'v')); | ||
273 | i = sizearray(h); | 308 | i = sizearray(h); |
274 | while (i--) { | 309 | while (i--) { |
275 | TObject *o = &h->array[i]; | 310 | TObject *o = &h->array[i]; |
@@ -279,10 +314,8 @@ static void cleartables (Table *h) { | |||
279 | i = sizenode(h); | 314 | i = sizenode(h); |
280 | while (i--) { | 315 | while (i--) { |
281 | Node *n = node(h, i); | 316 | Node *n = node(h, i); |
282 | if (!hasmark(val(n)) || !hasmark(key(n))) { | 317 | if (!hasmark(val(n))) |
283 | setnilvalue(val(n)); /* remove value ... */ | ||
284 | removekey(n); /* ... and key */ | 318 | removekey(n); /* ... and key */ |
285 | } | ||
286 | } | 319 | } |
287 | } | 320 | } |
288 | } | 321 | } |
@@ -458,10 +491,11 @@ void luaC_collectgarbage (lua_State *L) { | |||
458 | st.toclear = NULL; | 491 | st.toclear = NULL; |
459 | markstacks(&st); /* mark all stacks */ | 492 | markstacks(&st); /* mark all stacks */ |
460 | propagatemarks(&st); /* mark all reachable objects */ | 493 | propagatemarks(&st); /* mark all reachable objects */ |
461 | cleartables(st.toclear); | 494 | cleartablevalues(&st); |
462 | separateudata(L); /* separate userdata to be preserved */ | 495 | separateudata(L); /* separate userdata to be preserved */ |
463 | marktmu(&st); /* mark `preserved' userdata */ | 496 | marktmu(&st); /* mark `preserved' userdata */ |
464 | propagatemarks(&st); /* remark */ | 497 | propagatemarks(&st); /* remark */ |
498 | cleartablekeys(&st); | ||
465 | luaC_collect(L, 0); | 499 | luaC_collect(L, 0); |
466 | checkMbuffer(L); | 500 | checkMbuffer(L); |
467 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | 501 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.137 2002/06/24 13:08:45 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 1.138 2002/06/24 20:17:59 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -217,9 +217,6 @@ typedef struct Table { | |||
217 | } Table; | 217 | } Table; |
218 | 218 | ||
219 | 219 | ||
220 | /* unmarked tables are represented by pointing `mark' to themselves */ | ||
221 | #define ismarked(x) ((x)->mark != (x)) | ||
222 | |||
223 | 220 | ||
224 | /* | 221 | /* |
225 | ** `module' operation for hashing (size is always a power of 2) | 222 | ** `module' operation for hashing (size is always a power of 2) |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 1.36 2002/06/24 20:17:59 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 1.37 2002/06/25 19:17:22 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -10,6 +10,13 @@ | |||
10 | 10 | ||
11 | #include "lobject.h" | 11 | #include "lobject.h" |
12 | 12 | ||
13 | |||
14 | /* | ||
15 | ** Important: garbage collection uses two extra bits of `Table.flags' | ||
16 | ** (after TM_MODE), so the maximum number of `fast tag methods' is six | ||
17 | ** (at least while `flags' is a byte). | ||
18 | */ | ||
19 | |||
13 | /* | 20 | /* |
14 | * WARNING: if you change the order of this enumeration, | 21 | * WARNING: if you change the order of this enumeration, |
15 | * grep "ORDER TM" | 22 | * grep "ORDER TM" |