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)
** See Copyright Notice in lua.h
*/
@ -41,14 +41,14 @@
** returns the `main' position of an element in a table (that is, the index
** of its hash value)
*/
Node *luaH_mainposition (const Hash *t, const Node *n) {
switch (ttype(key(n))) {
Node *luaH_mainposition (const Hash *t, const TObject *key) {
switch (ttype(key)) {
case LUA_TNUMBER:
return hashnum(t, nvalue(key(n)));
return hashnum(t, nvalue(key));
case LUA_TSTRING:
return hashstr(t, tsvalue(key(n)));
return hashstr(t, tsvalue(key));
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);
if (v == &luaO_nilobject)
luaD_error(L, l_s("invalid key for `next'"));
i = (int)(((const l_char *)v -
(const l_char *)(val(node(t, 0)))) / sizeof(Node)) + 1;
i = (int)(((const lu_byte *)v -
(const lu_byte *)(val(node(t, 0)))) / sizeof(Node)) + 1;
}
for (; i<t->size; 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) {
for (i++; i<t->size; i++) {
while ((++i)<t->size) {
if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */
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
** 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? */
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 */
if (othern != mp) { /* is colliding node out of its main 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) {
TObject kobj;
Node *mp = hashnum(t, key);
Node *n = mp;
static const TObject *luaH_getany (Hash *t, const TObject *key) {
if (ttype(key) == LUA_TNIL) return &luaO_nilobject;
else {
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 */
if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == key)
return val(n); /* that's all */
if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key)
return val(n); /* that's it */
else n = n->next;
} while (n);
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */
/* `key' not found; must insert it */
setnvalue(&kobj, key);
return newkey(L, t, mp, &kobj);
return &luaO_nilobject;
}
/*
** search function for strings
*/
TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
TObject kobj;
Node *mp = hashstr(t, key);
Node *n = mp;
const TObject *luaH_getstr (Hash *t, TString *key) {
Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */
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;
} while (n);
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */
/* `key' not found; must insert it */
setsvalue(&kobj, key);
return newkey(L, t, mp, &kobj);
return &luaO_nilobject;
}
/*
** search function for 'pointer' types
** main search function
*/
static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) {
Node *mp = hashpointer(t, hvalue(key));
Node *n = mp;
do { /* check whether `key' is somewhere in the chain */
/* compare as `tsvalue', but may be other pointers (it is the same) */
if (ttype(key(n)) == ttype(key) && tsvalue(key(n)) == tsvalue(key))
return val(n); /* that's all */
else n = n->next;
} while (n);
if (L == NULL) return (TObject *)&luaO_nilobject; /* get option */
return newkey(L, t, mp, key); /* `key' not found; must insert it */
const TObject *luaH_get (Hash *t, const TObject *key) {
switch (ttype(key)) {
case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
case LUA_TNUMBER: {
int k = (int)nvalue(key);
if ((lua_Number)k == nvalue(key)) /* is an integer index? */
return luaH_getnum(t, k); /* use specialized version */
/* else go through */
}
default: return luaH_getany(t, key);
}
}
TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
switch (ttype(key)) {
case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key));
case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key));
case LUA_TNIL:
if (L) luaD_error(L, l_s("table index is nil"));
return (TObject *)&luaO_nilobject; /* get option */
default: return luaH_setany(L, t, key);
const TObject *p = luaH_get(t, key);
if (p != &luaO_nilobject) return (TObject *)p;
else if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil"));
return newkey(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)
** See Copyright Notice in lua.h
*/
@ -14,21 +14,19 @@
#define key(_n) (&(_n)->key)
#define val(_n) (&(_n)->val)
#define luaH_get(_t,_k) luaH_set(NULL,_t,_k)
#define luaH_getnum(_t,_k) luaH_setnum(NULL,_t,_k)
#define luaH_getstr(_t,_k) luaH_setstr(NULL,_t,_k)
const TObject *luaH_getnum (Hash *t, int key);
TObject *luaH_setnum (lua_State *L, Hash *t, int key);
const TObject *luaH_getstr (Hash *t, TString *key);
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);
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);
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 */
Node *luaH_mainposition (const Hash *t, const Node *n);
Node *luaH_mainposition (const Hash *t, const TObject *key);
#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
** 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);
}
else {
Hash *t;
Node n;
TObject *o = luaA_index(L, 1);
Hash *t;
luaL_checktype(L, 2, LUA_TTABLE);
t = hvalue(luaA_index(L, 2));
setobj(key(&n), o);
lua_pushnumber(L, luaH_mainposition(t, &n) - t->node);
lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
}
return 1;
}