summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-04-05 14:53:37 -0400
committergit <svn-admin@ruby-lang.org>2024-04-05 19:24:04 +0000
commit1953ead74e0ceaea83a874ae3ec0001289375247 (patch)
treee6049cfbdcc7dfe2a777fd4581c12737bf8a364b
parenta801889c580663dde984afa2c27811a8d2438597 (diff)
[ruby/prism] Use a simpler and faster hash function for locals
https://github.com/ruby/prism/commit/5f56bf4464
-rw-r--r--prism/prism.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/prism/prism.c b/prism/prism.c
index 3ac298dcb0..d47cf204a7 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -805,17 +805,15 @@ pm_locals_free(pm_locals_t *locals) {
}
/**
- * Use the mid-square method to hash the given constant id.
+ * Use as simple and fast a hash function as we can that still properly mixes
+ * the bits.
*/
static uint32_t
pm_locals_hash(pm_constant_id_t name) {
- uint64_t square = (uint64_t) name * (uint64_t) name;
-
- uint32_t num_digits = (uint32_t) floor(log10((double) square) + 1);
- uint32_t start = num_digits / 2;
- uint32_t end = start + 1;
-
- return (uint32_t) (((uint64_t) ((square / ((uint64_t) pow(10, (double) start)))) % (uint64_t) pow(10, (double) end)));
+ name = ((name >> 16) ^ name) * 0x45d9f3b;
+ name = ((name >> 16) ^ name) * 0x45d9f3b;
+ name = (name >> 16) ^ name;
+ return name;
}
/**
@@ -837,15 +835,16 @@ pm_locals_resize(pm_locals_t *locals) {
} else {
// If we just switched from a list to a hash, then we need to fill in
// the hash values of all of the locals.
- bool hash_needed = locals->locals[0].hash == 0;
+ bool hash_needed = (locals->capacity <= PM_LOCALS_HASH_THRESHOLD);
uint32_t mask = next_capacity - 1;
for (uint32_t index = 0; index < locals->capacity; index++) {
pm_local_t *local = &locals->locals[index];
if (local->name != PM_CONSTANT_ID_UNSET) {
- uint32_t hash = hash_needed ? pm_locals_hash(local->name) : local->hash;
+ if (hash_needed) local->hash = pm_locals_hash(local->name);
+ uint32_t hash = local->hash;
while (next_locals[hash & mask].name != PM_CONSTANT_ID_UNSET) hash++;
next_locals[hash & mask] = *local;
}
@@ -908,7 +907,7 @@ pm_locals_write(pm_locals_t *locals, pm_constant_id_t name, const uint8_t *start
.name = name,
.index = locals->size++,
.reads = reads,
- .hash = hash
+ .hash = initial_hash
};
return true;
} else if (local->name == name) {
@@ -920,6 +919,7 @@ pm_locals_write(pm_locals_t *locals, pm_constant_id_t name, const uint8_t *start
}
assert(false && "unreachable");
+ return true;
}
/**