diff options
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 131 |
1 files changed, 85 insertions, 46 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.121 2017/05/19 12:47:00 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.122 2017/05/19 12:57:10 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 | */ |
@@ -75,8 +75,8 @@ | |||
75 | #define dummynode (&dummynode_) | 75 | #define dummynode (&dummynode_) |
76 | 76 | ||
77 | static const Node dummynode_ = { | 77 | static const Node dummynode_ = { |
78 | {NILCONSTANT}, /* value */ | 78 | {{NULL}, LUA_TNIL, /* value's value and type */ |
79 | {{NILCONSTANT, 0}} /* key */ | 79 | LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ |
80 | }; | 80 | }; |
81 | 81 | ||
82 | 82 | ||
@@ -111,43 +111,79 @@ static int l_hashfloat (lua_Number n) { | |||
111 | 111 | ||
112 | 112 | ||
113 | /* | 113 | /* |
114 | ** returns the 'main' position of an element in a table (that is, the index | 114 | ** returns the 'main' position of an element in a table (that is, |
115 | ** of its hash value) | 115 | ** the index of its hash value). The key comes broken (tag in 'ktt' |
116 | ** and value in 'vkl') so that we can call it on keys inserted into | ||
117 | ** nodes. | ||
116 | */ | 118 | */ |
117 | static Node *mainposition (const Table *t, const TValue *key) { | 119 | static Node *mainposition (const Table *t, int ktt, const Value *kvl) { |
118 | switch (ttype(key)) { | 120 | switch (ttyperaw(ktt)) { |
119 | case LUA_TNUMINT: | 121 | case LUA_TNUMINT: |
120 | return hashint(t, ivalue(key)); | 122 | return hashint(t, ivalueraw(*kvl)); |
121 | case LUA_TNUMFLT: | 123 | case LUA_TNUMFLT: |
122 | return hashmod(t, l_hashfloat(fltvalue(key))); | 124 | return hashmod(t, l_hashfloat(fltvalueraw(*kvl))); |
123 | case LUA_TSHRSTR: | 125 | case LUA_TSHRSTR: |
124 | return hashstr(t, tsvalue(key)); | 126 | return hashstr(t, tsvalueraw(*kvl)); |
125 | case LUA_TLNGSTR: | 127 | case LUA_TLNGSTR: |
126 | return hashpow2(t, luaS_hashlongstr(tsvalue(key))); | 128 | return hashpow2(t, luaS_hashlongstr(tsvalueraw(*kvl))); |
127 | case LUA_TBOOLEAN: | 129 | case LUA_TBOOLEAN: |
128 | return hashboolean(t, bvalue(key)); | 130 | return hashboolean(t, bvalueraw(*kvl)); |
129 | case LUA_TLIGHTUSERDATA: | 131 | case LUA_TLIGHTUSERDATA: |
130 | return hashpointer(t, pvalue(key)); | 132 | return hashpointer(t, pvalueraw(*kvl)); |
131 | case LUA_TLCF: | 133 | case LUA_TLCF: |
132 | return hashpointer(t, fvalue(key)); | 134 | return hashpointer(t, fvalueraw(*kvl)); |
133 | default: | 135 | default: |
134 | lua_assert(!ttisdeadkey(key)); | 136 | return hashpointer(t, gcvalueraw(*kvl)); |
135 | return hashpointer(t, gcvalue(key)); | ||
136 | } | 137 | } |
137 | } | 138 | } |
138 | 139 | ||
139 | 140 | ||
141 | static Node *mainpositionTV (const Table *t, const TValue *key) { | ||
142 | return mainposition(t, rttype(key), valraw(key)); | ||
143 | } | ||
144 | |||
145 | |||
140 | /* | 146 | /* |
141 | ** returns the index for 'key' if 'key' is an appropriate key to live in | 147 | ** Check whether key 'k1' is equal to the key in node 'n2'. |
142 | ** the array part of the table, 0 otherwise. | 148 | ** This equality is raw, so there are no metamethods. Floats |
149 | ** with integer values have been normalized, so integers cannot | ||
150 | ** be equal to floats. It is assumed that 'eqshrstr' is simply | ||
151 | ** pointer equality, so that short strings are handled in the | ||
152 | ** default case. | ||
143 | */ | 153 | */ |
144 | static unsigned int arrayindex (const TValue *key) { | 154 | static int equalkey (const TValue *k1, const Node *n2) { |
145 | if (ttisinteger(key)) { | 155 | if (rttype(k1) != keytt(n2)) /* not the same variants? */ |
146 | lua_Integer k = ivalue(key); | 156 | return 0; /* cannot be same key */ |
147 | if (0 < k && (lua_Unsigned)k <= MAXASIZE) | 157 | switch (ttype(k1)) { |
148 | return cast(unsigned int, k); /* 'key' is an appropriate array index */ | 158 | case LUA_TNIL: |
159 | return 1; | ||
160 | case LUA_TNUMINT: | ||
161 | return (ivalue(k1) == keyival(n2)); | ||
162 | case LUA_TNUMFLT: | ||
163 | return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); | ||
164 | case LUA_TBOOLEAN: | ||
165 | return bvalue(k1) == bvalueraw(keyval(n2)); | ||
166 | case LUA_TLIGHTUSERDATA: | ||
167 | return pvalue(k1) == pvalueraw(keyval(n2)); | ||
168 | case LUA_TLCF: | ||
169 | return fvalue(k1) == fvalueraw(keyval(n2)); | ||
170 | case LUA_TLNGSTR: | ||
171 | return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); | ||
172 | default: | ||
173 | return gcvalue(k1) == gcvalueraw(keyval(n2)); | ||
149 | } | 174 | } |
150 | return 0; /* 'key' did not match some condition */ | 175 | } |
176 | |||
177 | |||
178 | /* | ||
179 | ** returns the index for 'k' if 'k' is an appropriate key to live in | ||
180 | ** the array part of a table, 0 otherwise. | ||
181 | */ | ||
182 | static unsigned int arrayindex (lua_Integer k) { | ||
183 | if (0 < k && l_castS2U(k) <= MAXASIZE) | ||
184 | return cast(unsigned int, k); /* 'key' is an appropriate array index */ | ||
185 | else | ||
186 | return 0; | ||
151 | } | 187 | } |
152 | 188 | ||
153 | 189 | ||
@@ -159,17 +195,17 @@ static unsigned int arrayindex (const TValue *key) { | |||
159 | static unsigned int findindex (lua_State *L, Table *t, StkId key) { | 195 | static unsigned int findindex (lua_State *L, Table *t, StkId key) { |
160 | unsigned int i; | 196 | unsigned int i; |
161 | if (ttisnil(key)) return 0; /* first iteration */ | 197 | if (ttisnil(key)) return 0; /* first iteration */ |
162 | i = arrayindex(key); | 198 | i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; |
163 | if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ | 199 | if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ |
164 | return i; /* yes; that's the index */ | 200 | return i; /* yes; that's the index */ |
165 | else { | 201 | else { |
166 | int nx; | 202 | int nx; |
167 | Node *n = mainposition(t, key); | 203 | Node *n = mainpositionTV(t, key); |
168 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 204 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
169 | /* key may be dead already, but it is ok to use it in 'next' */ | 205 | /* key may be dead already, but it is ok to use it in 'next' */ |
170 | if (luaV_rawequalobj(gkey(n), key) || | 206 | if (equalkey(key, n) || |
171 | (ttisdeadkey(gkey(n)) && iscollectable(key) && | 207 | (keyisdead(n) && iscollectable(key) && |
172 | deadvalue(gkey(n)) == gcvalue(key))) { | 208 | deadkey(n) == gcvalue(key))) { |
173 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ | 209 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ |
174 | /* hash elements are numbered after array ones */ | 210 | /* hash elements are numbered after array ones */ |
175 | return (i + 1) + t->sizearray; | 211 | return (i + 1) + t->sizearray; |
@@ -194,8 +230,9 @@ int luaH_next (lua_State *L, Table *t, StkId key) { | |||
194 | } | 230 | } |
195 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ | 231 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ |
196 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ | 232 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ |
197 | setobj2s(L, key, gkey(gnode(t, i))); | 233 | Node *n = gnode(t, i); |
198 | setobj2s(L, key+1, gval(gnode(t, i))); | 234 | getnodekey(L, key, n); |
235 | setobj2s(L, key + 1, gval(n)); | ||
199 | return 1; | 236 | return 1; |
200 | } | 237 | } |
201 | } | 238 | } |
@@ -239,7 +276,7 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { | |||
239 | } | 276 | } |
240 | 277 | ||
241 | 278 | ||
242 | static int countint (const TValue *key, unsigned int *nums) { | 279 | static int countint (lua_Integer key, unsigned int *nums) { |
243 | unsigned int k = arrayindex(key); | 280 | unsigned int k = arrayindex(key); |
244 | if (k != 0) { /* is 'key' an appropriate array index? */ | 281 | if (k != 0) { /* is 'key' an appropriate array index? */ |
245 | nums[luaO_ceillog2(k)]++; /* count as such */ | 282 | nums[luaO_ceillog2(k)]++; /* count as such */ |
@@ -288,7 +325,8 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { | |||
288 | while (i--) { | 325 | while (i--) { |
289 | Node *n = &t->node[i]; | 326 | Node *n = &t->node[i]; |
290 | if (!ttisnil(gval(n))) { | 327 | if (!ttisnil(gval(n))) { |
291 | ause += countint(gkey(n), nums); | 328 | if (keyisinteger(n)) |
329 | ause += countint(keyival(n), nums); | ||
292 | totaluse++; | 330 | totaluse++; |
293 | } | 331 | } |
294 | } | 332 | } |
@@ -322,7 +360,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
322 | for (i = 0; i < (int)size; i++) { | 360 | for (i = 0; i < (int)size; i++) { |
323 | Node *n = gnode(t, i); | 361 | Node *n = gnode(t, i); |
324 | gnext(n) = 0; | 362 | gnext(n) = 0; |
325 | setnilvalue(wgkey(n)); | 363 | setnilkey(n); |
326 | setnilvalue(gval(n)); | 364 | setnilvalue(gval(n)); |
327 | } | 365 | } |
328 | t->lsizenode = cast_byte(lsize); | 366 | t->lsizenode = cast_byte(lsize); |
@@ -358,7 +396,8 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | |||
358 | if (!ttisnil(gval(old))) { | 396 | if (!ttisnil(gval(old))) { |
359 | /* doesn't need barrier/invalidate cache, as entry was | 397 | /* doesn't need barrier/invalidate cache, as entry was |
360 | already present in the table */ | 398 | already present in the table */ |
361 | setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); | 399 | TValue k; getnodekey(L, &k, old); |
400 | setobjt2t(L, luaH_set(L, t, &k), gval(old)); | ||
362 | } | 401 | } |
363 | } | 402 | } |
364 | if (oldhsize > 0) /* not the dummy node? */ | 403 | if (oldhsize > 0) /* not the dummy node? */ |
@@ -385,7 +424,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { | |||
385 | totaluse = na; /* all those keys are integer keys */ | 424 | totaluse = na; /* all those keys are integer keys */ |
386 | totaluse += numusehash(t, nums, &na); /* count keys in hash part */ | 425 | totaluse += numusehash(t, nums, &na); /* count keys in hash part */ |
387 | /* count extra key */ | 426 | /* count extra key */ |
388 | na += countint(ek, nums); | 427 | if (ttisinteger(ek)) |
428 | na += countint(ivalue(ek), nums); | ||
389 | totaluse++; | 429 | totaluse++; |
390 | /* compute new size for array part */ | 430 | /* compute new size for array part */ |
391 | asize = computesizes(nums, &na); | 431 | asize = computesizes(nums, &na); |
@@ -424,7 +464,7 @@ static Node *getfreepos (Table *t) { | |||
424 | if (!isdummy(t)) { | 464 | if (!isdummy(t)) { |
425 | while (t->lastfree > t->node) { | 465 | while (t->lastfree > t->node) { |
426 | t->lastfree--; | 466 | t->lastfree--; |
427 | if (ttisnil(gkey(t->lastfree))) | 467 | if (keyisnil(t->lastfree)) |
428 | return t->lastfree; | 468 | return t->lastfree; |
429 | } | 469 | } |
430 | } | 470 | } |
@@ -453,7 +493,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
453 | else if (luai_numisnan(fltvalue(key))) | 493 | else if (luai_numisnan(fltvalue(key))) |
454 | luaG_runerror(L, "table index is NaN"); | 494 | luaG_runerror(L, "table index is NaN"); |
455 | } | 495 | } |
456 | mp = mainposition(t, key); | 496 | mp = mainpositionTV(t, key); |
457 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ | 497 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
458 | Node *othern; | 498 | Node *othern; |
459 | Node *f = getfreepos(t); /* get a free place */ | 499 | Node *f = getfreepos(t); /* get a free place */ |
@@ -463,7 +503,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
463 | return luaH_set(L, t, key); /* insert key into grown table */ | 503 | return luaH_set(L, t, key); /* insert key into grown table */ |
464 | } | 504 | } |
465 | lua_assert(!isdummy(t)); | 505 | lua_assert(!isdummy(t)); |
466 | othern = mainposition(t, gkey(mp)); | 506 | othern = mainposition(t, keytt(mp), &keyval(mp)); |
467 | if (othern != mp) { /* is colliding node out of its main position? */ | 507 | if (othern != mp) { /* is colliding node out of its main position? */ |
468 | /* yes; move colliding node into free position */ | 508 | /* yes; move colliding node into free position */ |
469 | while (othern + gnext(othern) != mp) /* find previous */ | 509 | while (othern + gnext(othern) != mp) /* find previous */ |
@@ -485,7 +525,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
485 | mp = f; | 525 | mp = f; |
486 | } | 526 | } |
487 | } | 527 | } |
488 | setnodekey(L, &mp->i_key, key); | 528 | setnodekey(L, mp, key); |
489 | luaC_barrierback(L, t, key); | 529 | luaC_barrierback(L, t, key); |
490 | lua_assert(ttisnil(gval(mp))); | 530 | lua_assert(ttisnil(gval(mp))); |
491 | return gval(mp); | 531 | return gval(mp); |
@@ -502,7 +542,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
502 | else { | 542 | else { |
503 | Node *n = hashint(t, key); | 543 | Node *n = hashint(t, key); |
504 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 544 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
505 | if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) | 545 | if (keyisinteger(n) && keyival(n) == key) |
506 | return gval(n); /* that's it */ | 546 | return gval(n); /* that's it */ |
507 | else { | 547 | else { |
508 | int nx = gnext(n); | 548 | int nx = gnext(n); |
@@ -522,8 +562,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { | |||
522 | Node *n = hashstr(t, key); | 562 | Node *n = hashstr(t, key); |
523 | lua_assert(key->tt == LUA_TSHRSTR); | 563 | lua_assert(key->tt == LUA_TSHRSTR); |
524 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 564 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
525 | const TValue *k = gkey(n); | 565 | if (keyisshrstr(n) && eqshrstr(keystrval(n), key)) |
526 | if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) | ||
527 | return gval(n); /* that's it */ | 566 | return gval(n); /* that's it */ |
528 | else { | 567 | else { |
529 | int nx = gnext(n); | 568 | int nx = gnext(n); |
@@ -540,9 +579,9 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { | |||
540 | ** which may be in array part, nor for floats with integral values.) | 579 | ** which may be in array part, nor for floats with integral values.) |
541 | */ | 580 | */ |
542 | static const TValue *getgeneric (Table *t, const TValue *key) { | 581 | static const TValue *getgeneric (Table *t, const TValue *key) { |
543 | Node *n = mainposition(t, key); | 582 | Node *n = mainpositionTV(t, key); |
544 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 583 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
545 | if (luaV_rawequalobj(gkey(n), key)) | 584 | if (equalkey(key, n)) |
546 | return gval(n); /* that's it */ | 585 | return gval(n); /* that's it */ |
547 | else { | 586 | else { |
548 | int nx = gnext(n); | 587 | int nx = gnext(n); |
@@ -683,7 +722,7 @@ lua_Unsigned luaH_getn (Table *t) { | |||
683 | #if defined(LUA_DEBUG) | 722 | #if defined(LUA_DEBUG) |
684 | 723 | ||
685 | Node *luaH_mainposition (const Table *t, const TValue *key) { | 724 | Node *luaH_mainposition (const Table *t, const TValue *key) { |
686 | return mainposition(t, key); | 725 | return mainpositionTV(t, key); |
687 | } | 726 | } |
688 | 727 | ||
689 | int luaH_isdummy (const Table *t) { return isdummy(t); } | 728 | int luaH_isdummy (const Table *t) { return isdummy(t); } |