aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-11-05 16:34:37 +0000
committergingerBill <bill@gingerbill.org>2021-11-05 16:34:37 +0000
commite95204908a12d4386ba9bda6de1fed7c73f66d29 (patch)
tree633e2b4e1b9c8498235004c23cd9cd157d748bdd /src
parente963fc4d6a2b8fc63f46bb57b2c727999ce39e29 (diff)
Add `PtrMap`, begin working change `Map` to `PtrMap` where possible
Diffstat (limited to 'src')
-rw-r--r--src/checker.cpp15
-rw-r--r--src/checker.hpp2
-rw-r--r--src/common.cpp1
-rw-r--r--src/ptr_map.cpp318
4 files changed, 326 insertions, 10 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index 125893d11..643673afe 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -1135,8 +1135,7 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) {
mutex_lock(&info->type_info_mutex);
isize entry_index = -1;
- HashKey key = hash_type(type);
- isize *found_entry_index = map_get(&info->type_info_map, key);
+ isize *found_entry_index = map_get(&info->type_info_map, type);
if (found_entry_index) {
entry_index = *found_entry_index;
}
@@ -1145,11 +1144,10 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) {
// TODO(bill): This is O(n) and can be very slow
for_array(i, info->type_info_map.entries){
auto *e = &info->type_info_map.entries[i];
- Type *prev_type = cast(Type *)cast(uintptr)e->key.key;
- if (are_types_identical(prev_type, type)) {
+ if (are_types_identical(e->key, type)) {
entry_index = e->value;
// NOTE(bill): Add it to the search map
- map_set(&info->type_info_map, key, entry_index);
+ map_set(&info->type_info_map, type, entry_index);
break;
}
}
@@ -1484,7 +1482,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
add_type_info_dependency(c->decl, t);
- auto found = map_get(&c->info->type_info_map, hash_type(t));
+ auto found = map_get(&c->info->type_info_map, t);
if (found != nullptr) {
// Types have already been added
return;
@@ -1494,8 +1492,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
isize ti_index = -1;
for_array(i, c->info->type_info_map.entries) {
auto *e = &c->info->type_info_map.entries[i];
- Type *prev_type = cast(Type *)cast(uintptr)e->key.key;
- if (are_types_identical(t, prev_type)) {
+ if (are_types_identical(t, e->key)) {
// Duplicate entry
ti_index = e->value;
prev = true;
@@ -1508,7 +1505,7 @@ 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(&c->checker->info.type_info_map, hash_type(t), ti_index);
+ 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/checker.hpp b/src/checker.hpp
index c65d766ba..e7f152eb2 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -321,7 +321,7 @@ struct CheckerInfo {
BlockingMutex type_info_mutex; // NOT recursive
Array<Type *> type_info_types;
- Map<isize> type_info_map; // Key: Type *
+ PtrMap<Type *, isize> type_info_map;
BlockingMutex foreign_mutex; // NOT recursive
StringMap<Entity *> foreigns;
diff --git a/src/common.cpp b/src/common.cpp
index 7af7026b9..5d7c87b6d 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -277,6 +277,7 @@ gb_global bool global_module_path_set = false;
#include "string_map.cpp"
#include "map.cpp"
+#include "ptr_map.cpp"
#include "ptr_set.cpp"
#include "string_set.cpp"
#include "priority_queue.cpp"
diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp
new file mode 100644
index 000000000..af3cf86f9
--- /dev/null
+++ b/src/ptr_map.cpp
@@ -0,0 +1,318 @@
+#define PTR_MAP_ENABLE_MULTI_MAP 1
+
+
+template <typename K, typename V>
+struct PtrMapEntry {
+ static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size");
+
+ u32 hash;
+ MapIndex next;
+ K key;
+ V value;
+};
+
+template <typename K, typename V>
+struct PtrMap {
+ Slice<MapIndex> hashes;
+ Array<PtrMapEntry<K, V> > entries;
+};
+
+
+template <typename K>
+u32 ptr_map_hash_key(K key) {
+ return gb_fnv32a(&key, gb_size_of(key));
+}
+
+template <typename K, typename V> void map_init (PtrMap<K, V> *h, gbAllocator a, isize capacity = 16);
+template <typename K, typename V> void map_destroy (PtrMap<K, V> *h);
+template <typename K, typename V> V * map_get (PtrMap<K, V> *h, K key);
+template <typename K, typename V> void map_set (PtrMap<K, V> *h, K key, V const &value);
+template <typename K, typename V> void map_remove (PtrMap<K, V> *h, K key);
+template <typename K, typename V> void map_clear (PtrMap<K, V> *h);
+template <typename K, typename V> void map_grow (PtrMap<K, V> *h);
+template <typename K, typename V> void map_rehash (PtrMap<K, V> *h, isize new_count);
+template <typename K, typename V> void map_reserve (PtrMap<K, V> *h, isize cap);
+
+#if PTR_MAP_ENABLE_MULTI_MAP
+// Mutlivalued map procedure
+template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key);
+template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e);
+
+template <typename K, typename V> isize multi_map_count (PtrMap<K, V> *h, K key);
+template <typename K, typename V> void multi_map_get_all (PtrMap<K, V> *h, K key, V *items);
+template <typename K, typename V> void multi_map_insert (PtrMap<K, V> *h, K key, V const &value);
+template <typename K, typename V> void multi_map_remove (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e);
+template <typename K, typename V> void multi_map_remove_all(PtrMap<K, V> *h, K key);
+#endif
+
+template <typename K, typename V>
+gb_inline void map_init(PtrMap<K, V> *h, gbAllocator a, isize capacity) {
+ capacity = next_pow2_isize(capacity);
+ slice_init(&h->hashes, a, capacity);
+ array_init(&h->entries, a, 0, capacity);
+ for (isize i = 0; i < capacity; i++) {
+ h->hashes.data[i] = MAP_SENTINEL;
+ }
+}
+
+template <typename K, typename V>
+gb_inline void map_destroy(PtrMap<K, V> *h) {
+ slice_free(&h->hashes, h->entries.allocator);
+ array_free(&h->entries);
+}
+
+template <typename K, typename V>
+gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) {
+ PtrMapEntry<K, V> e = {};
+ e.hash = ptr_map_hash_key(key);
+ e.key = key;
+ e.next = MAP_SENTINEL;
+ array_add(&h->entries, e);
+ return cast(MapIndex)(h->entries.count-1);
+}
+
+template <typename K, typename V>
+gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) {
+ MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
+ if (h->hashes.count == 0) {
+ return fr;
+ }
+ u32 hash = ptr_map_hash_key(key);
+ fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1));
+ fr.entry_index = h->hashes.data[fr.hash_index];
+ while (fr.entry_index != MAP_SENTINEL) {
+ if (h->entries.data[fr.entry_index].key == key) {
+ return fr;
+ }
+ fr.entry_prev = fr.entry_index;
+ fr.entry_index = h->entries.data[fr.entry_index].next;
+ }
+ return fr;
+}
+
+template <typename K, typename V>
+gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
+ MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
+ if (h->hashes.count == 0) {
+ return fr;
+ }
+ fr.hash_index = cast(MapIndex)(e->hash & (h->hashes.count-1));
+ fr.entry_index = h->hashes.data[fr.hash_index];
+ while (fr.entry_index != MAP_SENTINEL) {
+ if (&h->entries.data[fr.entry_index] == e) {
+ return fr;
+ }
+ fr.entry_prev = fr.entry_index;
+ fr.entry_index = h->entries.data[fr.entry_index].next;
+ }
+ return fr;
+}
+
+template <typename K, typename V>
+gb_internal b32 map__full(PtrMap<K, V> *h) {
+ return 0.75f * h->hashes.count <= h->entries.count;
+}
+
+template <typename K, typename V>
+gb_inline void map_grow(PtrMap<K, V> *h) {
+ isize new_count = gb_max(h->hashes.count<<1, 16);
+ map_rehash(h, new_count);
+}
+
+template <typename K, typename V>
+void map_reset_entries(PtrMap<K, V> *h) {
+ for (isize i = 0; i < h->hashes.count; i++) {
+ h->hashes.data[i] = MAP_SENTINEL;
+ }
+ for (isize i = 0; i < h->entries.count; i++) {
+ MapFindResult fr;
+ PtrMapEntry<K, V> *e = &h->entries.data[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;
+ }
+ }
+}
+
+template <typename K, typename V>
+void map_reserve(PtrMap<K, V> *h, isize cap) {
+ array_reserve(&h->entries, cap);
+ if (h->entries.count*2 < h->hashes.count) {
+ return;
+ }
+ slice_resize(&h->hashes, h->entries.allocator, cap*2);
+ map_reset_entries(h);
+}
+
+
+template <typename K, typename V>
+void map_rehash(PtrMap<K, V> *h, isize new_count) {
+ map_reserve(h, new_count);
+}
+
+template <typename K, typename V>
+V *map_get(PtrMap<K, V> *h, K key) {
+ isize index = map__find(h, key).entry_index;
+ if (index != MAP_SENTINEL) {
+ return &h->entries.data[index].value;
+ }
+ return nullptr;
+}
+
+template <typename K, typename V>
+V &map_must_get(PtrMap<K, V> *h, K key) {
+ isize index = map__find(h, key).entry_index;
+ GB_ASSERT(index != MAP_SENTINEL);
+ return h->entries.data[index].value;
+}
+
+template <typename K, typename V>
+void map_set(PtrMap<K, V> *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.data[fr.entry_prev].next = index;
+ } else {
+ h->hashes.data[fr.hash_index] = index;
+ }
+ }
+ h->entries.data[index].value = value;
+
+ if (map__full(h)) {
+ map_grow(h);
+ }
+}
+
+
+template <typename K, typename V>
+void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) {
+ MapFindResult last;
+ if (fr.entry_prev == MAP_SENTINEL) {
+ h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next;
+ } else {
+ h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next;
+ }
+ if (fr.entry_index == h->entries.count-1) {
+ array_pop(&h->entries);
+ return;
+ }
+ h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
+ array_pop(&h->entries);
+
+ last = map__find(h, h->entries.data[fr.entry_index].key);
+ if (last.entry_prev != MAP_SENTINEL) {
+ h->entries.data[last.entry_prev].next = fr.entry_index;
+ } else {
+ h->hashes.data[last.hash_index] = fr.entry_index;
+ }
+}
+
+template <typename K, typename V>
+void map_remove(PtrMap<K, V> *h, HashKey const &key) {
+ MapFindResult fr = map__find(h, key);
+ if (fr.entry_index != MAP_SENTINEL) {
+ map__erase(h, fr);
+ }
+}
+
+template <typename K, typename V>
+gb_inline void map_clear(PtrMap<K, V> *h) {
+ array_clear(&h->entries);
+ for (isize i = 0; i < h->hashes.count; i++) {
+ h->hashes.data[i] = MAP_SENTINEL;
+ }
+}
+
+
+#if PTR_MAP_ENABLE_MULTI_MAP
+template <typename K, typename V>
+PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, HashKey const &key) {
+ isize i = map__find(h, key).entry_index;
+ if (i == MAP_SENTINEL) {
+ return nullptr;
+ }
+ return &h->entries.data[i];
+}
+
+template <typename K, typename V>
+PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
+ isize i = e->next;
+ while (i != MAP_SENTINEL) {
+ if (hash_key_equal(h->entries.data[i].key, e->key)) {
+ return &h->entries.data[i];
+ }
+ i = h->entries.data[i].next;
+ }
+ return nullptr;
+}
+
+template <typename K, typename V>
+isize multi_map_count(PtrMap<K, V> *h, HashKey const &key) {
+ isize count = 0;
+ PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
+ while (e != nullptr) {
+ count++;
+ e = multi_map_find_next(h, e);
+ }
+ return count;
+}
+
+template <typename K, typename V>
+void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) {
+ isize i = 0;
+ PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
+ while (e != nullptr) {
+ items[i++] = e->value;
+ e = multi_map_find_next(h, e);
+ }
+}
+
+template <typename K, typename V>
+void multi_map_insert(PtrMap<K, V> *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.data[fr.hash_index] = i;
+ } else {
+ h->entries.data[fr.entry_prev].next = i;
+ }
+ h->entries.data[i].next = fr.entry_index;
+ h->entries.data[i].value = value;
+ // Grow if needed
+ if (map__full(h)) {
+ map_grow(h);
+ }
+}
+
+template <typename K, typename V>
+void multi_map_remove(PtrMap<K, V> *h, HashKey const &key, PtrMapEntry<K, V> *e) {
+ MapFindResult fr = map__find_from_entry(h, e);
+ if (fr.entry_index != MAP_SENTINEL) {
+ map__erase(h, fr);
+ }
+}
+
+template <typename K, typename V>
+void multi_map_remove_all(PtrMap<K, V> *h, HashKey const &key) {
+ while (map_get(h, key) != nullptr) {
+ map_remove(h, key);
+ }
+}
+#endif