diff --git a/lgc.c b/lgc.c index f1d00e09..cdfd6496 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.133 2002/03/26 18:55:50 roberto Exp roberto $ +** $Id: lgc.c,v 1.134 2002/04/05 18:54:31 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -211,14 +211,13 @@ static void traversetable (GCState *st, Table *h) { int weakkey = 0; int weakvalue = 0; marktable(st, h->metatable); + lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); mode = fasttm(st->L, h->metatable, TM_WEAKMODE); - if (mode) { /* weak table? must be cleared after GC... */ - h->mark = st->toclear; /* put in the appropriate list */ - st->toclear = h; - if (ttype(mode) == LUA_TSTRING) { - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); - } + if (mode && ttype(mode) == LUA_TSTRING) { /* weak table? */ + h->mark = st->toclear; /* must be cleared after GC, ... */ + st->toclear = h; /* ...put in the appropriate list */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); } if (!weakvalue) { i = sizearray(h); diff --git a/lstate.c b/lstate.c index 9725bed5..5360d343 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.89 2002/04/16 17:08:28 roberto Exp roberto $ +** $Id: lstate.c,v 1.90 2002/04/22 14:40:23 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -69,6 +69,9 @@ static void f_luaopen (lua_State *L, void *ud) { G(L)->rootupval = NULL; G(L)->rootudata = NULL; G(L)->tmudata = NULL; + setnilvalue(key(G(L)->dummynode)); + setnilvalue(val(G(L)->dummynode)); + G(L)->dummynode->next = NULL; G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); stack_init(L, L); /* init stack */ /* create default meta table with a dummy table, and then close the loop */ diff --git a/lstate.h b/lstate.h index 6c2cfee9..84971213 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.82 2002/04/10 12:11:07 roberto Exp roberto $ +** $Id: lstate.h,v 1.83 2002/04/16 17:08:28 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -113,6 +113,7 @@ typedef struct global_State { lu_mem GCthreshold; lu_mem nblocks; /* number of `bytes' currently allocated */ lua_CFunction panic; /* to be called in unprotected errors */ + Node dummynode[1]; /* common node array for all empty tables */ TString *tmname[TM_N]; /* array with tag-method names */ } global_State; diff --git a/ltable.c b/ltable.c index 0403f3c2..7071ad0e 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 1.103 2002/04/05 18:54:31 roberto Exp roberto $ +** $Id: ltable.c,v 1.104 2002/04/22 14:40:23 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -52,13 +52,13 @@ #define hashnum(t,n) \ (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t)))) #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t)))) -#define hashboolean(t,p) (node(t, p)) /* `p' in [0,1] < minimum table size */ +#define hashboolean(t,p) (node(t, lmod(p, sizenode(t)))) /* ** for pointers, avoid modulus by power of 2, as they tend to have many ** 2 factors. */ -#define hashpointer(t,p) (node(t, (IntPoint(p) % (sizenode(t)-1)))) +#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1)))) /* @@ -200,12 +200,6 @@ static void numuse (const Table *t, int *narray, int *nhash) { } -/* -** (log2 of) minimum size for hash part of a table -*/ -#define MINHASHSIZE 1 - - static void setarrayvector (lua_State *L, Table *t, int size) { int i; luaM_reallocvector(L, t->array, t->sizearray, size, TObject); @@ -217,16 +211,22 @@ static void setarrayvector (lua_State *L, Table *t, int size) { static void setnodevector (lua_State *L, Table *t, int lsize) { int i; - int size; - if (lsize < MINHASHSIZE) lsize = MINHASHSIZE; - else if (lsize > MAXBITS) + int size = twoto(lsize); + if (lsize > MAXBITS) luaD_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i=0; inode[i].next = NULL; - setnilvalue(key(node(t, i))); - setnilvalue(val(node(t, i))); + if (lsize == 0) { /* no elements to hash part? */ + t->node = G(L)->dummynode; /* use common `dummynode' */ + lua_assert(ttype(key(t->node)) == LUA_TNIL); /* assert invariants: */ + lua_assert(ttype(val(t->node)) == LUA_TNIL); + lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */ + } + else { + t->node = luaM_newvector(L, size, Node); + for (i=0; inode[i].next = NULL; + setnilvalue(key(node(t, i))); + setnilvalue(val(node(t, i))); + } } t->lsizenode = cast(lu_byte, lsize); t->firstfree = node(t, size-1); /* first free position to be used */ @@ -235,14 +235,22 @@ static void setnodevector (lua_State *L, Table *t, int lsize) { static void resize (lua_State *L, Table *t, int nasize, int nhsize) { int i; - int oldasize, oldhsize; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; Node *nold; - oldasize = t->sizearray; + Node temp[1]; + if (oldhsize) + nold = t->node; /* save old hash ... */ + else { /* old hash is `dummynode' */ + lua_assert(t->node == G(L)->dummynode); + temp[0] = t->node[0]; /* copy it to `temp' (in case of errors) */ + nold = temp; + setnilvalue(key(G(L)->dummynode)); /* restate invariant */ + setnilvalue(val(G(L)->dummynode)); + } if (nasize > oldasize) /* should grow array part? */ setarrayvector(L, t, nasize); /* create new hash part with appropriate size */ - nold = t->node; /* save old hash ... */ - oldhsize = t->lsizenode; /* ... and (log of) old size */ setnodevector(L, t, nhsize); /* re-insert elements */ if (nasize < oldasize) { /* array part must shrink? */ @@ -262,7 +270,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { if (ttype(val(old)) != LUA_TNIL) luaH_set(L, t, key(old), val(old)); } - luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ + if (oldhsize) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ } @@ -299,8 +308,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) { void luaH_free (lua_State *L, Table *t) { - lua_assert(t->lsizenode > 0 || t->node == NULL); - if (t->lsizenode > 0) + if (t->lsizenode) luaM_freearray(L, t->node, sizenode(t), Node); luaM_freearray(L, t->array, t->sizearray, TObject); luaM_freelem(L, t);