summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-23 12:04:39 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-23 12:04:39 -0300
commit383e8b9e778d2bed9dc4347f441803e2c4f99d09 (patch)
tree6035d4b69801d535f3042120e549e457fb154068
parentf1a1bb23fe29264ec0cf81a8bbfa8f30b0a5b76d (diff)
downloadlua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.gz
lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.bz2
lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.zip
use of a common `dummynode' for all empty tables
-rw-r--r--lgc.c15
-rw-r--r--lstate.c5
-rw-r--r--lstate.h3
-rw-r--r--ltable.c58
4 files changed, 46 insertions, 35 deletions
diff --git a/lgc.c b/lgc.c
index f1d00e09..cdfd6496 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.133 2002/03/26 18:55:50 roberto Exp roberto $ 2** $Id: lgc.c,v 1.134 2002/04/05 18:54:31 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -211,14 +211,13 @@ static void traversetable (GCState *st, Table *h) {
211 int weakkey = 0; 211 int weakkey = 0;
212 int weakvalue = 0; 212 int weakvalue = 0;
213 marktable(st, h->metatable); 213 marktable(st, h->metatable);
214 lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
214 mode = fasttm(st->L, h->metatable, TM_WEAKMODE); 215 mode = fasttm(st->L, h->metatable, TM_WEAKMODE);
215 if (mode) { /* weak table? must be cleared after GC... */ 216 if (mode && ttype(mode) == LUA_TSTRING) { /* weak table? */
216 h->mark = st->toclear; /* put in the appropriate list */ 217 h->mark = st->toclear; /* must be cleared after GC, ... */
217 st->toclear = h; 218 st->toclear = h; /* ...put in the appropriate list */
218 if (ttype(mode) == LUA_TSTRING) { 219 weakkey = (strchr(svalue(mode), 'k') != NULL);
219 weakkey = (strchr(svalue(mode), 'k') != NULL); 220 weakvalue = (strchr(svalue(mode), 'v') != NULL);
220 weakvalue = (strchr(svalue(mode), 'v') != NULL);
221 }
222 } 221 }
223 if (!weakvalue) { 222 if (!weakvalue) {
224 i = sizearray(h); 223 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 @@
1/* 1/*
2** $Id: lstate.c,v 1.89 2002/04/16 17:08:28 roberto Exp roberto $ 2** $Id: lstate.c,v 1.90 2002/04/22 14:40:23 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -69,6 +69,9 @@ static void f_luaopen (lua_State *L, void *ud) {
69 G(L)->rootupval = NULL; 69 G(L)->rootupval = NULL;
70 G(L)->rootudata = NULL; 70 G(L)->rootudata = NULL;
71 G(L)->tmudata = NULL; 71 G(L)->tmudata = NULL;
72 setnilvalue(key(G(L)->dummynode));
73 setnilvalue(val(G(L)->dummynode));
74 G(L)->dummynode->next = NULL;
72 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); 75 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
73 stack_init(L, L); /* init stack */ 76 stack_init(L, L); /* init stack */
74 /* create default meta table with a dummy table, and then close the loop */ 77 /* 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 @@
1/* 1/*
2** $Id: lstate.h,v 1.82 2002/04/10 12:11:07 roberto Exp roberto $ 2** $Id: lstate.h,v 1.83 2002/04/16 17:08:28 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -113,6 +113,7 @@ typedef struct global_State {
113 lu_mem GCthreshold; 113 lu_mem GCthreshold;
114 lu_mem nblocks; /* number of `bytes' currently allocated */ 114 lu_mem nblocks; /* number of `bytes' currently allocated */
115 lua_CFunction panic; /* to be called in unprotected errors */ 115 lua_CFunction panic; /* to be called in unprotected errors */
116 Node dummynode[1]; /* common node array for all empty tables */
116 TString *tmname[TM_N]; /* array with tag-method names */ 117 TString *tmname[TM_N]; /* array with tag-method names */
117} global_State; 118} global_State;
118 119
diff --git a/ltable.c b/ltable.c
index 0403f3c2..7071ad0e 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.103 2002/04/05 18:54:31 roberto Exp roberto $ 2** $Id: ltable.c,v 1.104 2002/04/22 14:40:23 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -52,13 +52,13 @@
52#define hashnum(t,n) \ 52#define hashnum(t,n) \
53 (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t)))) 53 (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
54#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t)))) 54#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t))))
55#define hashboolean(t,p) (node(t, p)) /* `p' in [0,1] < minimum table size */ 55#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
56 56
57/* 57/*
58** for pointers, avoid modulus by power of 2, as they tend to have many 58** for pointers, avoid modulus by power of 2, as they tend to have many
59** 2 factors. 59** 2 factors.
60*/ 60*/
61#define hashpointer(t,p) (node(t, (IntPoint(p) % (sizenode(t)-1)))) 61#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
62 62
63 63
64/* 64/*
@@ -200,12 +200,6 @@ static void numuse (const Table *t, int *narray, int *nhash) {
200} 200}
201 201
202 202
203/*
204** (log2 of) minimum size for hash part of a table
205*/
206#define MINHASHSIZE 1
207
208
209static void setarrayvector (lua_State *L, Table *t, int size) { 203static void setarrayvector (lua_State *L, Table *t, int size) {
210 int i; 204 int i;
211 luaM_reallocvector(L, t->array, t->sizearray, size, TObject); 205 luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
@@ -217,16 +211,22 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
217 211
218static void setnodevector (lua_State *L, Table *t, int lsize) { 212static void setnodevector (lua_State *L, Table *t, int lsize) {
219 int i; 213 int i;
220 int size; 214 int size = twoto(lsize);
221 if (lsize < MINHASHSIZE) lsize = MINHASHSIZE; 215 if (lsize > MAXBITS)
222 else if (lsize > MAXBITS)
223 luaD_runerror(L, "table overflow"); 216 luaD_runerror(L, "table overflow");
224 size = twoto(lsize); 217 if (lsize == 0) { /* no elements to hash part? */
225 t->node = luaM_newvector(L, size, Node); 218 t->node = G(L)->dummynode; /* use common `dummynode' */
226 for (i=0; i<size; i++) { 219 lua_assert(ttype(key(t->node)) == LUA_TNIL); /* assert invariants: */
227 t->node[i].next = NULL; 220 lua_assert(ttype(val(t->node)) == LUA_TNIL);
228 setnilvalue(key(node(t, i))); 221 lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */
229 setnilvalue(val(node(t, i))); 222 }
223 else {
224 t->node = luaM_newvector(L, size, Node);
225 for (i=0; i<size; i++) {
226 t->node[i].next = NULL;
227 setnilvalue(key(node(t, i)));
228 setnilvalue(val(node(t, i)));
229 }
230 } 230 }
231 t->lsizenode = cast(lu_byte, lsize); 231 t->lsizenode = cast(lu_byte, lsize);
232 t->firstfree = node(t, size-1); /* first free position to be used */ 232 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) {
235 235
236static void resize (lua_State *L, Table *t, int nasize, int nhsize) { 236static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
237 int i; 237 int i;
238 int oldasize, oldhsize; 238 int oldasize = t->sizearray;
239 int oldhsize = t->lsizenode;
239 Node *nold; 240 Node *nold;
240 oldasize = t->sizearray; 241 Node temp[1];
242 if (oldhsize)
243 nold = t->node; /* save old hash ... */
244 else { /* old hash is `dummynode' */
245 lua_assert(t->node == G(L)->dummynode);
246 temp[0] = t->node[0]; /* copy it to `temp' (in case of errors) */
247 nold = temp;
248 setnilvalue(key(G(L)->dummynode)); /* restate invariant */
249 setnilvalue(val(G(L)->dummynode));
250 }
241 if (nasize > oldasize) /* should grow array part? */ 251 if (nasize > oldasize) /* should grow array part? */
242 setarrayvector(L, t, nasize); 252 setarrayvector(L, t, nasize);
243 /* create new hash part with appropriate size */ 253 /* create new hash part with appropriate size */
244 nold = t->node; /* save old hash ... */
245 oldhsize = t->lsizenode; /* ... and (log of) old size */
246 setnodevector(L, t, nhsize); 254 setnodevector(L, t, nhsize);
247 /* re-insert elements */ 255 /* re-insert elements */
248 if (nasize < oldasize) { /* array part must shrink? */ 256 if (nasize < oldasize) { /* array part must shrink? */
@@ -262,7 +270,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
262 if (ttype(val(old)) != LUA_TNIL) 270 if (ttype(val(old)) != LUA_TNIL)
263 luaH_set(L, t, key(old), val(old)); 271 luaH_set(L, t, key(old), val(old));
264 } 272 }
265 luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ 273 if (oldhsize)
274 luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
266} 275}
267 276
268 277
@@ -299,8 +308,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
299 308
300 309
301void luaH_free (lua_State *L, Table *t) { 310void luaH_free (lua_State *L, Table *t) {
302 lua_assert(t->lsizenode > 0 || t->node == NULL); 311 if (t->lsizenode)
303 if (t->lsizenode > 0)
304 luaM_freearray(L, t->node, sizenode(t), Node); 312 luaM_freearray(L, t->node, sizenode(t), Node);
305 luaM_freearray(L, t->array, t->sizearray, TObject); 313 luaM_freearray(L, t->array, t->sizearray, TObject);
306 luaM_freelem(L, t); 314 luaM_freelem(L, t);