diff --git a/src/lapi.c b/src/lapi.c index d87b090..df0ca5b 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -599,13 +599,11 @@ LUA_API const char *lua_pushsubstring (lua_State *L, int idx, size_t start, size } if (ss != NULL) break; if (nextsscluster(cluster) == NULL) { /* need new cluster? */ - olddebt = g->GCdebt; next = luaM_newvector(L, SUBSTR_CLUSTER_SIZE, TString); - g->GCdebt = olddebt; memset(next, 0, SUBSTR_CLUSTER_SIZE * sizeof(TString)); nextsscluster(cluster) = next; /* chain next cluster in list */ nextsscluster(next) = NULL; /* ensure next pointer is NULL */ - clusterid(next) = clusterid(cluster) + 1; /* set cluster number */ + rawclusterid(next) = (clusterid(cluster) + 1) | (g->currentwhite & bitmask(WHITE0BIT) ? 0 : ~CLUSTERID_MASK); /* set cluster number */ ((bitmap_unit*)next)[BITMAP_SKIP] = 0xFFFF; /* always mark first entry as used by bitmap */ nextsscluster(cluster) = next; } diff --git a/src/lgc.c b/src/lgc.c index 1e81493..4b0592d 100644 --- a/src/lgc.c +++ b/src/lgc.c @@ -525,26 +525,27 @@ static lu_mem traversestack (global_State *g, lua_State *th) { static int traverserope (global_State *g, TString *r) { - int size = sizeof(TString); - if (r->tsr.left) { + if (r->tsr.left) markobject(g, r->tsr.left); - //size += sizeof(TString); - } - if (r->tsr.right) { + if (r->tsr.right) markobject(g, r->tsr.right); - //size += sizeof(TString); - } - if (r->tsr.res) { + if (r->tsr.res) markobject(g, r->tsr.res); - //size += sizeof(TString); + if ((rawclusterid(r->tsr.cluster) & ~CLUSTERID_MASK ? 1 : 0) != (g->currentwhite & bitmask(WHITE0BIT) ? 1 : 0)) { + rawclusterid(r->tsr.cluster) = clusterid(r->tsr.cluster) | (g->currentwhite & bitmask(WHITE0BIT) ? ~CLUSTERID_MASK : 0); + return sizeof(TString); } - return size; + return 0; } static int traversesubstr (global_State *g, TString *ss) { markobject(g, ss->tss.str); - return sizeof(TString); + if ((rawclusterid(ss->tss.cluster) & ~CLUSTERID_MASK ? 1 : 0) != (g->currentwhite & bitmask(WHITE0BIT) ? 1 : 0)) { + rawclusterid(ss->tss.cluster) = clusterid(ss->tss.cluster) | (g->currentwhite & bitmask(WHITE0BIT) ? ~CLUSTERID_MASK : 0); + return sizeof(TString); + } + return 0; } @@ -1089,8 +1090,12 @@ static lu_mem singlestep (lua_State *L) { global_State *g = G(L); switch (g->gcstate) { case GCSpause: { + TString* cluster; /* start to count memory traversed */ - g->GCmemtrav = g->strt.size * sizeof(GCObject*); + g->GCmemtrav = g->strt.size * sizeof(GCObject*) + + g->ropestacksize * sizeof(TString*) + + ROPE_CLUSTER_SIZE * sizeof(TString) + + SUBSTR_CLUSTER_SIZE * sizeof(TString); /* "static" blocks */ lua_assert(!isgenerational(g)); restartcollection(g); g->gcstate = GCSpropagate; diff --git a/src/lstate.c b/src/lstate.c index ccf9edb..1258faf 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -200,7 +200,6 @@ static void f_luaopen (lua_State *L, void *ud) { g->memerrmsg = luaS_newliteral(L, MEMERRMSG); luaS_fix(g->memerrmsg); /* it should never be collected */ /* allocate rope and substring clusters */ - olddebt = g->GCdebt; /* don't count debt of these, they are never found by GC */ g->ropestack = luaM_newvector(L, g->ropestacksize, TString *); g->ropeclusters = luaM_newvector(L, ROPE_CLUSTER_SIZE, TString); memset(g->ropeclusters, 0, ROPE_CLUSTER_SIZE * sizeof(TString)); @@ -213,9 +212,6 @@ static void f_luaopen (lua_State *L, void *ud) { ((unsigned long*)g->ssclusters)[BITMAP_SKIP] = 0xFFFF; /* always mark first entry as used by bitmap */ g->ssfreecluster = g->ssclusters; memset(g->allowedcfuncs, 0, sizeof(g->allowedcfuncs)); /* set all funclists to NULL */ - /* mark new allocations as compensated & reset debt */ - //g->totalbytes += g->GCdebt - olddebt; - g->GCdebt = olddebt; g->gcrunning = 1; /* allow gc */ g->version = lua_version(NULL); luai_userstateopen(L); @@ -257,19 +253,17 @@ 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); - olddebt = g->GCdebt; luaM_freearray(L, g->ropestack, g->ropestacksize); while (cluster != NULL) { next = *(TString**)cluster; - luaM_free(L, cluster); + luaM_freemem(L, cluster, ROPE_CLUSTER_SIZE * sizeof(TString)); cluster = next; } while (sscluster != NULL) { ssnext = *(TString**)sscluster; - luaM_free(L, sscluster); + luaM_freemem(L, sscluster, SUBSTR_CLUSTER_SIZE * sizeof(TString)); sscluster = ssnext; } - g->GCdebt = olddebt; //lua_assert(gettotalbytes(g) == sizeof(LG)); if (g->lockstate) lua_unlock(L); _lua_freelock(g->lock); diff --git a/src/lstring.c b/src/lstring.c index cf4df22..d124e79 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -209,13 +209,11 @@ TString *luaS_concat (lua_State *L, TString *l, TString *r) { } if (rope != NULL) break; if (nextropecluster(cluster) == NULL) { /* need new cluster? */ - olddebt = g->GCdebt; next = luaM_newvector(L, ROPE_CLUSTER_SIZE, TString); - g->GCdebt = olddebt; memset(next, 0, ROPE_CLUSTER_SIZE * sizeof(TString)); nextropecluster(cluster) = next; /* chain next cluster in list */ nextropecluster(next) = NULL; /* ensure next pointer is NULL */ - clusterid(next) = clusterid(cluster) + 1; /* set cluster number */ + rawclusterid(next) = (clusterid(cluster) + 1) | (g->currentwhite & bitmask(WHITE0BIT) ? 0 : ~CLUSTERID_MASK); /* set cluster number */ ((bitmap_unit*)next)[BITMAP_SKIP] = 0xFFFF; /* always mark first entry as used by bitmap */ nextropecluster(cluster) = next; } @@ -239,20 +237,21 @@ TString *luaS_build (lua_State *L, TString *rope) { TString *s; TString **stack; TString *orig = rope; - l_mem olddebt; + int freemem = 0; + void* alloc_ud; if (rope->tsr.tt == LUA_TSHRSTR || rope->tsr.tt == LUA_TLNGSTR || rope->tsr.tt == LUA_TSUBSTR) return cast(TString *, rope); if (rope->tsr.res || rope->tsr.left == NULL || rope->tsr.right == NULL) return rope->tsr.res; - if (rope->tsr.len >= ROPE_ALLOC_MIN_SIZE) buffer = cur = luaM_newvector(L, rope->tsr.len, char); - else buffer = cur = luaZ_openspace(L, &G(L)->buff, rope->tsr.len); + if (rope->tsr.len >= ROPE_ALLOC_MIN_SIZE) { + buffer = cur = G(L)->frealloc(G(L)->ud, NULL, 0, rope->tsr.len * sizeof(char)); + freemem = 1; + } else buffer = cur = luaZ_openspace(L, &G(L)->buff, rope->tsr.len); stack = G(L)->ropestack; do { int b = 0; while (rope->tsr.left->tsr.tt == LUA_TROPSTR && rope->tsr.left->tsr.res == NULL) { if (stack - G(L)->ropestack == G(L)->ropestacksize - 1) { TString **oldbase = G(L)->ropestack; - olddebt = G(L)->GCdebt; luaM_reallocvector(L, G(L)->ropestack, G(L)->ropestacksize, G(L)->ropestacksize + G(L)->ropestacksize, TString *); - G(L)->GCdebt = olddebt; stack = G(L)->ropestack + (stack - oldbase); G(L)->ropestacksize += G(L)->ropestacksize; } @@ -287,7 +286,9 @@ TString *luaS_build (lua_State *L, TString *rope) { rope = rope->tsr.right; } while (stack >= G(L)->ropestack); s = luaS_newlstr(L, buffer, cur - buffer); - if (orig->tsr.len >= ROPE_ALLOC_MIN_SIZE) luaM_free(L, buffer); + if (freemem) { + G(L)->frealloc(G(L)->ud, buffer, orig->tsr.len * sizeof(char), 0); + } orig->tsr.res = s; orig->tsr.left = orig->tsr.right = NULL; /* release left & right nodes (we don't need them anymore) */ /* mark the string as black so it doesn't accidentally get freed */ @@ -318,7 +319,6 @@ static void freeropeclusters (lua_State *L) { TString *cluster, *last = NULL; bitmap_unit *bitmap; int i, empty, full, kept = 1, setfree = 0; - l_mem olddebt; for (cluster = G(L)->ropeclusters; cluster != NULL; last = cluster, cluster = nextropecluster(cluster)) { bitmap = (bitmap_unit*)cluster + BITMAP_SKIP; empty = (bitmap[0] & ~(bitmap_unit)(0xFFFF)) == 0; /* ignore first entry use bit */ @@ -334,14 +334,14 @@ static void freeropeclusters (lua_State *L) { if (empty) { /* entire cluster unused? */ if (kept) { kept--; /* leave one empty cluster allocated */ + setfree = 1; + G(L)->ropefreecluster = cluster; } else { /* unlink and free cluster */ nextropecluster(last) = nextropecluster(cluster); if (G(L)->ropefreecluster == cluster) G(L)->ropefreecluster = nextropecluster(cluster); - olddebt = G(L)->GCdebt; - luaM_free(L, cluster); - G(L)->GCdebt = olddebt; + luaM_freemem(L, cluster, ROPE_CLUSTER_SIZE * sizeof(TString)); cluster = last; } } else if (full && !setfree) { @@ -355,7 +355,6 @@ static void freessclusters (lua_State *L) { TString *cluster, *last = NULL; bitmap_unit *bitmap; int i, empty, full, kept = 1, setfree = 0; - l_mem olddebt; for (cluster = G(L)->ssclusters; cluster != NULL; last = cluster, cluster = nextsscluster(cluster)) { bitmap = (bitmap_unit*)cluster + BITMAP_SKIP; empty = (bitmap[0] & ~(bitmap_unit)(0xFFFF)) == 0; /* ignore first entry use bit */ @@ -371,14 +370,14 @@ static void freessclusters (lua_State *L) { if (empty) { /* entire cluster unused? */ if (kept) { kept--; /* leave one empty cluster allocated */ + setfree = 1; + G(L)->ssfreecluster = cluster; } else { /* unlink and free cluster */ nextsscluster(last) = nextsscluster(cluster); if (G(L)->ssfreecluster == cluster) G(L)->ssfreecluster = nextsscluster(cluster); - olddebt = G(L)->GCdebt; - luaM_free(L, cluster); - G(L)->GCdebt = olddebt; + luaM_freemem(L, cluster, SUBSTR_CLUSTER_SIZE * sizeof(TString)); cluster = last; } } else if (full && !setfree) { diff --git a/src/lstring.h b/src/lstring.h index 9c2deea..37fa11c 100644 --- a/src/lstring.h +++ b/src/lstring.h @@ -16,12 +16,14 @@ #define SUBSTR_CLUSTER_SIZE ((sizeof(TString) * 16 - sizeof(void*) * 2) * 8) #define BITMAP_UNIT_SIZE (sizeof(bitmap_unit) * 8) #define BITMAP_SKIP (sizeof(void*) / sizeof(bitmap_unit) * 2) +#define CLUSTERID_MASK LONG_MAX #define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) #define sizeudata(u) (sizeof(union Udata)+(u)->len) -#define clusterid(l) (*(bitmap_unit*)((void**)(l) + 1)) +#define clusterid(l) (*(bitmap_unit*)((void**)(l) + 1) & CLUSTERID_MASK) +#define rawclusterid(l) (*(bitmap_unit*)((void**)(l) + 1)) #define nextropecluster(l) (*(TString**)(l)) #define nextsscluster(l) (*(TString**)(l))