diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-07-05 17:31:14 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-07-05 17:31:14 -0300 |
commit | 654b16e83aad64643d524295300cf29677b7f2ba (patch) | |
tree | 2db8ea2d0b7d9a12daa0691e3a966fe05751a0f0 | |
parent | dc4e0ecdafbdd2e0f936680ccc703b663260407e (diff) | |
download | lua-654b16e83aad64643d524295300cf29677b7f2ba.tar.gz lua-654b16e83aad64643d524295300cf29677b7f2ba.tar.bz2 lua-654b16e83aad64643d524295300cf29677b7f2ba.zip |
better performance for table operations (mainly for integer indices)
-rw-r--r-- | ltable.c | 125 | ||||
-rw-r--r-- | ltable.h | 18 | ||||
-rw-r--r-- | ltests.c | 8 |
3 files changed, 86 insertions, 65 deletions
@@ -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 | */ |
44 | Node *luaH_mainposition (const Hash *t, const Node *n) { | 44 | Node *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 | ||
76 | int luaH_nexti (Hash *t, int i) { | 76 | int 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 | */ |
180 | static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) { | 180 | static 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 | */ |
215 | TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) { | 216 | static 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 | */ | ||
232 | const 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 | */ |
234 | TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) { | 246 | const 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 | */ |
253 | static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) { | 260 | const 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 | ||
267 | TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { | 274 | TObject *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 | |
282 | TObject *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 | |||
293 | TObject *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 | ||
@@ -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 | 17 | const TObject *luaH_getnum (Hash *t, int key); | |
18 | #define luaH_get(_t,_k) luaH_set(NULL,_t,_k) | 18 | TObject *luaH_setnum (lua_State *L, Hash *t, int key); |
19 | #define luaH_getnum(_t,_k) luaH_setnum(NULL,_t,_k) | 19 | const TObject *luaH_getstr (Hash *t, TString *key); |
20 | #define luaH_getstr(_t,_k) luaH_setstr(NULL,_t,_k) | 20 | TObject *luaH_setstr (lua_State *L, Hash *t, TString *key); |
21 | 21 | const TObject *luaH_get (Hash *t, const TObject *key); | |
22 | TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); | ||
22 | Hash *luaH_new (lua_State *L, int nhash); | 23 | Hash *luaH_new (lua_State *L, int nhash); |
23 | void luaH_free (lua_State *L, Hash *t); | 24 | void luaH_free (lua_State *L, Hash *t); |
24 | TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); | ||
25 | Node *luaH_next (lua_State *L, Hash *t, const TObject *r); | 25 | Node *luaH_next (lua_State *L, Hash *t, const TObject *r); |
26 | int luaH_nexti (Hash *t, int i); | 26 | int luaH_nexti (Hash *t, int i); |
27 | TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key); | ||
28 | TObject *luaH_setstr (lua_State *L, Hash *t, TString *key); | ||
29 | 27 | ||
30 | /* exported only for debugging */ | 28 | /* exported only for debugging */ |
31 | Node *luaH_mainposition (const Hash *t, const Node *n); | 29 | Node *luaH_mainposition (const Hash *t, const TObject *key); |
32 | 30 | ||
33 | 31 | ||
34 | #endif | 32 | #endif |
@@ -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 | } |