lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 551b076f1c7f9b66eecd8f6b7a12b1bd7a78b967
parent 737f119187aca3c8f6743ec6e3cfc04e83723180
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Mon, 20 Dec 2010 17:39:43 -0200

change in the relationship between totalbytes and GCdebt - luaM_realloc_
is too critical to update two counters

Diffstat:
Mlapi.c | 8++++----
Mlgc.c | 23+++++++++++++----------
Mlmem.c | 5++---
Mlstate.c | 15+++++++++------
Mlstate.h | 10+++++++---
5 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/lapi.c b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.141 2010/11/26 14:32:31 roberto Exp roberto $ +** $Id: lapi.c,v 2.142 2010/12/20 18:17:46 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -964,7 +964,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } case LUA_GCRESTART: { - g->GCdebt = 0; + luaE_setdebt(g, 0); g->gcrunning = 1; break; } @@ -975,11 +975,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { } case LUA_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(g->totalbytes >> 10); + res = cast_int(gettotalbytes(g) >> 10); break; } case LUA_GCCOUNTB: { - res = cast_int(g->totalbytes & 0x3ff); + res = cast_int(gettotalbytes(g) & 0x3ff); break; } case LUA_GCSTEP: { diff --git a/lgc.c b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.105 2010/12/03 11:48:25 roberto Exp roberto $ +** $Id: lgc.c,v 2.106 2010/12/20 18:17:46 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -51,7 +51,7 @@ ** standard negative debt for GC; a reasonable "time" to wait before ** starting a new cycle */ -#define stddebt(g) (-cast(l_mem, g->totalbytes/100) * g->gcpause) +#define stddebt(g) (-cast(l_mem, gettotalbytes(g)/100) * g->gcpause) /* @@ -634,6 +634,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { int ow = otherwhite(g); int toclear, toset; /* bits to clear and to set in all live objects */ int tostop; /* stop sweep when this is true */ + l_mem debt = g->GCdebt; /* current debt */ if (isgenerational(g)) { /* generational mode? */ toclear = ~0; /* clear nothing */ toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ @@ -656,13 +657,15 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ if (testbits(marked, tostop)) { static GCObject *nullp = NULL; - return &nullp; /* stop sweeping this list */ + p = &nullp; /* stop sweeping this list */ + break; } /* update marks */ gch(curr)->marked = cast_byte((marked & toclear) | toset); p = &gch(curr)->next; /* go to next element */ } } + luaE_setdebt(g, debt); /* sweeping should not change debt */ return p; } @@ -807,7 +810,7 @@ void luaC_changemode (lua_State *L, int mode) { if (mode == KGC_GEN) { /* change to generational mode */ /* make sure gray lists are consistent */ luaC_runtilstate(L, bitmask(GCSpropagate)); - g->lastmajormem = g->totalbytes; + g->lastmajormem = gettotalbytes(g); g->gckind = KGC_GEN; } else { /* change to incremental mode */ @@ -958,15 +961,15 @@ static void generationalcollection (lua_State *L) { global_State *g = G(L); if (g->lastmajormem == 0) { /* signal for another major collection? */ luaC_fullgc(L, 0); /* perform a full regular collection */ - g->lastmajormem = g->totalbytes; /* update control */ + g->lastmajormem = gettotalbytes(g); /* update control */ } else { luaC_runtilstate(L, ~bitmask(GCSpause)); /* run complete cycle */ luaC_runtilstate(L, bitmask(GCSpause)); - if (g->totalbytes > g->lastmajormem/100 * g->gcmajorinc) + if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc) g->lastmajormem = 0; /* signal for a major collection */ } - g->GCdebt = stddebt(g); + luaE_setdebt(g, stddebt(g)); } @@ -977,9 +980,9 @@ static void step (lua_State *L) { lim -= singlestep(L); } while (lim > 0 && g->gcstate != GCSpause); if (g->gcstate != GCSpause) - g->GCdebt -= GCSTEPSIZE; + luaE_setdebt(g, g->GCdebt - GCSTEPSIZE); else - g->GCdebt = stddebt(g); + luaE_setdebt(g, stddebt(g)); } @@ -1022,7 +1025,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { luaC_runtilstate(L, bitmask(GCSpropagate)); } g->gckind = origkind; - g->GCdebt = stddebt(g); + luaE_setdebt(g, stddebt(g)); if (!isemergency) /* do not run finalizers during emergency GC */ callallpendingfinalizers(L, 1); } diff --git a/lmem.c b/lmem.c @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.79 2010/05/05 18:49:56 roberto Exp roberto $ +** $Id: lmem.c,v 1.80 2010/12/20 18:17:46 roberto Exp roberto $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -94,8 +94,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { luaD_throw(L, LUA_ERRMEM); } lua_assert((nsize == 0) == (newblock == NULL)); - g->totalbytes = (g->totalbytes - realosize) + nsize; - g->GCdebt += nsize; /* give some credit to garbage collector */ + g->GCdebt = (g->GCdebt + nsize) - realosize; #if defined(TRACEMEM) { /* auxiliary patch to monitor garbage collection. ** To plot, gnuplot with following command: diff --git a/lstate.c b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.87 2010/11/26 14:32:31 roberto Exp roberto $ +** $Id: lstate.c,v 2.88 2010/12/20 18:17:46 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -65,11 +65,14 @@ typedef struct LG { #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) - /* -** maximum number of nested calls made by error-handling function +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant */ -#define LUAI_EXTRACALLS 10 +void luaE_setdebt (global_State *g, l_mem debt) { + g->totalbytes -= (debt - g->GCdebt); + g->GCdebt = debt; +} CallInfo *luaE_extendCI (lua_State *L) { @@ -154,7 +157,6 @@ static void f_luaopen (lua_State *L, void *ud) { /* pre-create memory-error message */ g->memerrmsg = luaS_newliteral(L, MEMERRMSG); luaS_fix(g->memerrmsg); /* it should never be collected */ - g->GCdebt = 0; g->gcrunning = 1; /* allow gc */ } @@ -188,7 +190,7 @@ static void close_state (lua_State *L) { luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); luaZ_freebuffer(L, &g->buff); freestack(L); - lua_assert(g->totalbytes == sizeof(LG)); + lua_assert(gettotalbytes(g) == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); } @@ -258,6 +260,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->gray = g->grayagain = NULL; g->weak = g->ephemeron = g->allweak = NULL; g->totalbytes = sizeof(LG); + g->GCdebt = 0; g->gcpause = LUAI_GCPAUSE; g->gcmajorinc = LUAI_GCMAJOR; g->gcstepmul = LUAI_GCMUL; diff --git a/lstate.h b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.69 2010/11/26 14:32:31 roberto Exp roberto $ +** $Id: lstate.h,v 2.70 2010/12/20 18:17:46 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -114,8 +114,8 @@ typedef struct CallInfo { typedef struct global_State { lua_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to `frealloc' */ - lu_mem totalbytes; /* number of bytes currently allocated */ - l_mem GCdebt; /* when positive, run a GC step */ + lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ lu_mem lastmajormem; /* memory in use after last major collection */ stringtable strt; /* hash table for strings */ TValue l_registry; @@ -210,6 +210,10 @@ union GCObject { #define obj2gco(v) (cast(GCObject *, (v))) +/* actual number of total bytes allocated */ +#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); LUAI_FUNC void luaE_freeCI (lua_State *L);