diff --git a/lapi.c b/lapi.c index 59dcb612..3a0dbdae 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.114 2010/03/08 16:55:52 roberto Exp roberto $ +** $Id: lapi.c,v 2.115 2010/03/22 18:28:03 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -928,7 +928,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } case LUA_GCRESTART: { - g->gckind = KGC_NORMAL; g->GCthreshold = g->totalbytes; break; } @@ -947,13 +946,19 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { } case LUA_GCSTEP: { lu_mem oldts = g->GCthreshold; - lu_mem a = (cast(lu_mem, data) << 10); - g->GCthreshold = (a <= g->totalbytes) ? g->totalbytes - a : 0; - while (g->GCthreshold <= g->totalbytes) { - luaC_step(L); - if (g->gcstate == GCSpause) { /* end of cycle? */ - res = 1; /* signal it */ - break; + if (g->gckind == KGC_GEN) { /* generational mode? */ + res = (g->lastmajormem == 0); /* 1 if will do major collection */ + luaC_step(L); /* do a single step */ + } + else { + lu_mem a = (cast(lu_mem, data) << 10); + g->GCthreshold = (a <= g->totalbytes) ? g->totalbytes - a : 0; + while (g->GCthreshold <= g->totalbytes) { + luaC_step(L); + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } } } if (oldts == MAX_LUMEM) /* collector was stopped? */ @@ -976,6 +981,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { } case LUA_GCGEN: { /* change collector to generational mode */ luaC_runtilstate(L, bitmask(GCSpropagate)); + g->lastmajormem = g->totalbytes; g->gckind = KGC_GEN; break; } diff --git a/lgc.c b/lgc.c index 9c5cdb4f..b8ab674f 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.71 2010/03/24 15:51:10 roberto Exp roberto $ +** $Id: lgc.c,v 2.72 2010/03/25 13:06:36 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -835,11 +835,19 @@ static int prev = 0; global_State *g = G(L); int a = g->totalbytes; lua_assert(g->gcstate == GCSpropagate); - luaC_runtilstate(L, bitmask(GCSpause)); - g->gcstate = GCSpropagate; /* do not run 'markroot' */ + if (g->lastmajormem == 0) { /* signal for another major collection? */ + luaC_fullgc(L, 0); /* perform a full regular collection */ + g->lastmajormem = g->totalbytes; /* update control */ + } + else { + luaC_runtilstate(L, bitmask(GCSpause)); + g->gcstate = GCSpropagate; /* do not run 'markroot' */ + if (g->totalbytes > g->lastmajormem/100 * g->gcpause) + g->lastmajormem = 0; /* signal for a major collection */ + } g->GCthreshold = (g->totalbytes/100) * g->gcpause; -/*printf("count: %d old: %d new: %d dif: %d\n", c++, a, g->totalbytes, -g->totalbytes - prev);*/ +/*printf("count: %d old: %d new: %d dif: %d lim: %d threshold: %d\n", +c++, a, g->totalbytes, g->totalbytes - prev, g->lastmajormem, g->GCthreshold);*/ prev = g->totalbytes; } @@ -890,7 +898,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { if (!isemergency) /* do not run finalizers during emergency GC */ luaC_runtilstate(L, bitmask(GCSpause)); if (origkind == KGC_GEN) { /* generational mode? */ - g->gckind = GCSpause; /* collector must be always in... */ + g->gcstate = GCSpause; /* collector must be always in... */ luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ } g->GCthreshold = (g->totalbytes/100) * g->gcpause; diff --git a/lstate.c b/lstate.c index 02554c4d..b00b62a1 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.72 2010/03/24 13:07:01 roberto Exp roberto $ +** $Id: lstate.c,v 2.73 2010/03/25 13:06:36 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -254,6 +254,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->uvhead.u.l.prev = &g->uvhead; g->uvhead.u.l.next = &g->uvhead; g->GCthreshold = MAX_LUMEM; /* no GC while building state */ + g->lastmajormem = 0; g->strt.size = 0; g->strt.nuse = 0; g->strt.hash = NULL; diff --git a/lstate.h b/lstate.h index 45eccf8a..2377810a 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.55 2010/03/22 18:28:03 roberto Exp roberto $ +** $Id: lstate.h,v 2.56 2010/03/24 13:07:01 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -114,9 +114,14 @@ typedef struct CallInfo { ** `global state', shared by all threads of this state */ typedef struct global_State { - stringtable strt; /* hash table for strings */ lua_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to `frealloc' */ + lu_mem totalbytes; /* number of bytes currently allocated */ + lu_mem GCthreshold; /* when totalbytes > GCthreshold, run GC step */ + lu_mem lastmajormem; /* memory in use after last major collection */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + struct Table *l_gt; /* table of globals */ unsigned short nCcalls; /* number of nested C calls */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ @@ -131,16 +136,12 @@ typedef struct global_State { GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ GCObject *allweak; /* list of all-weak tables */ GCObject *tobefnz; /* list of userdata to be GC */ + UpVal uvhead; /* head of double-linked list of all open upvalues */ Mbuffer buff; /* temporary buffer for string concatenation */ - lu_mem GCthreshold; /* when totalbytes > GCthreshold, run GC step */ - lu_mem totalbytes; /* number of bytes currently allocated */ int gcpause; /* size of pause between successive GCs */ int gcstepmul; /* GC `granularity' */ lua_CFunction panic; /* to be called in unprotected errors */ - TValue l_registry; - struct Table *l_gt; /* table of globals */ struct lua_State *mainthread; - UpVal uvhead; /* head of double-linked list of all open upvalues */ const lua_Number *version; /* pointer to version number */ TString *envn; /* environment variable name */ TString *tmname[TM_N]; /* array with tag-method names */