From 27130259cc0e9aaffed13ed7515b05ffd5e1e9cb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 6 Dec 2022 19:55:17 +0000 Subject: [PATCH] Coalesce tombstones on `delete_key` to reduce all map slots from being filled on insertion This is a bodge and will need to be replaced with an actual solution involving backward shift deletion rather than relying on tombstone slots in the first place. --- core/runtime/dynamic_map_internal.odin | 57 ++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index c23baab60..0afe05f1c 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -230,6 +230,8 @@ map_data :: #force_inline proc "contextless" (m: Raw_Map) -> uintptr { Map_Hash :: uintptr +TOMBSTONE_MASK :: 1<<(size_of(Map_Hash)*8 - 1) + // Procedure to check if a slot is empty for a given hash. This is represented // by the zero value to make the zero value useful. This is a procedure just // for prose reasons. @@ -241,14 +243,12 @@ map_hash_is_empty :: #force_inline proc "contextless" (hash: Map_Hash) -> bool { @(require_results) map_hash_is_deleted :: #force_no_inline proc "contextless" (hash: Map_Hash) -> bool { // The MSB indicates a tombstone - N :: size_of(Map_Hash)*8 - 1 - return hash >> N != 0 + return hash & TOMBSTONE_MASK != 0 } @(require_results) map_hash_is_valid :: #force_inline proc "contextless" (hash: Map_Hash) -> bool { // The MSB indicates a tombstone - N :: size_of(Map_Hash)*8 - 1 - return (hash != 0) & (hash >> N == 0) + return (hash != 0) & (hash & TOMBSTONE_MASK == 0) } @@ -627,15 +627,58 @@ map_exists_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, @(require_results) map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (old_k, old_v: uintptr, ok: bool) { - MASK :: 1 << (size_of(Map_Hash)*8 - 1) - index := map_lookup_dynamic(m^, info, k) or_return ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info) - hs[index] |= MASK + hs[index] |= TOMBSTONE_MASK old_k = map_cell_index_dynamic(ks, info.ks, index) old_v = map_cell_index_dynamic(vs, info.vs, index) m.len -= 1 ok = true + + { // coalesce tombstones + // HACK NOTE(bill): This is an ugly bodge but it is coalescing the tombstone slots + // TODO(bill): we should do backward shift deletion and not rely on tombstone slots + mask := (uintptr(1)<