summaryrefslogtreecommitdiff
path: root/src/ltable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ltable.c')
-rw-r--r--src/ltable.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/src/ltable.c b/src/ltable.c
index 33c1ab302e43..1b1cd2415b60 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -84,8 +84,6 @@
#define hashstr(t,str) hashpow2(t, (str)->hash)
#define hashboolean(t,p) hashpow2(t, p)
-#define hashint(t,i) hashpow2(t, i)
-
#define hashpointer(t,p) hashmod(t, point2uint(p))
@@ -101,6 +99,20 @@ static const Node dummynode_ = {
static const TValue absentkey = {ABSTKEYCONSTANT};
+/*
+** Hash for integers. To allow a good hash, use the remainder operator
+** ('%'). If integer fits as a non-negative int, compute an int
+** remainder, which is faster. Otherwise, use an unsigned-integer
+** remainder, which uses all bits and ensures a non-negative result.
+*/
+static Node *hashint (const Table *t, lua_Integer i) {
+ lua_Unsigned ui = l_castS2U(i);
+ if (ui <= (unsigned int)INT_MAX)
+ return hashmod(t, cast_int(ui));
+ else
+ return hashmod(t, ui);
+}
+
/*
** Hash for floating-point numbers.
@@ -134,26 +146,24 @@ static int l_hashfloat (lua_Number n) {
/*
** returns the 'main' position of an element in a table (that is,
-** the index of its hash value). The key comes broken (tag in 'ktt'
-** and value in 'vkl') so that we can call it on keys inserted into
-** nodes.
+** the index of its hash value).
*/
-static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
- switch (withvariant(ktt)) {
+static Node *mainpositionTV (const Table *t, const TValue *key) {
+ switch (ttypetag(key)) {
case LUA_VNUMINT: {
- lua_Integer key = ivalueraw(*kvl);
- return hashint(t, key);
+ lua_Integer i = ivalue(key);
+ return hashint(t, i);
}
case LUA_VNUMFLT: {
- lua_Number n = fltvalueraw(*kvl);
+ lua_Number n = fltvalue(key);
return hashmod(t, l_hashfloat(n));
}
case LUA_VSHRSTR: {
- TString *ts = tsvalueraw(*kvl);
+ TString *ts = tsvalue(key);
return hashstr(t, ts);
}
case LUA_VLNGSTR: {
- TString *ts = tsvalueraw(*kvl);
+ TString *ts = tsvalue(key);
return hashpow2(t, luaS_hashlongstr(ts));
}
case LUA_VFALSE:
@@ -161,26 +171,25 @@ static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
case LUA_VTRUE:
return hashboolean(t, 1);
case LUA_VLIGHTUSERDATA: {
- void *p = pvalueraw(*kvl);
+ void *p = pvalue(key);
return hashpointer(t, p);
}
case LUA_VLCF: {
- lua_CFunction f = fvalueraw(*kvl);
+ lua_CFunction f = fvalue(key);
return hashpointer(t, f);
}
default: {
- GCObject *o = gcvalueraw(*kvl);
+ GCObject *o = gcvalue(key);
return hashpointer(t, o);
}
}
}
-/*
-** Returns the main position of an element given as a 'TValue'
-*/
-static Node *mainpositionTV (const Table *t, const TValue *key) {
- return mainposition(t, rawtt(key), valraw(key));
+l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) {
+ TValue key;
+ getnodekey(cast(lua_State *, NULL), &key, nd);
+ return mainpositionTV(t, &key);
}
@@ -679,7 +688,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
return;
}
lua_assert(!isdummy(t));
- othern = mainposition(t, keytt(mp), &keyval(mp));
+ othern = mainpositionfromnode(t, mp);
if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
while (othern + gnext(othern) != mp) /* find previous */