فهرست منبع

fix map_entry sometimes giving wrong key pointer

`map_desired_position` does not return the actual position, probing must
be done afterwards to figure out the real position. `map_entry` did not
do this for the returned key pointer so it could point to the wrong key
if probing was done.
Laytan Laats 7 ماه پیش
والد
کامیت
4de5911a15
1فایلهای تغییر یافته به همراه27 افزوده شده و 10 حذف شده
  1. 27 10
      base/runtime/dynamic_map_internal.odin

+ 27 - 10
base/runtime/dynamic_map_internal.odin

@@ -400,7 +400,7 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc
 // This procedure returns the address of the just inserted value, and will
 // return 'nil' if there was no room to insert the entry
 @(require_results)
-map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
+map_insert_hash_dynamic_with_key :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (key: uintptr, result: uintptr) {
 	h        := h
 	pos      := map_desired_position(m^, h)
 	distance := uintptr(0)
@@ -436,7 +436,11 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 			intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
 			hs[pos] = h
 
-			return result if result != 0 else v_dst
+			if result == 0 {
+				key    = k_dst
+				result = v_dst
+			}
+			return
 		}
 
 		if map_hash_is_deleted(element_hash) {
@@ -444,13 +448,14 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 		}
 
 		if probe_distance := map_probe_distance(m^, element_hash, pos); distance > probe_distance {
-			if result == 0 {
-				result = map_cell_index_dynamic(vs, info.vs, pos)
-			}
-
 			kp := map_cell_index_dynamic(ks, info.ks, pos)
 			vp := map_cell_index_dynamic(vs, info.vs, pos)
 
+			if result == 0 {
+				key    = kp
+				result = vp
+			}
+
 			intrinsics.mem_copy_non_overlapping(rawptr(tk), rawptr(k), size_of_k)
 			intrinsics.mem_copy_non_overlapping(rawptr(k),  rawptr(kp), size_of_k)
 			intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(tk), size_of_k)
@@ -491,7 +496,11 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 			intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
 			hs[pos] = h
 
-			return result if result != 0 else v_dst
+			if result == 0 {
+				key    = k_dst
+				result = v_dst
+			}
+			return
 		}
 
 		k_src := map_cell_index_dynamic(ks, info.ks, la_pos)
@@ -501,6 +510,7 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 		if probe_distance < look_ahead {
 			// probed can be made ideal while placing saved (ending condition)
 			if result == 0 {
+				key    = k_dst
 				result = v_dst
 			}
 			intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
@@ -550,6 +560,7 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 		} else {
 			// place saved, save probed
 			if result == 0 {
+				key    = k_dst
 				result = v_dst
 			}
 			intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
@@ -568,6 +579,12 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 	}
 }
 
+@(require_results)
+map_insert_hash_dynamic :: #force_inline proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
+	_, result = map_insert_hash_dynamic_with_key(m, info, h, ik, iv)
+	return
+}
+
 @(require_results)
 map_grow_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
 	log2_capacity := map_log2_cap(m^)
@@ -955,9 +972,9 @@ __dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_
 		hash = info.key_hasher(key, map_seed(m^))
 	}
 
-	value_ptr = rawptr(map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(zero)))
-	assert(value_ptr != nil)
-	key_ptr = rawptr(map_cell_index_dynamic(map_data(m^), info.ks, map_desired_position(m^, hash)))
+	kp, vp := map_insert_hash_dynamic_with_key(m, info, hash, uintptr(key), uintptr(zero))
+	key_ptr   = rawptr(kp)
+	value_ptr = rawptr(vp)
 
 	m.len += 1
 	just_inserted = true