aboutsummaryrefslogtreecommitdiff
path: root/core/runtime
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-11-09 21:00:17 +0000
committergingerBill <bill@gingerbill.org>2022-11-09 21:00:17 +0000
commit0424fb486b8fee2c0853724cd3336239509b35f7 (patch)
treeb976a45d70ce6f2e25b893c2374bcd8f93939f7d /core/runtime
parent3858422f1d9c607736b2b911a3a27678d77afed5 (diff)
Rewrite `map_insert_hash_dynamic`
Diffstat (limited to 'core/runtime')
-rw-r--r--core/runtime/dynamic_map_internal.odin66
1 files changed, 28 insertions, 38 deletions
diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin
index 632fe9d4a..bf0154a77 100644
--- a/core/runtime/dynamic_map_internal.odin
+++ b/core/runtime/dynamic_map_internal.odin
@@ -345,40 +345,35 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc
return
}
-// When the type information is known we should use map_insert_hash_static for
-// better performance. This procedure has to stack allocate storage to store
-// local keys during the Robin Hood hashing technique where elements are swapped
-// in the backing arrays to reduce variance. This swapping can only be done with
-// memcpy since there is no type information.
+// This procedure has to stack allocate storage to store local keys during the
+// Robin Hood hashing technique where elements are swapped in the backing
+// arrays to reduce variance. This swapping can only be done with memcpy since
+// there is no type information.
//
// This procedure returns the address of the just inserted value.
@(optimization_mode="speed")
map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
- pos := map_desired_position(m, h)
+ pos := map_desired_position(m, h)
distance := uintptr(0)
- mask := (uintptr(1) << map_log2_cap(m)) - 1 // Saturating arithmetic mask
+ mask := (uintptr(1) << map_log2_cap(m)) - 1
ks, vs, hs, sk, sv := map_kvh_data_dynamic(m, info)
+ _, _ = sk, sv
// Avoid redundant loads of these values
size_of_k := info.ks.size_of_type
size_of_v := info.vs.size_of_type
- // Use sk and sv scratch storage space for dynamic k and v storage here.
- //
- // Simulate the following at runtime
- // k = ik
- // v = iv
- // h = h
- k := map_cell_index_dynamic_const(sk, info.ks, 0)
- v := map_cell_index_dynamic_const(sv, info.vs, 0)
+ k := map_cell_index_dynamic(sk, info.ks, 0)
+ v := map_cell_index_dynamic(sv, info.vs, 0)
intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(ik), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(iv), size_of_v)
- h := h
// Temporary k and v dynamic storage for swap below
- tk := map_cell_index_dynamic_const(sk, info.ks, 1)
- tv := map_cell_index_dynamic_const(sv, info.vs, 1)
+ tk := map_cell_index_dynamic(sk, info.ks, 1)
+ tv := map_cell_index_dynamic(sv, info.vs, 1)
+
+ h := h
for {
hp := &hs[pos]
@@ -393,7 +388,7 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
return result if result != 0 else v_dst
}
- if pd := map_probe_distance(m, element_hash, pos); pd <= distance {
+ if probe_distance := map_probe_distance(m, element_hash, pos); probe_distance < distance {
if map_hash_is_deleted(element_hash) {
k_dst := map_cell_index_dynamic(ks, info.ks, pos)
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
@@ -407,23 +402,18 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
result = map_cell_index_dynamic(vs, info.vs, pos)
}
- kp := map_cell_index_dynamic(ks, info.vs, pos)
- vp := map_cell_index_dynamic(vs, info.ks, pos)
-
- // Simulate the following at runtime with dynamic storage
- //
- // kp^, k = k, kp^
- // vp^, v = v, vp^
- // hp^, h = h, hp^
- intrinsics.mem_copy_non_overlapping(rawptr(tk), rawptr(kp), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(tv), rawptr(vp), size_of_v)
- intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
- intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(tk), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(tv), size_of_v)
- hp^, h = h, hp^
-
- distance = pd
+ kp := map_cell_index_dynamic(ks, info.ks, pos)
+ vp := map_cell_index_dynamic(vs, info.vs, pos)
+
+ intrinsics.mem_copy_non_overlapping(rawptr(tk), rawptr(k), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(kp), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(tk), size_of_k)
+
+ intrinsics.mem_copy_non_overlapping(rawptr(tv), rawptr(v), size_of_v)
+ intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(vp), size_of_v)
+ intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(tv), size_of_v)
+
+ distance = probe_distance
}
pos = (pos + 1) & mask
@@ -741,8 +731,8 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In
return nil
}
}
- hashed := info.key_hasher(key, 0)
- result := map_insert_hash_dynamic(m^, info, hashed, uintptr(key), uintptr(value))
+ hash := info.key_hasher(key, 0)
+ result := map_insert_hash_dynamic(m^, info, hash, uintptr(key), uintptr(value))
m.len += 1
return rawptr(result)
}