better performance for table operations (mainly for integer indices)

This commit is contained in:
Roberto Ierusalimschy 2001-07-05 17:31:14 -03:00
parent dc4e0ecdaf
commit 654b16e83a
3 changed files with 86 additions and 65 deletions

125
ltable.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.c,v 1.81 2001/06/15 20:36:57 roberto Exp roberto $ ** $Id: ltable.c,v 1.82 2001/06/26 13:20:45 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -41,14 +41,14 @@
** returns the `main' position of an element in a table (that is, the index ** returns the `main' position of an element in a table (that is, the index
** of its hash value) ** of its hash value)
*/ */
Node *luaH_mainposition (const Hash *t, const Node *n) { Node *luaH_mainposition (const Hash *t, const TObject *key) {
switch (ttype(key(n))) { switch (ttype(key)) {
case LUA_TNUMBER: case LUA_TNUMBER:
return hashnum(t, nvalue(key(n))); return hashnum(t, nvalue(key));
case LUA_TSTRING: case LUA_TSTRING:
return hashstr(t, tsvalue(key(n))); return hashstr(t, tsvalue(key));
default: /* all other types are hashed as (void *) */ default: /* all other types are hashed as (void *) */
return hashpointer(t, tsvalue(key(n))); return hashpointer(t, tsvalue(key));
} }
} }
@ -61,8 +61,8 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
const TObject *v = luaH_get(t, key); const TObject *v = luaH_get(t, key);
if (v == &luaO_nilobject) if (v == &luaO_nilobject)
luaD_error(L, l_s("invalid key for `next'")); luaD_error(L, l_s("invalid key for `next'"));
i = (int)(((const l_char *)v - i = (int)(((const lu_byte *)v -
(const l_char *)(val(node(t, 0)))) / sizeof(Node)) + 1; (const lu_byte *)(val(node(t, 0)))) / sizeof(Node)) + 1;
} }
for (; i<t->size; i++) { for (; i<t->size; i++) {
Node *n = node(t, i); Node *n = node(t, i);
@ -74,7 +74,7 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
int luaH_nexti (Hash *t, int i) { int luaH_nexti (Hash *t, int i) {
for (i++; i<t->size; i++) { while ((++i)<t->size) {
if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */ if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */
return i; return i;
} }
@ -177,9 +177,10 @@ static void rehash (lua_State *L, Hash *t) {
** put new key in its main position; otherwise (colliding node is in its main ** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position. ** position), new key goes to an empty position.
*/ */
static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) { static TObject *newkey (lua_State *L, Hash *t, const TObject *key) {
Node *mp = luaH_mainposition(t, key);
if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */
Node *othern = luaH_mainposition(t, mp); /* `mp' of colliding node */ Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */
Node *n = t->firstfree; /* get a free place */ Node *n = t->firstfree; /* get a free place */
if (othern != mp) { /* is colliding node out of its main position? */ if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */ /* yes; move colliding node into free position */
@ -210,68 +211,92 @@ static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) {
/* /*
** search function for numbers ** generic search function
*/ */
TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) { static const TObject *luaH_getany (Hash *t, const TObject *key) {
TObject kobj; if (ttype(key) == LUA_TNIL) return &luaO_nilobject;
Node *mp = hashnum(t, key); else {
Node *n = mp; Node *n = luaH_mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
if (luaO_equalObj(key(n), key)) return val(n); /* that's it */
else n = n->next;
} while (n);
return &luaO_nilobject;
}
}
/*
** search function for integers
*/
const TObject *luaH_getnum (Hash *t, int key) {
Node *n = hashnum(t, key);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == key) if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key)
return val(n); /* that's all */ return val(n); /* that's it */
else n = n->next; else n = n->next;
} while (n); } while (n);
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ return &luaO_nilobject;
/* `key' not found; must insert it */
setnvalue(&kobj, key);
return newkey(L, t, mp, &kobj);
} }
/* /*
** search function for strings ** search function for strings
*/ */
TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) { const TObject *luaH_getstr (Hash *t, TString *key) {
TObject kobj; Node *n = hashstr(t, key);
Node *mp = hashstr(t, key);
Node *n = mp;
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key)
return val(n); /* that's all */ return val(n); /* that's it */
else n = n->next; else n = n->next;
} while (n); } while (n);
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ return &luaO_nilobject;
/* `key' not found; must insert it */
setsvalue(&kobj, key);
return newkey(L, t, mp, &kobj);
} }
/* /*
** search function for 'pointer' types ** main search function
*/ */
static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) { const TObject *luaH_get (Hash *t, const TObject *key) {
Node *mp = hashpointer(t, hvalue(key)); switch (ttype(key)) {
Node *n = mp; case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
do { /* check whether `key' is somewhere in the chain */ case LUA_TNUMBER: {
/* compare as `tsvalue', but may be other pointers (it is the same) */ int k = (int)nvalue(key);
if (ttype(key(n)) == ttype(key) && tsvalue(key(n)) == tsvalue(key)) if ((lua_Number)k == nvalue(key)) /* is an integer index? */
return val(n); /* that's all */ return luaH_getnum(t, k); /* use specialized version */
else n = n->next; /* else go through */
} while (n); }
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */ default: return luaH_getany(t, key);
return newkey(L, t, mp, key); /* `key' not found; must insert it */ }
} }
TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
switch (ttype(key)) { const TObject *p = luaH_get(t, key);
case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key)); if (p != &luaO_nilobject) return (TObject *)p;
case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key)); else if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil"));
case LUA_TNIL: return newkey(L, t, key);
if (L) luaD_error(L, l_s("table index is nil")); }
return (TObject *)&luaO_nilobject; /* get option */
default: return luaH_setany(L, t, key);
TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
const TObject *p = luaH_getstr(t, key);
if (p != &luaO_nilobject) return (TObject *)p;
else {
TObject k;
setsvalue(&k, key);
return newkey(L, t, &k);
}
}
TObject *luaH_setnum (lua_State *L, Hash *t, int key) {
const TObject *p = luaH_getnum(t, key);
if (p != &luaO_nilobject) return (TObject *)p;
else {
TObject k;
setnvalue(&k, key);
return newkey(L, t, &k);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.h,v 1.32 2001/02/02 16:32:00 roberto Exp roberto $ ** $Id: ltable.h,v 1.33 2001/06/26 13:20:45 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -14,21 +14,19 @@
#define key(_n) (&(_n)->key) #define key(_n) (&(_n)->key)
#define val(_n) (&(_n)->val) #define val(_n) (&(_n)->val)
const TObject *luaH_getnum (Hash *t, int key);
#define luaH_get(_t,_k) luaH_set(NULL,_t,_k) TObject *luaH_setnum (lua_State *L, Hash *t, int key);
#define luaH_getnum(_t,_k) luaH_setnum(NULL,_t,_k) const TObject *luaH_getstr (Hash *t, TString *key);
#define luaH_getstr(_t,_k) luaH_setstr(NULL,_t,_k) TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
const TObject *luaH_get (Hash *t, const TObject *key);
TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
Hash *luaH_new (lua_State *L, int nhash); Hash *luaH_new (lua_State *L, int nhash);
void luaH_free (lua_State *L, Hash *t); void luaH_free (lua_State *L, Hash *t);
TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
Node *luaH_next (lua_State *L, Hash *t, const TObject *r); Node *luaH_next (lua_State *L, Hash *t, const TObject *r);
int luaH_nexti (Hash *t, int i); int luaH_nexti (Hash *t, int i);
TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key);
TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
/* exported only for debugging */ /* exported only for debugging */
Node *luaH_mainposition (const Hash *t, const Node *n); Node *luaH_mainposition (const Hash *t, const TObject *key);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltests.c,v 1.85 2001/06/28 15:06:20 roberto Exp roberto $ ** $Id: ltests.c,v 1.86 2001/06/28 19:58:57 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation ** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -251,13 +251,11 @@ static int hash_query (lua_State *L) {
lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash); lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash);
} }
else { else {
Hash *t;
Node n;
TObject *o = luaA_index(L, 1); TObject *o = luaA_index(L, 1);
Hash *t;
luaL_checktype(L, 2, LUA_TTABLE); luaL_checktype(L, 2, LUA_TTABLE);
t = hvalue(luaA_index(L, 2)); t = hvalue(luaA_index(L, 2));
setobj(key(&n), o); lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
lua_pushnumber(L, luaH_mainposition(t, &n) - t->node);
} }
return 1; return 1;
} }