mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +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
|
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) {
|
if map_hash_is_deleted(element_hash) {
|
||||||
k_dst := map_cell_index_dynamic(ks, info.ks, p)
|
k_dst := map_cell_index_dynamic(ks, info.ks, p)
|
||||||
v_dst := map_cell_index_dynamic(vs, info.vs, 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)
|
intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
|
||||||
hp^ = h
|
hp^ = h
|
||||||
return result if result != 0 else v_dst
|
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 {
|
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")
|
@(optimization_mode="size")
|
||||||
map_grow_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
|
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 {
|
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
|
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 {
|
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)
|
MASK :: 1 << (size_of(Map_Hash)*8 - 1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user