aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-06-21 13:41:34 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-06-21 13:41:34 -0300
commit777061e441ecbb9e3522aa5c88d9204decc9ff81 (patch)
treef974a57d8377be76b645de07f4c847dd6d15eaaf
parentfccadba4b54f8e13c8b9cfc97307f53931496936 (diff)
downloadlua-777061e441ecbb9e3522aa5c88d9204decc9ff81.tar.gz
lua-777061e441ecbb9e3522aa5c88d9204decc9ff81.tar.bz2
lua-777061e441ecbb9e3522aa5c88d9204decc9ff81.zip
resurect userdata before calling its GC tag method
-rw-r--r--lgc.c41
-rw-r--r--lgc.h5
-rw-r--r--lstate.c10
3 files changed, 34 insertions, 22 deletions
diff --git a/lgc.c b/lgc.c
index de5998e3..11119585 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.105 2001/06/15 19:17:33 roberto Exp roberto $ 2** $Id: lgc.c,v 1.106 2001/06/15 20:36:57 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*/
@@ -268,7 +268,7 @@ static void collecttable (lua_State *L) {
268} 268}
269 269
270 270
271void luaC_collectudata (lua_State *L) { 271static void collectudata (lua_State *L, int keep) {
272 Udata **p = &G(L)->rootudata; 272 Udata **p = &G(L)->rootudata;
273 Udata *curr; 273 Udata *curr;
274 while ((curr = *p) != NULL) { 274 while ((curr = *p) != NULL) {
@@ -279,8 +279,13 @@ void luaC_collectudata (lua_State *L) {
279 else { /* collect */ 279 else { /* collect */
280 int tag = curr->uv.tag; 280 int tag = curr->uv.tag;
281 *p = curr->uv.next; 281 *p = curr->uv.next;
282 curr->uv.next = G(L)->TMtable[tag].collected; /* chain udata */ 282 if (keep || /* must keep all of them (to close state)? */
283 G(L)->TMtable[tag].collected = curr; 283 luaT_gettm(G(L), tag, TM_GC)) { /* or is there a GC tag method? */
284 curr->uv.next = G(L)->TMtable[tag].collected; /* chain udata ... */
285 G(L)->TMtable[tag].collected = curr; /* ... to call its TM later */
286 }
287 else /* no tag method; delete udata */
288 luaM_free(L, curr, sizeudata(curr->uv.len));
284 } 289 }
285 } 290 }
286} 291}
@@ -327,7 +332,6 @@ static void callgcTM (lua_State *L, const TObject *obj) {
327 int oldah = L->allowhooks; 332 int oldah = L->allowhooks;
328 StkId top = L->top; 333 StkId top = L->top;
329 L->allowhooks = 0; /* stop debug hooks during GC tag methods */ 334 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
330 luaD_checkstack(L, 2);
331 setclvalue(top, tm); 335 setclvalue(top, tm);
332 setobj(top+1, obj); 336 setobj(top+1, obj);
333 L->top += 2; 337 L->top += 2;
@@ -338,23 +342,35 @@ static void callgcTM (lua_State *L, const TObject *obj) {
338} 342}
339 343
340 344
341void luaC_callgcTMudata (lua_State *L) { 345static void callgcTMudata (lua_State *L) {
342 int tag; 346 int tag;
347 luaD_checkstack(L, 3);
343 for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */ 348 for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */
344 Udata *udata; 349 Udata *udata;
345 while ((udata = G(L)->TMtable[tag].collected) != NULL) { 350 while ((udata = G(L)->TMtable[tag].collected) != NULL) {
346 TObject obj;
347 G(L)->TMtable[tag].collected = udata->uv.next; /* remove it from list */ 351 G(L)->TMtable[tag].collected = udata->uv.next; /* remove it from list */
348 setuvalue(&obj, udata); 352 udata->uv.next = G(L)->rootudata; /* resurect it */
349 callgcTM(L, &obj); 353 G(L)->rootudata = udata;
350 luaM_free(L, udata, sizeudata(udata->uv.len)); 354 setuvalue(L->top, udata);
355 L->top++; /* keep it in stack to avoid being (recursively) collected */
356 callgcTM(L, L->top-1);
357 uvalue(L->top-1)->uv.tag = 0; /* default tag (udata is `finalized') */
358 L->top--;
351 } 359 }
352 } 360 }
353} 361}
354 362
355 363
364void luaC_callallgcTM (lua_State *L) {
365 if (G(L)->rootudata) { /* avoid problems with incomplete states */
366 collectudata(L, 1); /* collect all udata into tag lists */
367 callgcTMudata(L); /* call their GC tag methods */
368 }
369}
370
371
356void luaC_collect (lua_State *L, int all) { 372void luaC_collect (lua_State *L, int all) {
357 luaC_collectudata(L); 373 collectudata(L, 0);
358 collectstrings(L, all); 374 collectstrings(L, all);
359 collecttable(L); 375 collecttable(L);
360 collectproto(L); 376 collectproto(L);
@@ -367,9 +383,8 @@ void luaC_collectgarbage (lua_State *L) {
367 cleartables(G(L)); 383 cleartables(G(L));
368 luaC_collect(L, 0); 384 luaC_collect(L, 0);
369 checkMbuffer(L); 385 checkMbuffer(L);
370 G(L)->GCthreshold = 2*G(L)->nblocks; /* temporary threshold (for TM) */
371 luaC_callgcTMudata(L);
372 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ 386 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
387 callgcTMudata(L);
373 callgcTM(L, &luaO_nilobject); 388 callgcTM(L, &luaO_nilobject);
374} 389}
375 390
diff --git a/lgc.h b/lgc.h
index 7268e4c2..7e1e5478 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 1.10 2001/06/05 19:27:32 roberto Exp roberto $ 2** $Id: lgc.h,v 1.11 2001/06/12 18:43:13 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*/
@@ -15,8 +15,7 @@
15 luaC_collectgarbage(L) 15 luaC_collectgarbage(L)
16 16
17 17
18void luaC_collectudata (lua_State *L); 18void luaC_callallgcTM (lua_State *L);
19void luaC_callgcTMudata (lua_State *L);
20void luaC_collect (lua_State *L, int all); 19void luaC_collect (lua_State *L, int all);
21void luaC_collectgarbage (lua_State *L); 20void luaC_collectgarbage (lua_State *L);
22 21
diff --git a/lstate.c b/lstate.c
index 65c1cde4..6c2c4c17 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.63 2001/06/06 18:00:19 roberto Exp roberto $ 2** $Id: lstate.c,v 1.64 2001/06/12 18:43:13 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -112,12 +112,10 @@ static void close_state (lua_State *L, lua_State *OL) {
112 L->next->previous = L->previous; 112 L->next->previous = L->previous;
113 } 113 }
114 else if (G(L)) { /* last thread; close global state */ 114 else if (G(L)) { /* last thread; close global state */
115 while (G(L)->rootudata) { 115 luaC_callallgcTM(L); /* call GC tag methods for all udata */
116 luaC_collectudata(L); /* collect all user data */ 116 luaC_collect(L, 1); /* collect all elements */
117 luaC_callgcTMudata(L); /* call their tag methods */
118 } /* repeat, as tag methods may create new userdata objects */
119 luaC_collect(L, 1); /* collect all other elements */
120 lua_assert(G(L)->rootproto == NULL); 117 lua_assert(G(L)->rootproto == NULL);
118 lua_assert(G(L)->rootudata == NULL);
121 lua_assert(G(L)->rootcl == NULL); 119 lua_assert(G(L)->rootcl == NULL);
122 lua_assert(G(L)->roottable == NULL); 120 lua_assert(G(L)->roottable == NULL);
123 luaS_freeall(L); 121 luaS_freeall(L);