diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index e56dd5bb2..df3d09375 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -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 } }