Sfoglia il codice sorgente

Add `PtrMap`, begin working change `Map` to `PtrMap` where possible

gingerBill 3 anni fa
parent
commit
e95204908a
4 ha cambiato i file con 326 aggiunte e 10 eliminazioni
  1. 6 9
      src/checker.cpp
  2. 1 1
      src/checker.hpp
  3. 1 0
      src/common.cpp
  4. 318 0
      src/ptr_map.cpp

+ 6 - 9
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

+ 1 - 1
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;

+ 1 - 0
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"

+ 318 - 0
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