summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-08-23 10:34:54 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-08-23 10:34:54 -0300
commit50955e27f592441a223c6267956e470f98eeb3c0 (patch)
tree4543b70e04d293c4eb09955d064f3446eb3e64a9
parent33c49f7fa03cf7e3bf7bb3aa697dc567d910c661 (diff)
downloadlua-github-50955e27f592441a223c6267956e470f98eeb3c0.tar.gz
C functions and strings now go to the local list; first version
of the local collector
-rw-r--r--lfunc.c5
-rw-r--r--lgc.c102
-rw-r--r--lgc.h3
-rw-r--r--lstate.c4
-rw-r--r--lstate.h4
-rw-r--r--lstring.c4
6 files changed, 107 insertions, 15 deletions
diff --git a/lfunc.c b/lfunc.c
index cb0b4ef6..d1185ec6 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 roberto Exp roberto $
+** $Id: lfunc.c,v 2.33 2013/08/16 18:55:49 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -21,7 +21,8 @@
Closure *luaF_newCclosure (lua_State *L, int n) {
- Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl;
+ Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n),
+ &G(L)->localgc, 0)->cl;
c->c.nupvalues = cast_byte(n);
return c;
}
diff --git a/lgc.c b/lgc.c
index fddc43cf..c261bd73 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.149 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lgc.c,v 2.150 2013/08/21 20:09:51 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -25,6 +25,12 @@
/*
+** How memory to allocate before a new local collection
+*/
+#define GCLOCALPAUSE 8000
+
+
+/*
** cost of sweeping one element (the size of a small object divided
** by some adjust for the sweep speed)
*/
@@ -191,9 +197,9 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
void luaC_fix (lua_State *L, GCObject *o) {
global_State *g = G(L);
- lua_assert(g->allgc == o);
+ lua_assert(g->localgc == o);
white2gray(o);
- g->allgc = o->gch.next; /* remove object from 'allgc' list */
+ g->localgc = o->gch.next; /* remove object from 'localgc' list */
o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */
g->fixedgc = o;
}
@@ -875,6 +881,72 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
/*
** {======================================================
+** Local Collection
+** =======================================================
+*/
+
+/*
+** Traverse a thread, local marking all its collectable objects
+*/
+static void localmarkthread (lua_State *l) {
+ StkId o = l->stack;
+ if (o == NULL)
+ return; /* stack not completely built yet */
+ for (; o < l->top; o++) { /* mark live elements in the stack */
+ if (iscollectable(o))
+ l_setbit(gcvalue(o)->gch.marked, LOCALBLACK);
+ }
+}
+
+
+/*
+** Mark all that is locally accessible (accessible directly from
+** a thread)
+*/
+static void localmark (global_State *g) {
+ GCObject *thread = hvalue(&g->l_registry)->next;
+ for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */
+ localmarkthread(gco2th(thread));
+ localmarkthread(g->mainthread);
+}
+
+
+static void localsweep (lua_State *L, global_State *g) {
+ GCObject **p = &g->localgc;
+ while (*p != NULL) {
+ GCObject *curr = *p;
+ if (!islocal(curr)) { /* is 'curr' no more local? */
+ *p = curr->gch.next; /* remove 'curr' from list */
+ curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */
+ g->allgc = curr;
+ }
+ else { /* still local */
+ if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */
+ resetbit(curr->gch.marked, LOCALBLACK);
+ p = &curr->gch.next; /* go to next element */
+ }
+ else { /* object is dead */
+ *p = curr->gch.next; /* remove 'curr' from list */
+ freeobj(L, curr); /* erase 'curr' */
+ }
+ }
+ }
+}
+
+
+static void luaC_localcollection (lua_State *L) {
+ global_State *g = G(L);
+ lua_assert(g->gcstate == GCSpause);
+ localmark(g);
+ localsweep(L, g);
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
** GC control
** =======================================================
*/
@@ -885,13 +957,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
** cycle will start when memory use hits threshold
*/
static void setpause (global_State *g, l_mem estimate) {
- l_mem debt, threshold;
+ l_mem threshold;
estimate = estimate / PAUSEADJ; /* adjust 'estimate' */
threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
? estimate * g->gcpause /* no overflow */
: MAX_LMEM; /* overflow; truncate to maximum */
- debt = -cast(l_mem, threshold - gettotalbytes(g));
- luaE_setdebt(g, debt);
+ g->GCthreshold = threshold;
+ luaE_setdebt(g, -GCLOCALPAUSE);
}
@@ -936,6 +1008,7 @@ void luaC_freeallobjects (lua_State *L) {
g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
g->gckind = KGC_NORMAL;
sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */
+ sweepwholelist(L, &g->localgc);
sweepwholelist(L, &g->allgc);
sweepwholelist(L, &g->fixedgc); /* collect fixed objects */
lua_assert(g->strt.nuse == 0);
@@ -1017,8 +1090,9 @@ static lu_mem singlestep (lua_State *L) {
return GCSWEEPMAX*GCSWEEPCOST;
}
else {
+ sweepwholelist(L, &g->localgc);
g->gcstate = GCSsweep;
- return 0;
+ return GCLOCALPAUSE / 4; /* some magic for now */
}
}
case GCSsweep: {
@@ -1090,7 +1164,19 @@ void luaC_forcestep (lua_State *L) {
*/
void luaC_step (lua_State *L) {
global_State *g = G(L);
- if (g->gcrunning) luaC_forcestep(L);
+ if (g->gcrunning) {
+ if (g->gcstate != GCSpause) {
+ luaC_forcestep(L);
+ }
+ else {
+ luaC_localcollection(L);
+ if (gettotalbytes(g) > g->GCthreshold) {
+ luaC_forcestep(L); /* restart collection */
+ }
+ else
+ luaE_setdebt(g, -GCLOCALPAUSE);
+ }
+ }
else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */
}
diff --git a/lgc.h b/lgc.h
index ccaaeab3..b931ae1a 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.h,v 2.64 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lgc.h,v 2.65 2013/08/21 20:09:51 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -77,6 +77,7 @@
#define BLACKBIT 2 /* object is black */
#define FINALIZEDBIT 3 /* object has been marked for finalization */
#define LOCALBIT 4 /* object is not local */
+#define LOCALBLACK 5 /* object is 'locally black' */
/* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
diff --git a/lstate.c b/lstate.c
index c8fc27c5..30fbc27c 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.c,v 2.103 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lstate.c,v 2.104 2013/08/21 20:09:51 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -280,6 +280,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->seed = makeseed(L);
g->gcrunning = 0; /* no GC while building state */
g->GCestimate = 0;
+ g->GCthreshold = 10000;
g->strt.size = g->strt.nuse = g->strt.empty = 0;
g->strt.hash = NULL;
setnilvalue(&g->l_registry);
@@ -288,6 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->version = lua_version(NULL);
g->gcstate = GCSpause;
g->allgc = NULL;
+ g->localgc = NULL;
g->finobj = NULL;
g->tobefnz = NULL;
g->fixedgc = NULL;
diff --git a/lstate.h b/lstate.h
index 2c89aad6..9c0434b9 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 2.87 2013/08/21 20:09:51 roberto Exp roberto $
+** $Id: lstate.h,v 2.88 2013/08/22 15:21:48 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -118,6 +118,7 @@ typedef struct global_State {
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCmemtrav; /* memory traversed by the GC */
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
+ lu_mem GCthreshold; /* threshold to start a new GC cycle */
stringtable strt; /* hash table for strings */
TValue l_registry;
unsigned int seed; /* randomized seed for hashes */
@@ -126,6 +127,7 @@ typedef struct global_State {
lu_byte gckind; /* kind of GC running */
lu_byte gcrunning; /* true if GC is running */
GCObject *allgc; /* list of all collectable objects */
+ GCObject *localgc; /* list of local objects */
GCObject *finobj; /* list of collectable objects with finalizers */
GCObject **sweepgc; /* current position of sweep in list 'allgc' */
GCObject **sweepfin; /* current position of sweep in list 'finobj' */
diff --git a/lstring.c b/lstring.c
index e53c6375..6d1ce978 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.29 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lstring.c,v 2.30 2013/08/22 15:21:48 roberto Exp roberto $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -106,7 +106,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
TString *ts;
size_t totalsize; /* total size of TString object */
totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
- ts = &luaC_newobj(L, tag, totalsize, NULL, 0)->ts;
+ ts = &luaC_newobj(L, tag, totalsize, &G(L)->localgc, 0)->ts;
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.extra = 0;