diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b893b3a00..06d0a8b12 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8079,11 +8079,10 @@ gb_internal void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Op } uintptr key = hash_exact_value(operand.value); - TypeAndToken *found = map_get(seen, key); - if (found != nullptr) { + GB_ASSERT(key != 0); + isize count = multi_map_count(seen, key); + if (count) { TEMPORARY_ALLOCATOR_GUARD(); - - isize count = multi_map_count(seen, key); TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count); multi_map_get_all(seen, key, taps); @@ -9406,7 +9405,8 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * continue; } ExactValue v = f->Constant.value; - auto found = map_get(&seen, hash_exact_value(v)); + uintptr hash = hash_exact_value(v); + auto found = map_get(&seen, hash); if (!found) { array_add(&unhandled, f); } diff --git a/src/checker.cpp b/src/checker.cpp index 3b51cc6e0..64fca0312 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1897,8 +1897,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_dependency(c->info, c->decl, t); MUTEX_GUARD_BLOCK(&c->info->type_info_mutex) { - MapFindResult fr; - auto found = map_try_get(&c->info->type_info_map, t, &fr); + auto found = map_get(&c->info->type_info_map, t); if (found != nullptr) { // Types have already been added return; @@ -1922,7 +1921,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); } - map_set_internal_from_try_get(&c->checker->info.type_info_map, t, ti_index, fr); + map_set(&c->checker->info.type_info_map, t, ti_index); if (prev) { // NOTE(bill): If a previous one exists already, no need to continue diff --git a/src/exact_value.cpp b/src/exact_value.cpp index b744d2db0..83af82f55 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -54,37 +54,50 @@ gb_global ExactValue const empty_exact_value = {}; gb_internal uintptr hash_exact_value(ExactValue v) { mutex_lock(&hash_exact_value_mutex); defer (mutex_unlock(&hash_exact_value_mutex)); + + uintptr res = 0; switch (v.kind) { case ExactValue_Invalid: return 0; case ExactValue_Bool: - return gb_fnv32a(&v.value_bool, gb_size_of(v.value_bool)); + res = gb_fnv32a(&v.value_bool, gb_size_of(v.value_bool)); + break; case ExactValue_String: - return gb_fnv32a(v.value_string.text, v.value_string.len); + res = gb_fnv32a(v.value_string.text, v.value_string.len); + break; case ExactValue_Integer: { u32 key = gb_fnv32a(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); u8 last = (u8)v.value_integer.sign; - return (key ^ last) * 0x01000193; + res = (key ^ last) * 0x01000193; + break; } case ExactValue_Float: - return gb_fnv32a(&v.value_float, gb_size_of(v.value_float)); + res = gb_fnv32a(&v.value_float, gb_size_of(v.value_float)); + break; case ExactValue_Pointer: - return ptr_map_hash_key(v.value_pointer); + res = ptr_map_hash_key(v.value_pointer); + break; case ExactValue_Complex: - return gb_fnv32a(v.value_complex, gb_size_of(Complex128)); + res = gb_fnv32a(v.value_complex, gb_size_of(Complex128)); + break; case ExactValue_Quaternion: - return gb_fnv32a(v.value_quaternion, gb_size_of(Quaternion256)); + res = gb_fnv32a(v.value_quaternion, gb_size_of(Quaternion256)); + break; case ExactValue_Compound: - return ptr_map_hash_key(v.value_compound); + res = ptr_map_hash_key(v.value_compound); + break; case ExactValue_Procedure: - return ptr_map_hash_key(v.value_procedure); + res = ptr_map_hash_key(v.value_procedure); + break; case ExactValue_Typeid: - return ptr_map_hash_key(v.value_typeid); + res = ptr_map_hash_key(v.value_typeid); + break; + default: + res = gb_fnv32a(&v, gb_size_of(ExactValue)); } - return gb_fnv32a(&v, gb_size_of(ExactValue)); - + return res & 0x7fffffff; } diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 23278014f..8fd627768 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -16,23 +16,21 @@ struct MapFindResult { }; enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; +static void *const MAP_TOMBSTONE = (void *)~(uintptr)0; template struct PtrMapEntry { static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); - K key; - V value; - MapIndex next; + K key; + V value; }; template struct PtrMap { - MapIndex * hashes; - usize hashes_count; PtrMapEntry *entries; u32 count; - u32 entries_capacity; + u32 capacity; }; @@ -69,7 +67,6 @@ template gb_internal void map_grow (PtrMap< template gb_internal void map_rehash (PtrMap *h, isize new_count); template gb_internal void map_reserve (PtrMap *h, isize cap); -#if PTR_MAP_ENABLE_MULTI_MAP // Mutlivalued map procedure template gb_internal PtrMapEntry * multi_map_find_first(PtrMap *h, K key); template gb_internal PtrMapEntry * multi_map_find_next (PtrMap *h, PtrMapEntry *e); @@ -79,7 +76,6 @@ template gb_internal void multi_map_get_all (PtrMap< template gb_internal void multi_map_insert (PtrMap *h, K key, V const &value); template gb_internal void multi_map_remove (PtrMap *h, K key, PtrMapEntry *e); template gb_internal void multi_map_remove_all(PtrMap *h, K key); -#endif gb_internal gbAllocator map_allocator(void) { return heap_allocator(); @@ -94,170 +90,141 @@ gb_internal gb_inline void map_init(PtrMap *h, isize capacity) { template gb_internal gb_inline void map_destroy(PtrMap *h) { gbAllocator a = map_allocator(); - gb_free(a, h->hashes); gb_free(a, h->entries); } -template -gb_internal void map__resize_hashes(PtrMap *h, usize count) { - h->hashes_count = cast(u32)resize_array_raw(&h->hashes, map_allocator(), h->hashes_count, count, MAP_CACHE_LINE_SIZE); -} template -gb_internal void map__reserve_entries(PtrMap *h, usize capacity) { - h->entries_capacity = cast(u32)resize_array_raw(&h->entries, map_allocator(), h->entries_capacity, capacity, MAP_CACHE_LINE_SIZE); -} - - -template -gb_internal MapIndex map__add_entry(PtrMap *h, K key) { - PtrMapEntry e = {}; - e.key = key; - e.next = MAP_SENTINEL; - if (h->count+1 >= h->entries_capacity) { - map__reserve_entries(h, gb_max(h->entries_capacity*2, 4)); - } - h->entries[h->count++] = e; - return cast(MapIndex)(h->count-1); -} - -template -gb_internal MapFindResult map__find(PtrMap *h, K key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count == 0) { - return fr; +gb_internal void map__insert(PtrMap *h, K key, V const &value) { + if (h->count+1 >= h->capacity) { + map_grow(h); } u32 hash = ptr_map_hash_key(key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->key == key) { - return fr; + u32 mask = h->capacity-1; + MapIndex index = hash & mask; + MapIndex original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key || entry->key == cast(K)MAP_TOMBSTONE) { + entry->key = key; + entry->value = value; + h->count += 1; + return; } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; - } - return fr; -} + index = (index+1)&mask; + } while (index != original_index); -template -gb_internal MapFindResult map__find_from_entry(PtrMap *h, PtrMapEntry *e) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count == 0) { - return fr; - } - u32 hash = ptr_map_hash_key(e->key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (&h->entries[fr.entry_index] == e) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries[fr.entry_index].next; - } - return fr; + GB_PANIC("FAILED TO INSERT"); } template gb_internal b32 map__full(PtrMap *h) { - return 0.75f * h->hashes_count <= h->count; + return 0.75f * h->capacity <= h->count; } template gb_internal gb_inline void map_grow(PtrMap *h) { - isize new_count = gb_max(h->hashes_count<<1, 16); - map_rehash(h, new_count); + isize new_capacity = gb_max(h->capacity<<1, 16); + map_reserve(h, new_capacity); } template -gb_internal void map_reset_entries(PtrMap *h) { - for (usize i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } - for (usize i = 0; i < h->count; i++) { - MapFindResult fr; - PtrMapEntry *e = &h->entries[i]; - e->next = MAP_SENTINEL; - fr = map__find_from_entry(h, e); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(MapIndex)i; - } else { - h->entries[fr.entry_prev].next = cast(MapIndex)i; - } +gb_internal void try_map_grow(PtrMap *h) { + if (h->capacity == 0 || map__full(h)) { + map_grow(h); } } + template gb_internal void map_reserve(PtrMap *h, isize cap) { - if (h->count*2 < h->hashes_count) { + if (cap < h->capacity) { return; } - map__reserve_entries(h, cap); - map__resize_hashes(h, cap*2); - map_reset_entries(h); -} + cap = next_pow2_isize(cap); + typedef PtrMapEntry EntryType; + PtrMap new_h = {}; + new_h.count = 0; + new_h.capacity = cast(u32)cap; + new_h.entries = gb_alloc_array(string_map_allocator(), EntryType, new_h.capacity); -template -gb_internal void map_rehash(PtrMap *h, isize new_count) { - map_reserve(h, new_count); + if (h->count) { + for (u32 i = 0; i < h->capacity; i++) { + auto *entry = h->entries+i; + if (entry->key && + entry->key != cast(K)MAP_TOMBSTONE) { + map__insert(&new_h, entry->key, entry->value); + } + } + } + map_destroy(h); + *h = new_h; } template gb_internal V *map_get(PtrMap *h, K key) { - MapIndex hash_index = MAP_SENTINEL; - MapIndex entry_prev = MAP_SENTINEL; - MapIndex entry_index = MAP_SENTINEL; - if (h->hashes_count != 0) { - u32 hash = ptr_map_hash_key(key); - hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - entry_index = h->hashes[hash_index]; - while (entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[entry_index]; - if (entry->key == key) { - return &entry->value; - } - entry_prev = entry_index; - entry_index = entry->next; - } + if (h->count == 0) { + return nullptr; } + if (key == 0) { + GB_PANIC("0 key"); + } + + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); return nullptr; } template -gb_internal V *map_try_get(PtrMap *h, K key, MapFindResult *fr_) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count != 0) { - u32 hash = ptr_map_hash_key(key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->key == key) { - return &entry->value; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; +gb_internal V *map_try_get(PtrMap *h, K key, MapIndex *found_index_) { + if (found_index_) *found_index_ = ~(MapIndex)0; + + if (h->count == 0) { + return nullptr; + } + if (key == 0) { + GB_PANIC("0 key"); + } + + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + if (found_index_) *found_index_ = index; + return &entry->value; } - } - if (h->hashes_count == 0 || map__full(h)) { - map_grow(h); - } - if (fr_) *fr_ = fr; + index = (index+1) & mask; + } while (original_index != index); return nullptr; } template -gb_internal void map_set_internal_from_try_get(PtrMap *h, K key, V const &value, MapFindResult const &fr) { - MapIndex index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; +gb_internal void map_set_internal_from_try_get(PtrMap *h, K key, V const &value, MapIndex found_index) { + if (found_index != MAP_SENTINEL) { + GB_ASSERT(h->entries[found_index].key == key); + h->entries[found_index].value = value; } else { - h->hashes[fr.hash_index] = index; + map_set(h, key, value); } - h->entries[index].value = value; } template @@ -269,116 +236,83 @@ gb_internal V &map_must_get(PtrMap *h, K key) { template gb_internal void map_set(PtrMap *h, K key, V const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes_count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - index = fr.entry_index; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; - } else { - h->hashes[fr.hash_index] = index; - } - } - h->entries[index].value = value; - - if (map__full(h)) { - map_grow(h); + GB_ASSERT(key != 0); + try_map_grow(h); + auto *found = map_get(h, key); + if (found) { + *found = value; + return; } + map__insert(h, key, value); } // returns true if it previously existed template gb_internal bool map_set_if_not_previously_exists(PtrMap *h, K key, V const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes_count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { + try_map_grow(h); + auto *found = map_get(h, key); + if (found) { return true; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; - } else { - h->hashes[fr.hash_index] = index; - } - } - h->entries[index].value = value; - - if (map__full(h)) { - map_grow(h); } + map__insert(h, key, value); return false; } -template -gb_internal void map__erase(PtrMap *h, MapFindResult const &fr) { - MapFindResult last; - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; - } else { - h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; - } - if (fr.entry_index == h->count-1) { - h->count--; - return; - } - h->entries[fr.entry_index] = h->entries[h->count-1]; - h->count--; - - last = map__find(h, h->entries[fr.entry_index].key); - if (last.entry_prev != MAP_SENTINEL) { - h->entries[last.entry_prev].next = fr.entry_index; - } else { - h->hashes[last.hash_index] = fr.entry_index; - } -} - template gb_internal void map_remove(PtrMap *h, K key) { - MapFindResult fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); + MapIndex found_index = 0; + if (map_try_get(h, key, &found_index)) { + h->entries[found_index].key = cast(K)MAP_TOMBSTONE; + h->count -= 1; } } template gb_internal gb_inline void map_clear(PtrMap *h) { h->count = 0; - for (usize i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } + gb_zero_array(h->entries, h->capacity); } #if PTR_MAP_ENABLE_MULTI_MAP template gb_internal PtrMapEntry *multi_map_find_first(PtrMap *h, K key) { - MapIndex i = map__find(h, key).entry_index; - if (i == MAP_SENTINEL) { + if (h->count == 0) { return nullptr; } - return &h->entries[i]; + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + return entry; + } + index = (index+1) & mask; + } while (original_index != index); + return nullptr; } template gb_internal PtrMapEntry *multi_map_find_next(PtrMap *h, PtrMapEntry *e) { - MapIndex i = e->next; - while (i != MAP_SENTINEL) { - if (h->entries[i].key == e->key) { - return &h->entries[i]; + u32 mask = h->capacity-1; + MapIndex index = cast(MapIndex)(e - h->entries); + MapIndex original_index = index; + do { + index = (index+1)&mask; + auto *entry = h->entries+index; + if (!entry->key) { + return nullptr; } - i = h->entries[i].next; - } + if (entry->key == e->key) { + return entry; + } + } while (original_index != index); return nullptr; } @@ -405,34 +339,16 @@ gb_internal void multi_map_get_all(PtrMap *h, K key, V *items) { template gb_internal void multi_map_insert(PtrMap *h, K key, V const &value) { - MapFindResult fr; - MapIndex i; - if (h->hashes_count == 0) { - map_grow(h); - } - // Make - fr = map__find(h, key); - i = map__add_entry(h, key); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = i; - } else { - h->entries[fr.entry_prev].next = i; - } - h->entries[i].next = fr.entry_index; - h->entries[i].value = value; - // Grow if needed - if (map__full(h)) { - map_grow(h); - } + try_map_grow(h); + map__insert(h, key, value); } -template -gb_internal void multi_map_remove(PtrMap *h, K key, PtrMapEntry *e) { - MapFindResult fr = map__find_from_entry(h, e); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} +// template +// gb_internal void multi_map_remove(PtrMap *h, K key, PtrMapEntry *e) { +// if (fr.entry_index != MAP_SENTINEL) { +// map__erase(h, fr); +// } +// } template gb_internal void multi_map_remove_all(PtrMap *h, K key) { @@ -443,22 +359,77 @@ gb_internal void multi_map_remove_all(PtrMap *h, K key) { #endif -template -gb_internal PtrMapEntry *begin(PtrMap &m) { - return m.entries; -} -template -gb_internal PtrMapEntry const *begin(PtrMap const &m) { - return m.entries; -} template -gb_internal PtrMapEntry *end(PtrMap &m) { - return m.entries + m.count; +struct PtrMapIterator { + PtrMap *map; + MapIndex index; + + PtrMapIterator &operator++() noexcept { + for (;;) { + ++index; + if (map->capacity == index) { + return *this; + } + PtrMapEntry *entry = map->entries+index; + if (entry->key && entry->key != cast(K)MAP_TOMBSTONE) { + return *this; + } + } + } + + bool operator==(PtrMapIterator const &other) const noexcept { + return this->map == other->map && this->index == other->index; + } + + operator PtrMapEntry *() const { + return map->entries+index; + } +}; + + +template +gb_internal PtrMapIterator end(PtrMap &m) noexcept { + return PtrMapIterator{&m, m.capacity}; } template -gb_internal PtrMapEntry const *end(PtrMap const &m) { - return m.entries + m.count; +gb_internal PtrMapIterator const end(PtrMap const &m) noexcept { + return PtrMapIterator{&m, m.capacity}; +} + + + +template +gb_internal PtrMapIterator begin(PtrMap &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + auto key = m.entries[index].key; + if (key && key != cast(K)MAP_TOMBSTONE) { + break; + } + index++; + } + return PtrMapIterator{&m, index}; +} +template +gb_internal PtrMapIterator const begin(PtrMap const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + auto key = m.entries[index].key; + if (key && key != cast(K)MAP_TOMBSTONE) { + break; + } + index++; + } + return PtrMapIterator{&m, index}; }