aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/lgc.c b/lgc.c
index 840bc796..6fd41d34 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
23typedef struct GCState { 23typedef 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*/
242static void cleartablekeys (Table *h) { 248static 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*/
260static void cleartablevalues (Table *h) { 264static 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
399static void mark (lua_State *L) { 402static 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