diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-04-23 12:04:39 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-04-23 12:04:39 -0300 |
commit | 383e8b9e778d2bed9dc4347f441803e2c4f99d09 (patch) | |
tree | 6035d4b69801d535f3042120e549e457fb154068 | |
parent | f1a1bb23fe29264ec0cf81a8bbfa8f30b0a5b76d (diff) | |
download | lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.gz lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.bz2 lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.zip |
use of a common `dummynode' for all empty tables
-rw-r--r-- | lgc.c | 15 | ||||
-rw-r--r-- | lstate.c | 5 | ||||
-rw-r--r-- | lstate.h | 3 | ||||
-rw-r--r-- | ltable.c | 58 |
4 files changed, 46 insertions, 35 deletions
@@ -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); |
@@ -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 */ |
@@ -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 | ||
@@ -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 | |||
209 | static void setarrayvector (lua_State *L, Table *t, int size) { | 203 | static 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 | ||
218 | static void setnodevector (lua_State *L, Table *t, int lsize) { | 212 | static 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 | ||
236 | static void resize (lua_State *L, Table *t, int nasize, int nhsize) { | 236 | static 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 | ||
301 | void luaH_free (lua_State *L, Table *t) { | 310 | void 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); |