diff --git a/core/mem/raw.odin b/core/mem/raw.odin index c4c5182e6..99712e9e5 100644 --- a/core/mem/raw.odin +++ b/core/mem/raw.odin @@ -58,3 +58,14 @@ raw_dynamic_array_data :: proc(a: $T/[dynamic]$E) -> ^E { raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data}; +Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) { + hash: uintptr, + next: int, + key: Key, + value: Value, +} + +Poly_Raw_Map :: struct($Key, $Value: typeid) { + hashes: []int, + entries: [dynamic]Poly_Raw_Map_Entry(Key, Value), +} \ No newline at end of file diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index 9a90800c4..88e769056 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -523,6 +523,15 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller return true; } +@builtin +map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) { + key, value := key, value; + h := __get_map_header(m); + hash := __get_map_hash(&key); + + data := uintptr(__dynamic_map_set(h, hash, &value, loc)); + return (^V)(data + h.value_offset); +} @builtin diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 8bb8975b6..6e54ba441 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -193,27 +193,28 @@ __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller } __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check { - new_header: Map_Header = header; - nm := Raw_Map{}; - nm.entries.allocator = m.entries.allocator; - nm.hashes = m.hashes; - new_header.m = &nm; - c := context; if m.entries.allocator.procedure != nil { c.allocator = m.entries.allocator; } context = c; + + nm := Raw_Map{}; + nm.entries.allocator = m.entries.allocator; + nm.hashes = m.hashes; + + new_header: Map_Header = header; + new_header.m = &nm; new_count := new_count; new_count = max(new_count, 2*m.entries.len); - __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc); __slice_resize(&nm.hashes, new_count, m.entries.allocator, loc); for i in 0 ..< new_count { nm.hashes[i] = -1; } + __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc); for i in 0 ..< m.entries.len { if len(nm.hashes) == 0 { __dynamic_map_grow(new_header, loc); @@ -253,7 +254,7 @@ __dynamic_map_get :: proc(h: Map_Header, hash: Map_Hash) -> rawptr { return nil; } -__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) #no_bounds_check { +__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check { index: int; assert(value != nil); @@ -277,7 +278,7 @@ __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := # e := __dynamic_map_get_entry(h, index); e.hash = hash.hash; - + key := rawptr(uintptr(e) + h.key_offset); mem_copy(key, hash.key_ptr, h.key_size); @@ -286,7 +287,11 @@ __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := # if __dynamic_map_full(h) { __dynamic_map_grow(h, loc); + index = __dynamic_map_find(h, hash).entry_index; + assert(index >= 0); } + + return __dynamic_map_get_entry(h, index); } @@ -297,7 +302,7 @@ __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) { } __dynamic_map_full :: #force_inline proc "contextless" (using h: Map_Header) -> bool { - return int(0.75 * f64(len(m.hashes))) <= m.entries.cap; + return int(0.75 * f64(len(m.hashes))) <= m.entries.len; }