diff --git a/lapi.c b/lapi.c index 0cde72cc..d6d7a8db 100644 --- a/lapi.c +++ b/lapi.c @@ -1145,7 +1145,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { } case LUA_GCRESTART: { luaE_setdebt(g, 0); - g->gcstp = 0; /* (GCSTPGC must be already zero here) */ + g->gcstp = 0; /* (bit GCSTPGC must be zero here) */ break; } case LUA_GCCOLLECT: { @@ -1162,21 +1162,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { break; } case LUA_GCSTEP: { - int data = va_arg(argp, int); - l_obj debt = 1; /* =1 to signal that it did an actual step */ + int todo = va_arg(argp, int); /* work to be done */ + int didsomething = 0; lu_byte oldstp = g->gcstp; - g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ - if (data == 0) { - luaE_setdebt(g, 0); /* do a basic step */ - luaC_step(L); - } - else { /* add 'data' to total debt */ - debt = data + g->GCdebt; - luaE_setdebt(g, debt); - luaC_checkGC(L); + g->gcstp = 0; /* allow GC to run (bit GCSTPGC must be zero here) */ + if (todo == 0) + todo = 1 << g->gcstepsize; /* standard step size */ + while (todo + g->GCdebt > 0) { /* enough to run a step? */ + todo += g->GCdebt; /* decrement 'todo' (debt is usually negative) */ + luaC_step(L); /* run one basic step */ + didsomething = 1; + if (g->gckind == KGC_GEN) /* minor collections? */ + todo = 0; /* doesn't make sense to repeat in this case */ + else if (g->gcstate == GCSpause) + break; /* don't run more than one cycle */ } + /* add remaining 'todo' to total debt */ + luaE_setdebt(g, todo + g->GCdebt); g->gcstp = oldstp; /* restore previous state */ - if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + if (didsomething && g->gcstate == GCSpause) /* end of cycle? */ res = 1; /* signal it */ break; } diff --git a/lgc.c b/lgc.c index 1b24fda6..c93b5994 100644 --- a/lgc.c +++ b/lgc.c @@ -1037,7 +1037,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { */ static void setpause (global_State *g) { unsigned int pause = getgcparam(g->gcpause); - lu_mem threshold = g->marked / 8 * pause / 12; + l_obj threshold = g->marked / 8 * pause / 12; l_obj debt = gettotalobjs(g) - threshold; if (debt > 0) debt = 0; luaE_setdebt(g, debt); @@ -1600,18 +1600,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) { ** controls when next step will be performed. */ static void incstep (lua_State *L, global_State *g) { - int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ - l_obj debt = (g->GCdebt / 100) * stepmul; l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; + l_obj work2do = stepsize * getgcparam(g->gcstepmul) / 100; do { /* repeat until pause or enough "credit" (negative debt) */ l_obj work = singlestep(L); /* perform one single step */ - debt -= work; - } while (debt > -stepsize && g->gcstate != GCSpause); + work2do -= work; + } while (work2do > 0 && g->gcstate != GCSpause); if (g->gcstate == GCSpause) setpause(g); /* pause until next cycle */ else { - debt = (debt / stepmul) * 100; /* apply step multiplier */ - luaE_setdebt(g, debt); + luaE_setdebt(g, -stepsize); } }