Do an extra check before insertion for pre-existing keys

This is test code
This commit is contained in:
gingerBill
2022-11-08 21:10:38 +00:00
parent 667af1be58
commit 503eb470a7

View File

@@ -354,12 +354,27 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc
// 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) {
p := map_desired_position(m, h)
d := uintptr(0)
c := (uintptr(1) << map_log2_cap(m)) - 1 // Saturating arithmetic mask
pos := map_desired_position(m, h)
distance := uintptr(0)
mask := (uintptr(1) << map_log2_cap(m)) - 1 // Saturating arithmetic mask
ks, vs, hs, sk, sv := map_kvh_data_dynamic(m, info)
get_loop: for {
element_hash := hs[pos]
if map_hash_is_empty(element_hash) {
break get_loop
} else if distance > map_probe_distance(m, element_hash, pos) {
break get_loop
} else if element_hash == h && info.key_equal(rawptr(ik), rawptr(map_cell_index_dynamic(ks, info.ks, pos))) {
result = map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(result), rawptr(iv), info.ks.size_of_type)
return
}
pos = (pos + 1) & mask
distance += 1
}
// Avoid redundant loads of these values
size_of_k := info.ks.size_of_type
size_of_v := info.vs.size_of_type
@@ -381,38 +396,38 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
tv := map_cell_index_dynamic_const(sv, info.vs, 1)
for {
hp := &hs[p]
hp := &hs[pos]
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)
k_dst := map_cell_index_dynamic(ks, info.ks, pos)
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
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 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, pos); pd <= distance {
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)
k_dst := map_cell_index_dynamic(ks, info.ks, pos)
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
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 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)
} else if element_hash == h && info.key_equal(rawptr(k), rawptr(map_cell_index_dynamic(ks, info.ks, pos))) {
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(iv), info.vs.size_of_type)
return v_dst
}
if result == 0 {
result = map_cell_index_dynamic(vs, info.vs, p)
result = map_cell_index_dynamic(vs, info.vs, pos)
}
kp := map_cell_index_dynamic(ks, info.vs, p)
vp := map_cell_index_dynamic(vs, info.ks, p)
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
//
@@ -427,11 +442,11 @@ map_insert_hash_dynamic :: proc "odin" (m: Raw_Map, #no_alias info: ^Map_Info, h
intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(tv), size_of_v)
hp^, h = h, hp^
d = pd
distance = pd
}
p = (p + 1) & c
d += 1
pos = (pos + 1) & mask
distance += 1
}
}