summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/jit/x86/instr_map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/jit/x86/instr_map.cpp')
-rw-r--r--erts/emulator/beam/jit/x86/instr_map.cpp92
1 files changed, 52 insertions, 40 deletions
diff --git a/erts/emulator/beam/jit/x86/instr_map.cpp b/erts/emulator/beam/jit/x86/instr_map.cpp
index 679b2a6609..5f89077ba6 100644
--- a/erts/emulator/beam/jit/x86/instr_map.cpp
+++ b/erts/emulator/beam/jit/x86/instr_map.cpp
@@ -30,13 +30,11 @@ extern "C"
}
static const Uint32 INTERNAL_HASH_SALT = 3432918353;
-static const Uint32 HCONST_22 = 0x98C475E6UL;
static const Uint32 HCONST = 0x9E3779B9;
-/* ARG3 = incoming hash
+/*
* ARG4 = lower 32
* ARG5 = upper 32
- * ARG6 = type constant
*
* Helper function for calculating the internal hash of keys before looking
* them up in a map.
@@ -47,15 +45,16 @@ static const Uint32 HCONST = 0x9E3779B9;
*
* Result is returned in ARG3. */
void BeamGlobalAssembler::emit_internal_hash_helper() {
- x86::Gp hash = ARG3d, lower = ARG4d, upper = ARG5d, constant = ARG6d;
+ x86::Gp hash = ARG3d, lower = ARG4d, upper = ARG5d;
- a.add(lower, constant);
- a.add(upper, constant);
+ a.mov(hash, imm(INTERNAL_HASH_SALT));
+ a.add(lower, imm(HCONST));
+ a.add(upper, imm(HCONST));
#if defined(ERL_INTERNAL_HASH_CRC32C)
- a.mov(constant, hash);
+ a.mov(ARG6d, hash);
a.crc32(hash, lower);
- a.add(hash, constant);
+ a.add(hash, ARG6d);
a.crc32(hash, upper);
#else
using rounds =
@@ -88,6 +87,23 @@ void BeamGlobalAssembler::emit_internal_hash_helper() {
}
#endif
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+ a.mov(TMP_MEM1q, ARG1);
+ a.mov(TMP_MEM2q, ARG2);
+ a.mov(TMP_MEM3q, RET);
+
+ a.mov(ARG1, ARG3);
+ emit_enter_runtime();
+ runtime_call<2>(erts_dbg_hashmap_collision_bonanza);
+ emit_leave_runtime();
+
+ a.mov(ARG3d, RETd);
+
+ a.mov(ARG1, TMP_MEM1q);
+ a.mov(ARG2, TMP_MEM2q);
+ a.mov(RET, TMP_MEM3q);
+#endif
+
a.ret();
}
@@ -109,8 +125,9 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.bind(node_loop);
{
- Label fail = a.newLabel(), leaf_node = a.newLabel(),
- skip_index_adjustment = a.newLabel(), update_hash = a.newLabel();
+ Label done = a.newLabel(), leaf_node = a.newLabel(),
+ skip_index_adjustment = a.newLabel(),
+ collision_node = a.newLabel();
/* Find out which child we should follow, and shift the hash for the
* next round. */
@@ -131,7 +148,7 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
* Note that we jump directly to a `RET` instruction, as `BT` only
* affects CF, and ZF ("not found") is clear at this point. */
a.bt(header_val, index);
- a.short_().jnc(fail);
+ a.short_().jnc(done);
/* The actual offset of our entry is the number of bits set (in
* essence "entries present") before our index in the bitmap. */
@@ -154,11 +171,11 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
/* Nope, we have to search another node. */
a.mov(header_val, emit_boxed_val(node, 0, sizeof(Uint32)));
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * need to update the hash to keep going. */
- a.test(depth, imm(0x7));
- a.short_().jz(update_hash);
- a.short_().jmp(node_loop);
+ /* After 8 nodes we've run out of the 32 bits we started with
+ * and we end up in a collision node. */
+ a.test(depth, imm(HAMT_MAX_LEVEL - 1));
+ a.short_().jnz(node_loop);
+ a.short_().jmp(collision_node);
a.bind(leaf_node);
{
@@ -168,36 +185,33 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.mov(RET, getCDRRef(node));
/* See comment at the jump. */
- a.bind(fail);
+ a.bind(done);
a.ret();
}
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * must calculate a new hash to continue.
- *
- * This is a manual expansion `make_map_hash` from utils.c, and all
- * changes to that function must be mirrored here. */
- a.bind(update_hash);
+ /* A collision node is a tuple of leafs where we do linear search.*/
+ a.bind(collision_node);
{
- a.mov(TMP_MEM1d, depth);
+ Label linear_loop = a.newLabel();
- /* NOTE: ARG3d is always 0 at this point. */
- a.mov(ARG4d, depth);
- a.shr(ARG4d, imm(3));
- mov_imm(ARG5d, 1);
- a.mov(ARG6d, imm(HCONST_22));
- a.call(labels[internal_hash_helper]);
+ a.shr(header_val, imm(_HEADER_ARITY_OFFS));
+ a.lea(ARG6d, x86::qword_ptr(header_val, -1));
- a.xor_(ARG3d, imm(INTERNAL_HASH_SALT));
- a.mov(ARG4d, key.r32());
- a.mov(ARG5, key);
- a.shr(ARG5, imm(32));
- a.mov(ARG6d, imm(HCONST));
- a.call(labels[internal_hash_helper]);
+ a.bind(linear_loop);
+ {
+ a.mov(ARG3,
+ x86::qword_ptr(node, ARG6, 3, 8 - TAG_PRIMARY_BOXED));
- a.mov(depth, TMP_MEM1d);
+ emit_ptr_val(ARG3, ARG3);
+ a.cmp(key, getCARRef(ARG3));
+ a.mov(RET, getCDRRef(ARG3));
+ a.short_().jz(done);
- a.jmp(node_loop);
+ a.dec(ARG6d);
+ a.short_().jns(linear_loop);
+ }
+
+ a.ret();
}
}
}
@@ -381,8 +395,6 @@ void BeamGlobalAssembler::emit_i_get_map_element_shared() {
a.shr(ARG5, imm(32));
a.mov(ARG4d, ARG2d);
- a.mov(ARG3d, imm(INTERNAL_HASH_SALT));
- a.mov(ARG6d, imm(HCONST));
a.call(labels[internal_hash_helper]);
emit_hashmap_get_element();