From ab7d9bfd0c38f1dd8eda40ae3c1f1c686564a92d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 17 Nov 2003 17:50:05 -0200 Subject: [PATCH] cleaner code for manipulation of `marked' field --- lfunc.c | 4 ++-- lgc.c | 70 +++++++++++++++++++++++++------------------------------ lgc.h | 31 +++++++++++++++++++++++- lstring.c | 4 ++-- lstring.h | 6 ++--- 5 files changed, 69 insertions(+), 46 deletions(-) diff --git a/lfunc.c b/lfunc.c index 7117b783..a3cb42a1 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.68 2003/10/02 19:21:09 roberto Exp roberto $ +** $Id: lfunc.c,v 1.69 2003/10/20 17:42:41 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -64,7 +64,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { } v = luaM_new(L, UpVal); /* not found: create a new one */ v->tt = LUA_TUPVAL; - v->marked = 1; /* open upvalues should not be collected */ + v->marked = bitmask(BLACKBIT); /* open upvalues should not be collected */ v->v = level; /* current value lives in the stack */ v->next = *pp; /* chain it in the proper position */ *pp = valtogco(v); diff --git a/lgc.c b/lgc.c index 1ec12f1d..486e3fbc 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.176 2003/07/29 19:25:37 roberto Exp roberto $ +** $Id: lgc.c,v 1.177 2003/08/27 21:01:44 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -29,45 +29,38 @@ typedef struct GCState { } GCState; -/* -** some userful bit tricks -*/ -#define setbit(x,b) ((x) |= (1<<(b))) -#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b)))) -#define testbit(x,b) ((x) & (1<<(b))) -#define unmark(x) resetbit((x)->gch.marked, 0) -#define ismarked(x) ((x)->gch.marked & ((1<<4)|1)) +#define unblack(x) resetbit((x)->gch.marked, BLACKBIT) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define blacken(x) setbit((x)->gch.marked, BLACKBIT) -#define stringmark(s) setbit((s)->tsv.marked, 0) +#define stringmark(s) setbit((s)->tsv.marked, BLACKBIT) -#define isfinalized(u) (!testbit((u)->uv.marked, 1)) -#define markfinalized(u) resetbit((u)->uv.marked, 1) +#define isfinalized(u) testbit((u)->uv.marked, FINALIZEDBIT) +#define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) -#define KEYWEAKBIT 1 -#define VALUEWEAKBIT 2 -#define KEYWEAK (1<gch.marked, 0); /* mark object */ + lua_assert(!isblack(o)); + blacken(o); switch (o->gch.tt) { case LUA_TUSERDATA: { markvalue(st, gcotou(o)->uv.metatable); @@ -101,7 +94,7 @@ static void reallymarkobject (GCState *st, GCObject *o) { static void marktmu (GCState *st) { GCObject *u; for (u = st->g->tmudata; u; u = u->gch.next) { - unmark(u); /* may be marked, if left from previous GC */ + unblack(u); /* may be marked, if left from previous GC */ reallymarkobject(st, u); } } @@ -116,7 +109,7 @@ size_t luaC_separateudata (lua_State *L) { GCObject **lastcollected = &collected; while ((curr = *p) != NULL) { lua_assert(curr->gch.tt == LUA_TUSERDATA); - if (ismarked(curr) || isfinalized(gcotou(curr))) + if (isblack(curr) || isfinalized(gcotou(curr))) p = &curr->gch.next; /* don't bother with them */ else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { @@ -216,9 +209,9 @@ static void traverseclosure (GCState *st, Closure *cl) { markvalue(st, cl->l.p); for (i=0; il.nupvalues; i++) { /* mark its upvalues */ UpVal *u = cl->l.upvals[i]; - if (!u->marked) { + if (!isblack(valtogco(u))) { + blacken(valtogco(u)); markobject(st, &u->value); - u->marked = 1; } } } @@ -300,7 +293,7 @@ static int iscleared (const TObject *o, int iskey) { stringmark(tsvalue(o)); /* strings are `values', so are never weak */ return 0; } - return !ismarked(gcvalue(o)) || + return !isblack(gcvalue(o)) || (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); } @@ -319,8 +312,9 @@ static void cleartable (GCObject *l) { while (l) { Table *h = gcotoh(l); int i = h->sizearray; - lua_assert(h->marked & (KEYWEAK | VALUEWEAK)); - if (h->marked & VALUEWEAK) { + lua_assert(testbit(h->marked, VALUEWEAKBIT) || + testbit(h->marked, KEYWEAKBIT)); + if (testbit(h->marked, VALUEWEAKBIT)) { while (i--) { TObject *o = &h->array[i]; if (iscleared(o, 0)) /* value was collected? */ @@ -363,12 +357,12 @@ static void freeobj (lua_State *L, GCObject *o) { } -static int sweeplist (lua_State *L, GCObject **p, int limit) { +static int sweeplist (lua_State *L, GCObject **p, int mask) { GCObject *curr; int count = 0; /* number of collected items */ while ((curr = *p) != NULL) { - if (curr->gch.marked > limit) { - unmark(curr); + if (curr->gch.marked & mask) { + unblack(curr); p = &curr->gch.next; } else { @@ -381,10 +375,10 @@ static int sweeplist (lua_State *L, GCObject **p, int limit) { } -static void sweepstrings (lua_State *L, int all) { +static void sweepstrings (lua_State *L, int mask) { int i; for (i=0; istrt.size; i++) { /* for each list */ - G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all); + G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], mask); } } @@ -426,7 +420,7 @@ void luaC_callGCTM (lua_State *L) { udata->uv.next = G(L)->rootudata; /* return it to `root' list */ G(L)->rootudata = o; setuvalue(L->top - 1, udata); /* keep a reference to it */ - unmark(o); + unblack(o); do1gcTM(L, udata); } L->top--; @@ -435,10 +429,10 @@ void luaC_callGCTM (lua_State *L) { void luaC_sweep (lua_State *L, int all) { - if (all) all = 256; /* larger than any mark */ - sweeplist(L, &G(L)->rootudata, all); - sweepstrings(L, all); - sweeplist(L, &G(L)->rootgc, all); + int mask = (all) ? 0 : (bitmask(BLACKBIT) | bitmask(FIXEDBIT)); + sweeplist(L, &G(L)->rootudata, mask); + sweepstrings(L, mask); + sweeplist(L, &G(L)->rootgc, mask); } diff --git a/lgc.h b/lgc.h index 85f3b43e..29adec24 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 1.20 2003/07/16 20:49:02 roberto Exp roberto $ +** $Id: lgc.h,v 1.21 2003/07/29 19:25:37 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -11,6 +11,35 @@ #include "lobject.h" +/* + * ** some userful bit tricks + * */ +#define bitmask(b) (1<<(b)) +#define setbit(x,b) ((x) |= bitmask(b)) +#define resetbit(x,b) ((x) &= cast(lu_byte, ~bitmask(b))) +#define testbit(x,b) ((x) & bitmask(b)) + + + +/* +** Layout for bit use in `marked' field: +** bit 0 - object is white (not used yet) +** bit 1 - object is black +** bit 2 - For userdata: is finalized; + for tables: has weak keys +** bit 3 - for tables: has weak values +** bit 4 - for strings: is fixed (should not be collected) +*/ + +#define WHITEBIT 0 +#define BLACKBIT 1 +#define FINALIZEDBIT 2 +#define KEYWEAKBIT 2 +#define VALUEWEAKBIT 3 +#define FIXEDBIT 4 + + + #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ luaC_collectgarbage(L); } diff --git a/lstring.c b/lstring.c index f1d7d232..1b0a0050 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 1.78 2002/12/04 17:38:31 roberto Exp roberto $ +** $Id: lstring.c,v 1.79 2003/04/28 19:26:16 roberto Exp roberto $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -91,7 +91,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { Udata *luaS_newudata (lua_State *L, size_t s) { Udata *u; u = cast(Udata *, luaM_malloc(L, sizeudata(s))); - u->uv.marked = (1<<1); /* is not finalized */ + u->uv.marked = 0; /* is not finalized */ u->uv.tt = LUA_TUSERDATA; u->uv.len = s; u->uv.metatable = hvalue(defaultmeta(L)); diff --git a/lstring.h b/lstring.h index 13a12a5a..1fae1a58 100644 --- a/lstring.h +++ b/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.36 2002/04/30 13:01:48 roberto Exp roberto $ +** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp roberto $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -8,11 +8,11 @@ #define lstring_h +#include "lgc.h" #include "lobject.h" #include "lstate.h" - #define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ (cast(lu_mem, l)+1)*sizeof(char)) @@ -22,7 +22,7 @@ #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) ((s)->tsv.marked |= (1<<4)) +#define luaS_fix(s) setbit((s)->tsv.marked, FIXEDBIT) void luaS_resize (lua_State *L, int newsize); Udata *luaS_newudata (lua_State *L, size_t s);