diff options
Diffstat (limited to 'apps/plugins/lua/lgc.c')
-rw-r--r-- | apps/plugins/lua/lgc.c | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c index 98194c1771..17b64a103b 100644 --- a/apps/plugins/lua/lgc.c +++ b/apps/plugins/lua/lgc.c @@ -58,6 +58,9 @@ #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) +#ifndef yield + #define yield() {} +#endif static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); @@ -232,8 +235,10 @@ static void traverseclosure (global_State *g, Closure *cl) { int i; lua_assert(cl->l.nupvalues == cl->l.p->nups); markobject(g, cl->l.p); - for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->l.upvals[i]); + for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ + if(cl->l.upvals[i]) + markobject(g, cl->l.upvals[i]); + } } } @@ -258,6 +263,7 @@ static void traversestack (global_State *g, lua_State *l) { CallInfo *ci; markvalue(g, gt(l)); lim = l->top; + if(l->stack == NULL) return; /* no stack to traverse */ for (ci = l->base_ci; ci <= l->ci; ci++) { lua_assert(ci->top <= l->stack_last); if (lim < ci->top) lim = ci->top; @@ -266,7 +272,8 @@ static void traversestack (global_State *g, lua_State *l) { markvalue(g, o); for (; o <= lim; o++) setnilvalue(o); - checkstacksizes(l, lim); + if (!isfixedstack(l)) /* if stack size is fixed, can't resize it. */ + checkstacksizes(l, lim); } @@ -419,8 +426,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ freeobj(L, curr); } } @@ -434,6 +439,8 @@ static void checkSizes (lua_State *L) { if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && g->strt.size > MINSTRTABSIZE*2) luaS_resize(L, g->strt.size/2); /* table is too big */ + /* it is not safe to re-size the buffer if it is in use. */ + if (luaZ_bufflen(&g->buff) > 0) return; /* check size of buffer */ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; @@ -552,6 +559,15 @@ static void atomic (lua_State *L) { g->estimate = g->totalbytes - udsize; /* first estimate */ } +static void sweepstrstep (global_State *g, lua_State *L) { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; +} + static l_mem singlestep (lua_State *L) { global_State *g = G(L); @@ -570,12 +586,7 @@ static l_mem singlestep (lua_State *L) { } } case GCSsweepstring: { - lu_mem old = g->totalbytes; - sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); - if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ - g->gcstate = GCSsweep; /* end sweep-string phase */ - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; + sweepstrstep(g, L); return GCSWEEPCOST; } case GCSsweep: { @@ -609,10 +620,14 @@ static l_mem singlestep (lua_State *L) { void luaC_step (lua_State *L) { global_State *g = G(L); + if(is_block_gc(L)) return; + set_block_gc(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; if (lim == 0) lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; + if (g->estimate > g->totalbytes) + g->estimate = g->totalbytes; do { lim -= singlestep(L); if (g->gcstate == GCSpause) @@ -629,11 +644,23 @@ void luaC_step (lua_State *L) { else { setthreshold(g); } + unset_block_gc(L); } +int luaC_sweepstrgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate == GCSsweepstring) { + sweepstrstep(g, L); + return (g->gcstate == GCSsweepstring) ? 1 : 0; + } + return 0; +} + void luaC_fullgc (lua_State *L) { global_State *g = G(L); + if(is_block_gc(L)) return; + set_block_gc(L); if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; @@ -649,12 +676,15 @@ void luaC_fullgc (lua_State *L) { while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); + yield(); } markroot(L); while (g->gcstate != GCSpause) { singlestep(L); + yield(); } setthreshold(g); + unset_block_gc(L); } @@ -682,6 +712,14 @@ void luaC_barrierback (lua_State *L, Table *t) { } +void luaC_marknew (lua_State *L, GCObject *o) { + global_State *g = G(L); + o->gch.marked = luaC_white(g); + if (g->gcstate == GCSpropagate) + reallymarkobject(g, o); /* mark new objects as gray during propagate state. */ +} + + void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { global_State *g = G(L); o->gch.next = g->rootgc; |