cleaning the stage for generational collection

This commit is contained in:
Roberto Ierusalimschy 2002-08-16 11:45:55 -03:00
parent 0039feb9da
commit da19c436cc
7 changed files with 54 additions and 55 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lfunc.c,v 1.56 2002/05/02 13:06:20 roberto Exp roberto $ ** $Id: lfunc.c,v 1.57 2002/06/20 20:41:46 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures ** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -54,6 +54,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
pp = &p->next; pp = &p->next;
} }
p = luaM_new(L, UpVal); /* not found: create a new one */ p = luaM_new(L, UpVal); /* not found: create a new one */
p->marked = 1; /* open upvalues should not be collected */
p->v = level; /* current value lives in the stack */ p->v = level; /* current value lives in the stack */
p->next = *pp; /* chain it in the proper position */ p->next = *pp; /* chain it in the proper position */
*pp = p; *pp = p;
@ -64,6 +65,8 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
void luaF_close (lua_State *L, StkId level) { void luaF_close (lua_State *L, StkId level) {
UpVal *p; UpVal *p;
while ((p = L->openupval) != NULL && p->v >= level) { while ((p = L->openupval) != NULL && p->v >= level) {
lua_assert(p->marked);
p->marked = 0;
setobj(&p->value, p->v); /* save current value */ setobj(&p->value, p->v); /* save current value */
p->v = &p->value; /* now current value lives here */ p->v = &p->value; /* now current value lives here */
L->openupval = p->next; /* remove from `open' list */ L->openupval = p->next; /* remove from `open' list */

62
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $ ** $Id: lgc.c,v 1.145 2002/08/06 17:06:56 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -27,27 +27,26 @@ typedef struct GCState {
} GCState; } GCState;
/* mark a string; marks larger than 1 cannot be changed */ /*
#define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} ** 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)))
/* unmarked tables are represented by pointing `mark' to themselves */ #define strmark(s) setbit((s)->tsv.marked, 0)
#define ismarked(x) ((x)->mark != (x)) #define strunmark(s) resetbit((s)->tsv.marked, 0)
/* mark tricks for userdata */ /* mark tricks for userdata */
#define isudmarked(u) (u->uv.len & 1) #define isudmarked(u) testbit(u->uv.marked, 0)
#define markud(u) (u->uv.len |= 1) #define markud(u) setbit(u->uv.marked, 0)
#define unmarkud(u) (u->uv.len &= (~(size_t)1)) #define unmarkud(u) resetbit(u->uv.marked, 0)
#define isfinalized(u) (u->uv.len & 2)
#define markfinalized(u) (u->uv.len |= 2)
/* mark tricks for upvalues (assume that open upvalues are always marked) */
#define isupvalmarked(uv) ((uv)->v != &(uv)->value)
#define isfinalized(u) testbit(u->uv.marked, 1)
#define markfinalized(u) setbit(u->uv.marked, 1)
#define ismarkable(o) (!((1 << ttype(o)) & \ #define ismarkable(o) (!((1 << ttype(o)) & \
@ -78,8 +77,9 @@ static void protomark (Proto *f) {
static void marktable (GCState *st, Table *h) { static void marktable (GCState *st, Table *h) {
if (!ismarked(h)) { if (!h->marked) {
h->mark = st->tmark; /* chain it for later traversal */ h->marked = 1;
h->gclist = st->tmark; /* chain it for later traversal */
st->tmark = h; st->tmark = h;
} }
} }
@ -100,9 +100,9 @@ static void markclosure (GCState *st, Closure *cl) {
protomark(cl->l.p); protomark(cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
UpVal *u = cl->l.upvals[i]; UpVal *u = cl->l.upvals[i];
if (!isupvalmarked(u)) { if (!u->marked) {
markobject(st, &u->value); markobject(st, &u->value);
u->v = NULL; /* mark it! */ u->marked = 1;
} }
} }
} }
@ -222,7 +222,7 @@ static void traversetable (GCState *st, Table *h) {
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */ if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
weakkey = h->mode & WEAKKEY; weakkey = h->mode & WEAKKEY;
weakvalue = h->mode & WEAKVALUE; weakvalue = h->mode & WEAKVALUE;
h->mark = st->toclear; /* must be cleared after GC, ... */ h->gclist = st->toclear; /* must be cleared after GC, ... */
st->toclear = h; /* ... so put in the appropriate list */ st->toclear = h; /* ... so put in the appropriate list */
} }
if (!weakvalue) { if (!weakvalue) {
@ -245,7 +245,7 @@ static void traversetable (GCState *st, Table *h) {
static void propagatemarks (GCState *st) { static void propagatemarks (GCState *st) {
while (st->tmark) { /* traverse marked tables */ while (st->tmark) { /* traverse marked tables */
Table *h = st->tmark; /* get first table from list */ Table *h = st->tmark; /* get first table from list */
st->tmark = h->mark; /* remove it from list */ st->tmark = h->gclist; /* remove it from list */
traversetable(st, h); traversetable(st, h);
} }
} }
@ -256,7 +256,7 @@ static int hasmark (const TObject *o) {
case LUA_TUSERDATA: case LUA_TUSERDATA:
return isudmarked(uvalue(o)); return isudmarked(uvalue(o));
case LUA_TTABLE: case LUA_TTABLE:
return ismarked(hvalue(o)); return hvalue(o)->marked;
case LUA_TFUNCTION: case LUA_TFUNCTION:
return clvalue(o)->c.marked; return clvalue(o)->c.marked;
case LUA_TSTRING: case LUA_TSTRING:
@ -273,7 +273,7 @@ static int hasmark (const TObject *o) {
*/ */
static void cleartablekeys (GCState *st) { static void cleartablekeys (GCState *st) {
Table *h; Table *h;
for (h = st->toclear; h; h = h->mark) { for (h = st->toclear; h; h = h->gclist) {
lua_assert(h->mode & (WEAKKEY | WEAKVALUE)); lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
if ((h->mode & WEAKKEY)) { /* table may have collected keys? */ if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
int i = sizenode(h); int i = sizenode(h);
@ -292,7 +292,7 @@ static void cleartablekeys (GCState *st) {
*/ */
static void cleartablevalues (GCState *st) { static void cleartablevalues (GCState *st) {
Table *h; Table *h;
for (h = st->toclear; h; h = h->mark) { for (h = st->toclear; h; h = h->gclist) {
if ((h->mode & WEAKVALUE)) { /* table may have collected values? */ if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
int i = sizearray(h); int i = sizearray(h);
while (i--) { while (i--) {
@ -347,9 +347,8 @@ static void collectupval (lua_State *L) {
UpVal **v = &G(L)->rootupval; UpVal **v = &G(L)->rootupval;
UpVal *curr; UpVal *curr;
while ((curr = *v) != NULL) { while ((curr = *v) != NULL) {
if (isupvalmarked(curr)) { if (curr->marked) {
lua_assert(curr->v == NULL); curr->marked = 0; /* unmark */
curr->v = &curr->value; /* unmark */
v = &curr->next; /* next */ v = &curr->next; /* next */
} }
else { else {
@ -364,8 +363,8 @@ static void collecttable (lua_State *L) {
Table **p = &G(L)->roottable; Table **p = &G(L)->roottable;
Table *curr; Table *curr;
while ((curr = *p) != NULL) { while ((curr = *p) != NULL) {
if (ismarked(curr)) { if (curr->marked) {
curr->mark = curr; /* unmark */ curr->marked = 0;
p = &curr->next; p = &curr->next;
} }
else { else {
@ -387,7 +386,7 @@ static void collectudata (lua_State *L) {
} }
else { else {
*p = curr->uv.next; *p = curr->uv.next;
luaM_free(L, curr, sizeudata(curr->uv.len & (~(size_t)3))); luaM_free(L, curr, sizeudata(curr->uv.len));
} }
} }
} }
@ -400,8 +399,7 @@ static void collectstrings (lua_State *L, int all) {
TString *curr; TString *curr;
while ((curr = *p) != NULL) { while ((curr = *p) != NULL) {
if (curr->tsv.marked && !all) { /* preserve? */ if (curr->tsv.marked && !all) { /* preserve? */
if (curr->tsv.marked < FIXMARK) /* does not change FIXMARKs */ strunmark(curr);
curr->tsv.marked = 0;
p = &curr->tsv.nexthash; p = &curr->tsv.nexthash;
} }
else { /* collect */ else { /* collect */

9
llex.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.c,v 1.107 2002/07/08 18:14:36 roberto Exp roberto $ ** $Id: llex.c,v 1.108 2002/07/10 20:43:53 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -39,8 +39,9 @@ void luaX_init (lua_State *L) {
int i; int i;
for (i=0; i<NUM_RESERVED; i++) { for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, token2string[i]); TString *ts = luaS_new(L, token2string[i]);
luaS_fix(ts); /* reserved words are never collected */
lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN); lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
ts->tsv.marked = cast(unsigned short, RESERVEDMARK+i); /* reserved word */ ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */
} }
} }
@ -388,8 +389,8 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
/* identifier or reserved word */ /* identifier or reserved word */
size_t l = readname(LS); size_t l = readname(LS);
TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l); TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
if (ts->tsv.marked >= RESERVEDMARK) /* reserved word? */ if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.marked-RESERVEDMARK+FIRST_RESERVED; return ts->tsv.reserved - 1 + FIRST_RESERVED;
seminfo->ts = ts; seminfo->ts = ts;
return TK_NAME; return TK_NAME;
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $ ** $Id: lobject.h,v 1.142 2002/08/06 17:06:56 roberto Exp roberto $
** Type definitions for Lua objects ** Type definitions for Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -101,8 +101,9 @@ typedef union TString {
struct { struct {
lu_hash hash; lu_hash hash;
size_t len; size_t len;
int marked;
union TString *nexthash; /* chain for hash table */ union TString *nexthash; /* chain for hash table */
lu_byte marked;
lu_byte reserved;
} tsv; } tsv;
} TString; } TString;
@ -117,7 +118,8 @@ typedef union Udata {
struct { struct {
struct Table *metatable; struct Table *metatable;
union Udata *next; /* chain for list of all udata */ union Udata *next; /* chain for list of all udata */
size_t len; /* least 2 bits reserved for gc mark */ size_t len;
lu_byte marked;
} uv; } uv;
} Udata; } Udata;
@ -164,6 +166,7 @@ typedef struct UpVal {
TObject *v; /* points to stack or to its own value */ TObject *v; /* points to stack or to its own value */
struct UpVal *next; struct UpVal *next;
TObject value; /* the value (when closed) */ TObject value; /* the value (when closed) */
lu_byte marked;
} UpVal; } UpVal;
@ -219,11 +222,12 @@ typedef struct Table {
Node *node; Node *node;
Node *firstfree; /* this position is free; all positions after it are full */ Node *firstfree; /* this position is free; all positions after it are full */
struct Table *next; struct Table *next;
struct Table *mark; /* marked tables (point to itself when not marked) */ struct Table *gclist;
int sizearray; /* size of `array' array */ int sizearray; /* size of `array' array */
lu_byte flags; /* 1<<p means tagmethod(p) is not present */ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte lsizenode; /* log2 of size of `node' array */
lu_byte mode; lu_byte mode;
lu_byte marked;
} Table; } Table;
/* bit masks for `mode' */ /* bit masks for `mode' */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.c,v 1.73 2002/03/20 18:37:13 roberto Exp roberto $ ** $Id: lstring.c,v 1.74 2002/04/05 18:54:31 roberto Exp roberto $
** String table (keeps all strings handled by Lua) ** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -53,6 +53,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
ts->tsv.len = l; ts->tsv.len = l;
ts->tsv.hash = h; ts->tsv.hash = h;
ts->tsv.marked = 0; ts->tsv.marked = 0;
ts->tsv.reserved = 0;
memcpy(ts+1, str, l*sizeof(char)); memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
tb = &G(L)->strt; tb = &G(L)->strt;
@ -85,8 +86,8 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
Udata *luaS_newudata (lua_State *L, size_t s) { Udata *luaS_newudata (lua_State *L, size_t s) {
Udata *u; Udata *u;
s = (s+3) & (~(size_t)3); /* make sure size is multiple of 4 */
u = cast(Udata *, luaM_malloc(L, sizeudata(s))); u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
u->uv.marked = 0;
u->uv.len = s; u->uv.len = s;
u->uv.metatable = hvalue(defaultmeta(L)); u->uv.metatable = hvalue(defaultmeta(L));
/* chain it on udata list */ /* chain it on udata list */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.h,v 1.35 2001/11/28 20:13:13 roberto Exp roberto $ ** $Id: lstring.h,v 1.36 2002/04/30 13:01:48 roberto Exp roberto $
** String table (keep all strings handled by Lua) ** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,14 +13,6 @@
/*
** any TString with mark>=FIXMARK is never collected.
** Marks>=RESERVEDMARK are used to identify reserved words.
*/
#define FIXMARK 2
#define RESERVEDMARK 3
#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ #define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \
(cast(lu_mem, l)+1)*sizeof(char)) (cast(lu_mem, l)+1)*sizeof(char))
@ -30,7 +22,7 @@
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1)) (sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) ((s)->tsv.marked = FIXMARK) #define luaS_fix(s) ((s)->tsv.marked |= (1<<4))
void luaS_resize (lua_State *L, int newsize); void luaS_resize (lua_State *L, int newsize);
Udata *luaS_newudata (lua_State *L, size_t s); Udata *luaS_newudata (lua_State *L, size_t s);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $ ** $Id: ltable.c,v 1.116 2002/08/06 17:06:56 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -307,8 +307,8 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
t->metatable = hvalue(defaultmeta(L)); t->metatable = hvalue(defaultmeta(L));
t->next = G(L)->roottable; t->next = G(L)->roottable;
G(L)->roottable = t; G(L)->roottable = t;
t->mark = t;
t->flags = cast(lu_byte, ~0); t->flags = cast(lu_byte, ~0);
t->marked = 0;
t->mode = 0; t->mode = 0;
/* temporary values (kept only if some malloc fails) */ /* temporary values (kept only if some malloc fails) */
t->array = NULL; t->array = NULL;