Browse Source

Correct `map_insert_hash_dynamic` and `map_insert_dynamic`

gingerBill 2 years ago
parent
commit
667af1be58
1 changed files with 5 additions and 88 deletions
  1. 5 88
      core/runtime/dynamic_map_internal.odin

+ 5 - 88
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)