aboutsummaryrefslogtreecommitdiff
path: root/core/runtime
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-11-08 20:44:52 +0000
committergingerBill <bill@gingerbill.org>2022-11-08 20:44:52 +0000
commit667af1be586bc64229c2a3f61ab9d59636f0c5fc (patch)
tree1a1225c50ce1f7c6dfc488e1832bdadb971a15d9 /core/runtime
parent366779f8c7c7f9e522e890151df1becadbe20aba (diff)
Correct `map_insert_hash_dynamic` and `map_insert_dynamic`
Diffstat (limited to 'core/runtime')
-rw-r--r--core/runtime/dynamic_map_internal.odin93
1 files changed, 5 insertions, 88 deletions
diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin
index 351acb88a..e56dd5bb2 100644
--- a/core/runtime/dynamic_map_internal.odin
+++ b/core/runtime/dynamic_map_internal.odin
@@ -393,7 +393,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, p); pd < d {
+ if pd := map_probe_distance(m, element_hash, p); pd <= d {
if map_hash_is_deleted(element_hash) {
k_dst := map_cell_index_dynamic(ks, info.ks, p)
v_dst := map_cell_index_dynamic(vs, info.vs, p)
@@ -401,6 +401,10 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
hp^ = h
return result if result != 0 else v_dst
+ } else if element_hash == h && info.key_equal(rawptr(k), rawptr(map_cell_index_dynamic(ks, info.ks, p))) {
+ v_dst := map_cell_index_dynamic(vs, info.vs, p)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(iv), info.vs.size_of_type)
+ return v_dst
}
if result == 0 {
@@ -431,82 +435,6 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
}
}
-@(optimization_mode="speed")
-map_add_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) {
- capacity := uintptr(1) << map_log2_cap(m)
- p := map_desired_position(m, h)
- d := uintptr(0)
- c := capacity - 1 // Saturating arithmetic mask
-
- ks, vs, hs, sk, sv := map_kvh_data_dynamic(m, info)
-
- // 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)
- 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)
-
- for {
- hp := &hs[p]
- element_hash := hp^
-
- if map_hash_is_empty(element_hash) {
- k_dst := map_cell_index_dynamic(ks, info.ks, p)
- v_dst := map_cell_index_dynamic(vs, info.vs, p)
- intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
- hp^ = h
- return
- }
-
- if pd := map_probe_distance(m, element_hash, p); pd < d {
- if map_hash_is_deleted(element_hash) {
- k_dst := map_cell_index_dynamic(ks, info.ks, p)
- v_dst := map_cell_index_dynamic(vs, info.vs, p)
- intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
- hp^ = h
- return
- }
-
- kp := map_cell_index_dynamic(ks, info.vs, p)
- vp := map_cell_index_dynamic(vs, info.ks, p)
-
- // 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^
-
- d = pd
- }
-
- p = (p + 1) & c
- d += 1
- }
-}
-
@(optimization_mode="size")
map_grow_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
if m.allocator.procedure == nil {
@@ -729,17 +657,6 @@ map_insert_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_I
return
}
-// Same as map_insert_dynamic but does not return address to the inserted element.
-@(optimization_mode="speed")
-map_add_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k, v: uintptr, loc := #caller_location) -> Allocator_Error {
- if map_len(m^) + 1 >= map_resize_threshold(m^) {
- map_grow_dynamic(m, info, loc) or_return
- }
- map_add_hash_dynamic(m^, info, info.key_hasher(rawptr(k), 0), k, v)
- m.len += 1
- return nil
-}
-
map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> bool {
MASK :: 1 << (size_of(Map_Hash)*8 - 1)