diff options
| -rw-r--r-- | lgc.c | 73 |
1 files changed, 40 insertions, 33 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.154 2002/10/25 20:05:28 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.155 2002/11/07 15:37:10 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 | */ |
| @@ -22,7 +22,9 @@ | |||
| 22 | 22 | ||
| 23 | typedef struct GCState { | 23 | typedef struct GCState { |
| 24 | Table *tmark; /* list of marked tables to be visited */ | 24 | Table *tmark; /* list of marked tables to be visited */ |
| 25 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ | 25 | Table *wk; /* list of visited key-weak tables (to be cleared after GC) */ |
| 26 | Table *wv; /* list of visited value-weak tables */ | ||
| 27 | Table *wkv; /* list of visited key-value weak tables */ | ||
| 26 | lua_State *L; | 28 | lua_State *L; |
| 27 | } GCState; | 29 | } GCState; |
| 28 | 30 | ||
| @@ -198,10 +200,14 @@ static void traversetable (GCState *st, Table *h) { | |||
| 198 | marktable(st, h->metatable); | 200 | marktable(st, h->metatable); |
| 199 | lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); | 201 | lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); |
| 200 | if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */ | 202 | if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */ |
| 203 | Table **weaklist; | ||
| 201 | weakkey = h->mode & WEAKKEY; | 204 | weakkey = h->mode & WEAKKEY; |
| 202 | weakvalue = h->mode & WEAKVALUE; | 205 | weakvalue = h->mode & WEAKVALUE; |
| 203 | h->gclist = st->toclear; /* must be cleared after GC, ... */ | 206 | weaklist = (weakkey && weakvalue) ? &st->wkv : |
| 204 | st->toclear = h; /* ... so put in the appropriate list */ | 207 | (weakkey) ? &st->wk : |
| 208 | &st->wv; | ||
| 209 | h->gclist = *weaklist; /* must be cleared after GC, ... */ | ||
| 210 | *weaklist = h; /* ... so put in the appropriate list */ | ||
| 205 | } | 211 | } |
| 206 | if (!weakvalue) { | 212 | if (!weakvalue) { |
| 207 | i = sizearray(h); | 213 | i = sizearray(h); |
| @@ -241,14 +247,12 @@ static int valismarked (const TObject *o) { | |||
| 241 | */ | 247 | */ |
| 242 | static void cleartablekeys (Table *h) { | 248 | static void cleartablekeys (Table *h) { |
| 243 | for (; h; h = h->gclist) { | 249 | for (; h; h = h->gclist) { |
| 244 | lua_assert(h->mode & (WEAKKEY | WEAKVALUE)); | 250 | int i = sizenode(h); |
| 245 | if ((h->mode & WEAKKEY)) { /* table may have collected keys? */ | 251 | lua_assert(h->mode & WEAKKEY); |
| 246 | int i = sizenode(h); | 252 | while (i--) { |
| 247 | while (i--) { | 253 | Node *n = node(h, i); |
| 248 | Node *n = node(h, i); | 254 | if (!valismarked(key(n))) /* key was collected? */ |
| 249 | if (!valismarked(key(n))) /* key was collected? */ | 255 | removekey(n); /* remove entry from table */ |
| 250 | removekey(n); /* remove entry from table */ | ||
| 251 | } | ||
| 252 | } | 256 | } |
| 253 | } | 257 | } |
| 254 | } | 258 | } |
| @@ -259,19 +263,18 @@ static void cleartablekeys (Table *h) { | |||
| 259 | */ | 263 | */ |
| 260 | static void cleartablevalues (Table *h) { | 264 | static void cleartablevalues (Table *h) { |
| 261 | for (; h; h = h->gclist) { | 265 | for (; h; h = h->gclist) { |
| 262 | if ((h->mode & WEAKVALUE)) { /* table may have collected values? */ | 266 | int i = sizearray(h); |
| 263 | int i = sizearray(h); | 267 | lua_assert(h->mode & WEAKVALUE); |
| 264 | while (i--) { | 268 | while (i--) { |
| 265 | TObject *o = &h->array[i]; | 269 | TObject *o = &h->array[i]; |
| 266 | if (!valismarked(o)) /* value was collected? */ | 270 | if (!valismarked(o)) /* value was collected? */ |
| 267 | setnilvalue(o); /* remove value */ | 271 | setnilvalue(o); /* remove value */ |
| 268 | } | 272 | } |
| 269 | i = sizenode(h); | 273 | i = sizenode(h); |
| 270 | while (i--) { | 274 | while (i--) { |
| 271 | Node *n = node(h, i); | 275 | Node *n = node(h, i); |
| 272 | if (!valismarked(val(n))) /* value was collected? */ | 276 | if (!valismarked(val(n))) /* value was collected? */ |
| 273 | removekey(n); /* remove entry from table */ | 277 | removekey(n); /* remove entry from table */ |
| 274 | } | ||
| 275 | } | 278 | } |
| 276 | } | 279 | } |
| 277 | } | 280 | } |
| @@ -398,22 +401,26 @@ static void markroot (GCState *st) { | |||
| 398 | 401 | ||
| 399 | static void mark (lua_State *L) { | 402 | static void mark (lua_State *L) { |
| 400 | GCState st; | 403 | GCState st; |
| 401 | Table *toclear; | 404 | Table *wkv; |
| 402 | st.L = L; | 405 | st.L = L; |
| 403 | st.tmark = NULL; | 406 | st.tmark = NULL; |
| 404 | st.toclear = NULL; | 407 | st.wkv = st.wk = st.wv = NULL; |
| 405 | markroot(&st); | 408 | markroot(&st); |
| 406 | propagatemarks(&st); /* mark all reachable objects */ | 409 | propagatemarks(&st); /* mark all reachable objects */ |
| 407 | toclear = st.toclear; /* weak tables; to be cleared */ | 410 | cleartablevalues(st.wkv); |
| 408 | st.toclear = NULL; | 411 | cleartablevalues(st.wv); |
| 409 | cleartablevalues(toclear); | 412 | wkv = st.wkv; /* keys must be cleared after preserving udata */ |
| 413 | st.wkv = NULL; | ||
| 414 | st.wv = NULL; | ||
| 410 | separateudata(L); /* separate userdata to be preserved */ | 415 | separateudata(L); /* separate userdata to be preserved */ |
| 411 | marktmu(&st); /* mark `preserved' userdata */ | 416 | marktmu(&st); /* mark `preserved' userdata */ |
| 412 | propagatemarks(&st); /* remark, to propagate `preserveness' */ | 417 | propagatemarks(&st); /* remark, to propagate `preserveness' */ |
| 413 | cleartablekeys(toclear); | 418 | cleartablekeys(wkv); |
| 414 | /* `propagatemarks' may reborne some weak tables; clear them too */ | 419 | /* `propagatemarks' may reborne some weak tables; clear them too */ |
| 415 | cleartablekeys(st.toclear); | 420 | cleartablekeys(st.wk); |
| 416 | cleartablevalues(st.toclear); | 421 | cleartablevalues(st.wv); |
| 422 | cleartablekeys(st.wkv); | ||
| 423 | cleartablevalues(st.wkv); | ||
| 417 | } | 424 | } |
| 418 | 425 | ||
| 419 | 426 | ||
