aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-07-05 17:31:14 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-07-05 17:31:14 -0300
commit654b16e83aad64643d524295300cf29677b7f2ba (patch)
tree2db8ea2d0b7d9a12daa0691e3a966fe05751a0f0
parentdc4e0ecdafbdd2e0f936680ccc703b663260407e (diff)
downloadlua-654b16e83aad64643d524295300cf29677b7f2ba.tar.gz
lua-654b16e83aad64643d524295300cf29677b7f2ba.tar.bz2
lua-654b16e83aad64643d524295300cf29677b7f2ba.zip
better performance for table operations (mainly for integer indices)
-rw-r--r--ltable.c125
-rw-r--r--ltable.h18
-rw-r--r--ltests.c8
3 files changed, 86 insertions, 65 deletions
diff --git a/ltable.c b/ltable.c
index c51b0a81..aea20f38 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.81 2001/06/15 20:36:57 roberto Exp roberto $ 2** $Id: ltable.c,v 1.82 2001/06/26 13:20:45 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*/
@@ -41,14 +41,14 @@
41** returns the `main' position of an element in a table (that is, the index 41** returns the `main' position of an element in a table (that is, the index
42** of its hash value) 42** of its hash value)
43*/ 43*/
44Node *luaH_mainposition (const Hash *t, const Node *n) { 44Node *luaH_mainposition (const Hash *t, const TObject *key) {
45 switch (ttype(key(n))) { 45 switch (ttype(key)) {
46 case LUA_TNUMBER: 46 case LUA_TNUMBER:
47 return hashnum(t, nvalue(key(n))); 47 return hashnum(t, nvalue(key));
48 case LUA_TSTRING: 48 case LUA_TSTRING:
49 return hashstr(t, tsvalue(key(n))); 49 return hashstr(t, tsvalue(key));
50 default: /* all other types are hashed as (void *) */ 50 default: /* all other types are hashed as (void *) */
51 return hashpointer(t, tsvalue(key(n))); 51 return hashpointer(t, tsvalue(key));
52 } 52 }
53} 53}
54 54
@@ -61,8 +61,8 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
61 const TObject *v = luaH_get(t, key); 61 const TObject *v = luaH_get(t, key);
62 if (v == &luaO_nilobject) 62 if (v == &luaO_nilobject)
63 luaD_error(L, l_s("invalid key for `next'")); 63 luaD_error(L, l_s("invalid key for `next'"));
64 i = (int)(((const l_char *)v - 64 i = (int)(((const lu_byte *)v -
65 (const l_char *)(val(node(t, 0)))) / sizeof(Node)) + 1; 65 (const lu_byte *)(val(node(t, 0)))) / sizeof(Node)) + 1;
66 } 66 }
67 for (; i<t->size; i++) { 67 for (; i<t->size; i++) {
68 Node *n = node(t, i); 68 Node *n = node(t, i);
@@ -74,7 +74,7 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
74 74
75 75
76int luaH_nexti (Hash *t, int i) { 76int luaH_nexti (Hash *t, int i) {
77 for (i++; i<t->size; i++) { 77 while ((++i)<t->size) {
78 if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */ 78 if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */
79 return i; 79 return i;
80 } 80 }
@@ -177,9 +177,10 @@ static void rehash (lua_State *L, Hash *t) {
177** put new key in its main position; otherwise (colliding node is in its main 177** put new key in its main position; otherwise (colliding node is in its main
178** position), new key goes to an empty position. 178** position), new key goes to an empty position.
179*/ 179*/
180static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) { 180static TObject *newkey (lua_State *L, Hash *t, const TObject *key) {
181 Node *mp = luaH_mainposition(t, key);
181 if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ 182 if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */
182 Node *othern = luaH_mainposition(t, mp); /* `mp' of colliding node */ 183 Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */
183 Node *n = t->firstfree; /* get a free place */ 184 Node *n = t->firstfree; /* get a free place */
184 if (othern != mp) { /* is colliding node out of its main position? */ 185 if (othern != mp) { /* is colliding node out of its main position? */
185 /* yes; move colliding node into free position */ 186 /* yes; move colliding node into free position */
@@ -210,68 +211,92 @@ static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) {
210 211
211 212
212/* 213/*
213** search function for numbers 214** generic search function
214*/ 215*/
215TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) { 216static const TObject *luaH_getany (Hash *t, const TObject *key) {
216 TObject kobj; 217 if (ttype(key) == LUA_TNIL) return &luaO_nilobject;
217 Node *mp = hashnum(t, key); 218 else {
218 Node *n = mp; 219 Node *n = luaH_mainposition(t, key);
220 do { /* check whether `key' is somewhere in the chain */
221 if (luaO_equalObj(key(n), key)) return val(n); /* that's it */
222 else n = n->next;
223 } while (n);
224 return &luaO_nilobject;
225 }
226}
227
228
229/*
230** search function for integers
231*/
232const TObject *luaH_getnum (Hash *t, int key) {
233 Node *n = hashnum(t, key);
219 do { /* check whether `key' is somewhere in the chain */ 234 do { /* check whether `key' is somewhere in the chain */
220 if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == key) 235 if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key)
221 return val(n); /* that's all */ 236 return val(n); /* that's it */
222 else n = n->next; 237 else n = n->next;
223 } while (n); 238 } while (n);
224 if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ 239 return &luaO_nilobject;
225 /* `key' not found; must insert it */
226 setnvalue(&kobj, key);
227 return newkey(L, t, mp, &kobj);
228} 240}
229 241
230 242
231/* 243/*
232** search function for strings 244** search function for strings
233*/ 245*/
234TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) { 246const TObject *luaH_getstr (Hash *t, TString *key) {
235 TObject kobj; 247 Node *n = hashstr(t, key);
236 Node *mp = hashstr(t, key);
237 Node *n = mp;
238 do { /* check whether `key' is somewhere in the chain */ 248 do { /* check whether `key' is somewhere in the chain */
239 if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) 249 if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key)
240 return val(n); /* that's all */ 250 return val(n); /* that's it */
241 else n = n->next; 251 else n = n->next;
242 } while (n); 252 } while (n);
243 if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ 253 return &luaO_nilobject;
244 /* `key' not found; must insert it */
245 setsvalue(&kobj, key);
246 return newkey(L, t, mp, &kobj);
247} 254}
248 255
249 256
250/* 257/*
251** search function for 'pointer' types 258** main search function
252*/ 259*/
253static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) { 260const TObject *luaH_get (Hash *t, const TObject *key) {
254 Node *mp = hashpointer(t, hvalue(key)); 261 switch (ttype(key)) {
255 Node *n = mp; 262 case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
256 do { /* check whether `key' is somewhere in the chain */ 263 case LUA_TNUMBER: {
257 /* compare as `tsvalue', but may be other pointers (it is the same) */ 264 int k = (int)nvalue(key);
258 if (ttype(key(n)) == ttype(key) && tsvalue(key(n)) == tsvalue(key)) 265 if ((lua_Number)k == nvalue(key)) /* is an integer index? */
259 return val(n); /* that's all */ 266 return luaH_getnum(t, k); /* use specialized version */
260 else n = n->next; 267 /* else go through */
261 } while (n); 268 }
262 if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ 269 default: return luaH_getany(t, key);
263 return newkey(L, t, mp, key); /* `key' not found; must insert it */ 270 }
264} 271}
265 272
266 273
267TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { 274TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
268 switch (ttype(key)) { 275 const TObject *p = luaH_get(t, key);
269 case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key)); 276 if (p != &luaO_nilobject) return (TObject *)p;
270 case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key)); 277 else if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil"));
271 case LUA_TNIL: 278 return newkey(L, t, key);
272 if (L) luaD_error(L, l_s("table index is nil")); 279}
273 return (TObject *)&luaO_nilobject; /* get option */ 280
274 default: return luaH_setany(L, t, key); 281
282TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
283 const TObject *p = luaH_getstr(t, key);
284 if (p != &luaO_nilobject) return (TObject *)p;
285 else {
286 TObject k;
287 setsvalue(&k, key);
288 return newkey(L, t, &k);
289 }
290}
291
292
293TObject *luaH_setnum (lua_State *L, Hash *t, int key) {
294 const TObject *p = luaH_getnum(t, key);
295 if (p != &luaO_nilobject) return (TObject *)p;
296 else {
297 TObject k;
298 setnvalue(&k, key);
299 return newkey(L, t, &k);
275 } 300 }
276} 301}
277 302
diff --git a/ltable.h b/ltable.h
index a7c617c4..df0ff232 100644
--- a/ltable.h
+++ b/ltable.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.h,v 1.32 2001/02/02 16:32:00 roberto Exp roberto $ 2** $Id: ltable.h,v 1.33 2001/06/26 13:20:45 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*/
@@ -14,21 +14,19 @@
14#define key(_n) (&(_n)->key) 14#define key(_n) (&(_n)->key)
15#define val(_n) (&(_n)->val) 15#define val(_n) (&(_n)->val)
16 16
17 17const TObject *luaH_getnum (Hash *t, int key);
18#define luaH_get(_t,_k) luaH_set(NULL,_t,_k) 18TObject *luaH_setnum (lua_State *L, Hash *t, int key);
19#define luaH_getnum(_t,_k) luaH_setnum(NULL,_t,_k) 19const TObject *luaH_getstr (Hash *t, TString *key);
20#define luaH_getstr(_t,_k) luaH_setstr(NULL,_t,_k) 20TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
21 21const TObject *luaH_get (Hash *t, const TObject *key);
22TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
22Hash *luaH_new (lua_State *L, int nhash); 23Hash *luaH_new (lua_State *L, int nhash);
23void luaH_free (lua_State *L, Hash *t); 24void luaH_free (lua_State *L, Hash *t);
24TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
25Node *luaH_next (lua_State *L, Hash *t, const TObject *r); 25Node *luaH_next (lua_State *L, Hash *t, const TObject *r);
26int luaH_nexti (Hash *t, int i); 26int luaH_nexti (Hash *t, int i);
27TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key);
28TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
29 27
30/* exported only for debugging */ 28/* exported only for debugging */
31Node *luaH_mainposition (const Hash *t, const Node *n); 29Node *luaH_mainposition (const Hash *t, const TObject *key);
32 30
33 31
34#endif 32#endif
diff --git a/ltests.c b/ltests.c
index 8e7c2930..a8a1cd98 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.85 2001/06/28 15:06:20 roberto Exp roberto $ 2** $Id: ltests.c,v 1.86 2001/06/28 19:58:57 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -251,13 +251,11 @@ static int hash_query (lua_State *L) {
251 lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash); 251 lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash);
252 } 252 }
253 else { 253 else {
254 Hash *t;
255 Node n;
256 TObject *o = luaA_index(L, 1); 254 TObject *o = luaA_index(L, 1);
255 Hash *t;
257 luaL_checktype(L, 2, LUA_TTABLE); 256 luaL_checktype(L, 2, LUA_TTABLE);
258 t = hvalue(luaA_index(L, 2)); 257 t = hvalue(luaA_index(L, 2));
259 setobj(key(&n), o); 258 lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
260 lua_pushnumber(L, luaH_mainposition(t, &n) - t->node);
261 } 259 }
262 return 1; 260 return 1;
263} 261}