aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-12-12 15:47:33 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-12-12 15:47:33 -0200
commit21259a50e12ca45669379a4b37fbe7e502cdd22d (patch)
treecf881a0824e24bcc58eaf4cebbe81c928419e3ba /lgc.c
parent9aff171f3bf0125314a29a5ca952470b2d83708e (diff)
downloadlua-21259a50e12ca45669379a4b37fbe7e502cdd22d.tar.gz
lua-21259a50e12ca45669379a4b37fbe7e502cdd22d.tar.bz2
lua-21259a50e12ca45669379a4b37fbe7e502cdd22d.zip
run GC tag methods in protected mod
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/lgc.c b/lgc.c
index e70dbc77..1be57f2a 100644
--- a/lgc.c
+++ b/lgc.c
@@ -356,32 +356,30 @@ static void checkMbuffer (lua_State *L) {
356} 356}
357 357
358 358
359static void callgcTM (lua_State *L, Udata *udata) { 359static void do1gcTM (lua_State *L, Udata *udata) {
360 const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC); 360 const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC);
361 if (tm != NULL && ttype(tm) == LUA_TFUNCTION) { 361 if (tm != NULL) {
362 int oldah = L->allowhooks;
363 StkId top = L->top; 362 StkId top = L->top;
364 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
365 setobj(top, tm); 363 setobj(top, tm);
366 setuvalue(top+1, udata); 364 setuvalue(top+1, udata);
367 L->top += 2; 365 L->top += 2;
368 luaD_call(L, top); 366 luaD_call(L, top);
369 L->top = top; /* restore top */ 367 L->top = top; /* restore top */
370 L->allowhooks = oldah; /* restore hooks */
371 } 368 }
372} 369}
373 370
374 371
375static void callgcTMudata (lua_State *L) { 372static void unprotectedcallGCTM (lua_State *L, void *pu) {
376 luaD_checkstack(L, 3); 373 luaD_checkstack(L, 3);
377 L->top++; /* reserve space to keep udata while runs its gc method */ 374 L->top++; /* reserve space to keep udata while runs its gc method */
378 while (G(L)->tmudata != NULL) { 375 while (G(L)->tmudata != NULL) {
379 Udata *udata = G(L)->tmudata; 376 Udata *udata = G(L)->tmudata;
380 G(L)->tmudata = udata->uv.next; /* remove udata from list */ 377 G(L)->tmudata = udata->uv.next; /* remove udata from list */
378 *(Udata **)pu = udata; /* keep a reference to it (in case of errors) */
379 setuvalue(L->top - 1, udata); /* and on stack (in case of recursive GC) */
381 udata->uv.next = G(L)->rootudata; /* resurect it */ 380 udata->uv.next = G(L)->rootudata; /* resurect it */
382 G(L)->rootudata = udata; 381 G(L)->rootudata = udata;
383 setuvalue(L->top - 1, udata); 382 do1gcTM(L, udata);
384 callgcTM(L, udata);
385 /* mark udata as finalized (default event table) */ 383 /* mark udata as finalized (default event table) */
386 uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L)); 384 uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L));
387 } 385 }
@@ -389,11 +387,26 @@ static void callgcTMudata (lua_State *L) {
389} 387}
390 388
391 389
390static void callGCTM (lua_State *L) {
391 int oldah = L->allowhooks;
392 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
393 while (G(L)->tmudata != NULL) {
394 Udata *udata;
395 if (luaD_runprotected(L, unprotectedcallGCTM, &udata) != 0) {
396 /* `udata' generated an error during its gc */
397 /* mark it as finalized (default event table) */
398 udata->uv.eventtable = hvalue(defaultet(L));
399 }
400 }
401 L->allowhooks = oldah; /* restore hooks */
402}
403
404
392void luaC_callallgcTM (lua_State *L) { 405void luaC_callallgcTM (lua_State *L) {
393 lua_assert(G(L)->tmudata == NULL); 406 lua_assert(G(L)->tmudata == NULL);
394 G(L)->tmudata = G(L)->rootudata; /* all udata must be collected */ 407 G(L)->tmudata = G(L)->rootudata; /* all udata must be collected */
395 G(L)->rootudata = NULL; 408 G(L)->rootudata = NULL;
396 callgcTMudata(L); /* call their GC tag methods */ 409 callGCTM(L); /* call their GC tag methods */
397} 410}
398 411
399 412
@@ -416,6 +429,6 @@ void luaC_collectgarbage (lua_State *L) {
416 luaC_collect(L, 0); 429 luaC_collect(L, 0);
417 checkMbuffer(L); 430 checkMbuffer(L);
418 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ 431 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
419 callgcTMudata(L); 432 callGCTM(L);
420} 433}
421 434