diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 41 |
1 files changed, 28 insertions, 13 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 | ||