diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-21 13:41:34 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-21 13:41:34 -0300 |
commit | 777061e441ecbb9e3522aa5c88d9204decc9ff81 (patch) | |
tree | f974a57d8377be76b645de07f4c847dd6d15eaaf | |
parent | fccadba4b54f8e13c8b9cfc97307f53931496936 (diff) | |
download | lua-777061e441ecbb9e3522aa5c88d9204decc9ff81.tar.gz lua-777061e441ecbb9e3522aa5c88d9204decc9ff81.tar.bz2 lua-777061e441ecbb9e3522aa5c88d9204decc9ff81.zip |
resurect userdata before calling its GC tag method
-rw-r--r-- | lgc.c | 41 | ||||
-rw-r--r-- | lgc.h | 5 | ||||
-rw-r--r-- | lstate.c | 10 |
3 files changed, 34 insertions, 22 deletions
@@ -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 | ||
271 | void luaC_collectudata (lua_State *L) { | 271 | static 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 | ||
341 | void luaC_callgcTMudata (lua_State *L) { | 345 | static 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 | ||
364 | void 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 | |||
356 | void luaC_collect (lua_State *L, int all) { | 372 | void 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 | ||
@@ -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 | ||
18 | void luaC_collectudata (lua_State *L); | 18 | void luaC_callallgcTM (lua_State *L); |
19 | void luaC_callgcTMudata (lua_State *L); | ||
20 | void luaC_collect (lua_State *L, int all); | 19 | void luaC_collect (lua_State *L, int all); |
21 | void luaC_collectgarbage (lua_State *L); | 20 | void luaC_collectgarbage (lua_State *L); |
22 | 21 | ||
@@ -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); |