mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-07 13:33:13 +00:00
Correct map_insert_hash_dynamic and map_insert_dynamic
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user