aboutsummaryrefslogtreecommitdiff
path: root/ltable.c
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 /ltable.c
parentdc4e0ecdafbdd2e0f936680ccc703b663260407e (diff)
downloadlua-654b16e83aad64643d524295300cf29677b7f2ba.tar.gz
lua-654b16e83aad64643d524295300cf29677b7f2ba.tar.bz2
lua-654b16e83aad64643d524295300cf29677b7f2ba.zip
better performance for table operations (mainly for integer indices)
Diffstat (limited to 'ltable.c')
-rw-r--r--ltable.c125
1 files changed, 75 insertions, 50 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