diff options
| -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" |
