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 | } |
