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); |
