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 /ltable.c | |
parent | f1a1bb23fe29264ec0cf81a8bbfa8f30b0a5b76d (diff) | |
download | lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.gz lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.tar.bz2 lua-383e8b9e778d2bed9dc4347f441803e2c4f99d09.zip |
use of a common `dummynode' for all empty tables
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 58 |
1 files changed, 33 insertions, 25 deletions
@@ -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); |