diff options
Diffstat (limited to 'source/extern/lua/lgc.c')
-rw-r--r-- | source/extern/lua/lgc.c | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/source/extern/lua/lgc.c b/source/extern/lua/lgc.c index 973c269..db4df82 100644 --- a/source/extern/lua/lgc.c +++ b/source/extern/lua/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp $ +** $Id: lgc.c,v 2.215.1.2 2017/08/31 16:15:27 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -114,8 +114,13 @@ static void reallymarkobject (global_State *g, GCObject *o); /* -** if key is not marked, mark its entry as dead (therefore removing it -** from the table) +** If key is not marked, mark its entry as dead. This allows key to be +** collected, but keeps its entry in the table. A dead node is needed +** when Lua looks up for a key (it may be part of a chain) and when +** traversing a weak table (key might be removed from the table during +** traversal). Other places never manipulate dead keys, because its +** associated nil value is enough to signal that the entry is logically +** empty. */ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); @@ -462,7 +467,7 @@ static lu_mem traversetable (global_State *g, Table *h) { else /* not weak */ traversestrongtable(g, h); return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * cast(size_t, sizenode(h)); + sizeof(Node) * cast(size_t, allocsizenode(h)); } @@ -534,7 +539,7 @@ static lu_mem traversethread (global_State *g, lua_State *th) { StkId lim = th->stack + th->stacksize; /* real end of stack */ for (; o < lim; o++) /* clear not-marked stack slice */ setnilvalue(o); - /* 'remarkupvals' may have removed thread from 'twups' list */ + /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { th->twups = g->twups; /* link it back to the list */ g->twups = th; @@ -542,7 +547,8 @@ static lu_mem traversethread (global_State *g, lua_State *th) { } else if (g->gckind != KGC_EMERGENCY) luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return (sizeof(lua_State) + sizeof(TValue) * th->stacksize); + return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->nci); } @@ -637,8 +643,9 @@ static void clearkeys (global_State *g, GCObject *l, GCObject *f) { for (n = gnode(h, 0); n < limit; n++) { if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ } + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove entry from table */ } } } @@ -748,14 +755,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { /* ** sweep a list until a live object (or end of list) */ -static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { +static GCObject **sweeptolive (lua_State *L, GCObject **p) { GCObject **old = p; - int i = 0; do { - i++; p = sweeplist(L, p, 1); } while (p == old); - if (n) *n += i; return p; } @@ -769,12 +773,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { */ /* -** If possible, free concatenation buffer and shrink string table +** If possible, shrink string table */ static void checkSizes (lua_State *L, global_State *g) { if (g->gckind != KGC_EMERGENCY) { l_mem olddebt = g->GCdebt; - luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ luaS_resize(L, g->strt.size / 2); /* shrink it a little */ g->GCestimate += g->GCdebt - olddebt; /* update estimate */ @@ -797,7 +800,7 @@ static GCObject *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_call(L, L->top - 2, 0, 0); + luaD_callnoyield(L, L->top - 2, 0); } @@ -816,7 +819,9 @@ static void GCTM (lua_State *L, int propagateerrors) { setobj2s(L, L->top, tm); /* push finalizer... */ setobj2s(L, L->top + 1, &v); /* ... and its argument */ L->top += 2; /* and (next line) call the finalizer */ + L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ g->gcrunning = running; /* restore state */ if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ @@ -851,10 +856,10 @@ static int runafewfinalizers (lua_State *L) { /* ** call all pending finalizers */ -static void callallpendingfinalizers (lua_State *L, int propagateerrors) { +static void callallpendingfinalizers (lua_State *L) { global_State *g = G(L); while (g->tobefnz) - GCTM(L, propagateerrors); + GCTM(L, 0); } @@ -904,7 +909,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { if (issweepphase(g)) { makewhite(g, o); /* "sweep" object 'o' */ if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ - g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ } /* search for pointer pointing to 'o' */ for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } @@ -946,19 +951,16 @@ static void setpause (global_State *g) { /* ** Enter first sweep phase. -** The call to 'sweeptolive' makes pointer point to an object inside -** the list (instead of to the header), so that the real sweep do not -** need to skip objects created between "now" and the start of the real -** sweep. -** Returns how many objects it swept. +** The call to 'sweeplist' tries to make pointer point to an object +** inside the list (instead of to the header), so that the real sweep do +** not need to skip objects created between "now" and the start of the +** real sweep. */ -static int entersweep (lua_State *L) { +static void entersweep (lua_State *L) { global_State *g = G(L); - int n = 0; g->gcstate = GCSswpallgc; lua_assert(g->sweepgc == NULL); - g->sweepgc = sweeptolive(L, &g->allgc, &n); - return n; + g->sweepgc = sweeplist(L, &g->allgc, 1); } @@ -966,7 +968,7 @@ void luaC_freeallobjects (lua_State *L) { global_State *g = G(L); separatetobefnz(g, 1); /* separate all objects with finalizers */ lua_assert(g->finobj == NULL); - callallpendingfinalizers(L, 0); + callallpendingfinalizers(L); lua_assert(g->tobefnz == NULL); g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->gckind = KGC_NORMAL; @@ -1059,12 +1061,11 @@ static lu_mem singlestep (lua_State *L) { } case GCSatomic: { lu_mem work; - int sw; propagateall(g); /* make sure gray list is empty */ work = atomic(L); /* work is what was traversed by 'atomic' */ - sw = entersweep(L); + entersweep(L); g->GCestimate = gettotalbytes(g); /* first estimate */; - return work + sw * GCSWEEPCOST; + return work; } case GCSswpallgc: { /* sweep "regular" objects */ return sweepstep(L, g, GCSswpfinobj, &g->finobj); @@ -1114,9 +1115,12 @@ void luaC_runtilstate (lua_State *L, int statesmask) { static l_mem getdebt (global_State *g) { l_mem debt = g->GCdebt; int stepmul = g->gcstepmul; - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - return debt; + if (debt <= 0) return 0; /* minimal debt */ + else { + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + return debt; + } } /* |