aboutsummaryrefslogtreecommitdiff
path: root/base/runtime/dynamic_map_internal.odin
diff options
context:
space:
mode:
Diffstat (limited to 'base/runtime/dynamic_map_internal.odin')
-rw-r--r--base/runtime/dynamic_map_internal.odin45
1 files changed, 34 insertions, 11 deletions
diff --git a/base/runtime/dynamic_map_internal.odin b/base/runtime/dynamic_map_internal.odin
index 3dded7716..b95e3cd14 100644
--- a/base/runtime/dynamic_map_internal.odin
+++ b/base/runtime/dynamic_map_internal.odin
@@ -158,21 +158,21 @@ map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T
} else when (N & (N - 1)) == 0 && N <= 8*size_of(uintptr) {
// Likely case, N is a power of two because T is a power of two.
+ // Unique case, no need to index data here since only one element.
+ when N == 1 {
+ return &cells[index].data[0]
+ }
+
// Compute the integer log 2 of N, this is the shift amount to index the
// correct cell. Odin's intrinsics.count_leading_zeros does not produce a
// constant, hence this approach. We only need to check up to N = 64.
- SHIFT :: 1 when N < 2 else
- 2 when N < 4 else
- 3 when N < 8 else
- 4 when N < 16 else
- 5 when N < 32 else 6
+ SHIFT :: 1 when N == 2 else
+ 2 when N == 4 else
+ 3 when N == 8 else
+ 4 when N == 16 else
+ 5 when N == 32 else 6
#assert(SHIFT <= MAP_CACHE_LINE_LOG2)
- // Unique case, no need to index data here since only one element.
- when N == 1 {
- return &cells[index >> SHIFT].data[0]
- } else {
- return &cells[index >> SHIFT].data[index & (N - 1)]
- }
+ return &cells[index >> SHIFT].data[index & (N - 1)]
} else {
// Least likely (and worst case), we pay for a division operation but we
// assume the compiler does not actually generate a division. N will be in the
@@ -941,6 +941,29 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
return nil, rawptr(result)
}
+__dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr, zero: rawptr, loc := #caller_location) -> (key_ptr: rawptr, value_ptr: rawptr, just_inserted: bool, err: Allocator_Error) {
+ hash := info.key_hasher(key, map_seed(m^))
+
+ if key_ptr, value_ptr = __dynamic_map_get_key_and_value(m, info, hash, key); value_ptr != nil {
+ return
+ }
+
+ has_grown: bool
+ if err, has_grown = __dynamic_map_check_grow(m, info, loc); err != nil {
+ return
+ } else if has_grown {
+ 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)))
+
+ m.len += 1
+ just_inserted = true
+ return
+}
+
// IMPORTANT: USED WITHIN THE COMPILER
@(private)