aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-07-01 14:06:58 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-07-01 14:06:58 -0300
commit9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2 (patch)
tree748e3f7b84f04d7ab438b9970ac42ef0efe95811
parent5fabed21a17b133182a7e47712b7c7602ea87401 (diff)
downloadlua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.tar.gz
lua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.tar.bz2
lua-9f4b5b52327497e3ce82cb0af1d94ad6c09b1da2.zip
weak keys are removed only after finalization
-rw-r--r--lgc.c54
-rw-r--r--lobject.h5
-rw-r--r--ltm.h9
3 files changed, 53 insertions, 15 deletions
diff --git a/lgc.c b/lgc.c
index c7429c26..e5ecb9c6 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
204static void removekey (Node *n) { 215static 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*/
270static void cleartables (Table *h) { 283static 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*/
302static 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 */
diff --git a/lobject.h b/lobject.h
index 259c2977..616b897c 100644
--- a/lobject.h
+++ b/lobject.h
@@ -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)
diff --git a/ltm.h b/ltm.h
index c99bd59d..d6eab0eb 100644
--- a/ltm.h
+++ b/ltm.h
@@ -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"