Browse Source

Type caching

gingerBill 7 years ago
parent
commit
2e1e1e6034
4 changed files with 114 additions and 18 deletions
  1. 5 5
      src/check_expr.cpp
  2. 1 0
      src/main.cpp
  3. 2 2
      src/map.cpp
  4. 106 11
      src/types.cpp

+ 5 - 5
src/check_expr.cpp

@@ -782,21 +782,21 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
 		if (source->kind == Type_Array) {
 		if (source->kind == Type_Array) {
 
 
 			// IMPORTANT TODO(bill): Which is correct?
 			// IMPORTANT TODO(bill): Which is correct?
-			// if (poly->Array.generic_type != nullptr && modify_type) {
-			if (poly->Array.generic_type != nullptr) {
-				Type *gt = poly->Array.generic_type;
+			// if (poly->Array.generic_count != nullptr && modify_type) {
+			if (poly->Array.generic_count != nullptr) {
+				Type *gt = poly->Array.generic_count;
 				GB_ASSERT(gt->kind == Type_Generic);
 				GB_ASSERT(gt->kind == Type_Generic);
 				Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
 				Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
 				GB_ASSERT(e != nullptr);
 				GB_ASSERT(e != nullptr);
 				if (e->kind == Entity_TypeName) {
 				if (e->kind == Entity_TypeName) {
-					poly->Array.generic_type = nullptr;
+					poly->Array.generic_count = nullptr;
 					poly->Array.count = source->Array.count;
 					poly->Array.count = source->Array.count;
 
 
 					e->kind = Entity_Constant;
 					e->kind = Entity_Constant;
 					e->Constant.value = exact_value_i64(source->Array.count);
 					e->Constant.value = exact_value_i64(source->Array.count);
 					e->type = t_untyped_integer;
 					e->type = t_untyped_integer;
 				} else if (e->kind == Entity_Constant) {
 				} else if (e->kind == Entity_Constant) {
-					poly->Array.generic_type = nullptr;
+					poly->Array.generic_count = nullptr;
 					if (e->Constant.value.kind != ExactValue_Integer) {
 					if (e->Constant.value.kind != ExactValue_Integer) {
 						return false;
 						return false;
 					}
 					}

+ 1 - 0
src/main.cpp

@@ -698,6 +698,7 @@ int main(int arg_count, char **arg_ptr) {
 	init_string_buffer_memory();
 	init_string_buffer_memory();
 	init_scratch_memory(gb_megabytes(10));
 	init_scratch_memory(gb_megabytes(10));
 	init_global_error_collector();
 	init_global_error_collector();
+	init_cached_type_maps();
 
 
 	array_init(&library_collections, heap_allocator());
 	array_init(&library_collections, heap_allocator());
 	// NOTE(bill): 'core' cannot be (re)defined by the user
 	// NOTE(bill): 'core' cannot be (re)defined by the user

+ 2 - 2
src/map.cpp

@@ -22,7 +22,7 @@ enum HashKeyKind {
 
 
 struct PtrAndId {
 struct PtrAndId {
 	void *ptr;
 	void *ptr;
-	u32   id;
+	u64   id;
 };
 };
 
 
 struct HashKey {
 struct HashKey {
@@ -58,7 +58,7 @@ gb_inline HashKey hash_pointer(void *ptr) {
 	h.ptr = ptr;
 	h.ptr = ptr;
 	return h;
 	return h;
 }
 }
-gb_inline HashKey hash_ptr_and_id(void *ptr, u32 id) {
+gb_inline HashKey hash_ptr_and_id(void *ptr, u64 id) {
 	HashKey h = {HashKey_PtrAndId};
 	HashKey h = {HashKey_PtrAndId};
 	h.key = cast(u64)cast(uintptr)ptr;
 	h.key = cast(u64)cast(uintptr)ptr;
 	h.ptr_and_id.ptr = ptr;
 	h.ptr_and_id.ptr = ptr;

+ 106 - 11
src/types.cpp

@@ -114,7 +114,7 @@ struct TypeStruct {
 	TYPE_KIND(Array,   struct {                           \
 	TYPE_KIND(Array,   struct {                           \
 		Type *elem;                                       \
 		Type *elem;                                       \
 		i64   count;                                      \
 		i64   count;                                      \
-		Type *generic_type;                               \
+		Type *generic_count;                              \
 	})                                                    \
 	})                                                    \
 	TYPE_KIND(Slice,   struct { Type *elem; })            \
 	TYPE_KIND(Slice,   struct { Type *elem; })            \
 	TYPE_KIND(DynamicArray, struct { Type *elem; })       \
 	TYPE_KIND(DynamicArray, struct { Type *elem; })       \
@@ -408,6 +408,67 @@ gb_global Type *t_map_header                  = nullptr;
 
 
 
 
 
 
+/*
+	NOTE(bill): This caching system is to reduce allocation clutter - inspired by Per Vogensen's Bitwise
+ */
+enum CachedTypeKind {
+	CachedType_Invalid,
+
+	CachedType_Pointer,
+	CachedType_Array,
+	CachedType_Slice,
+	CachedType_DynamicArray,
+	CachedType_Map,
+
+	CachedType_COUNT
+};
+
+struct CachedType {
+	CachedTypeKind kind;
+	Type *type;
+};
+
+HashKey hash_cache_type_elem(Type *elem) {
+	return hash_ptr_and_id(elem, 0);
+}
+HashKey hash_cache_type_array(Type *elem, i64 count) {
+	return hash_ptr_and_id(elem, cast(u64)count);
+}
+HashKey hash_cache_type_map(Type *key, Type *value) {
+	u64 v = cast(u64)cast(uintptr)value;
+	return hash_ptr_and_id(key, v);
+}
+
+
+// Key: elem/elem+count/key+value
+gb_global Map<CachedType> cached_type_maps[CachedType_COUNT] = {};
+
+void init_cached_type_maps() {
+	for (isize i = 1; i < CachedType_COUNT; i++) {
+		map_init(&cached_type_maps[i], heap_allocator());
+	}
+}
+
+
+CachedType *find_cached_type(CachedTypeKind kind, HashKey key) {
+	GB_ASSERT(key.kind == HashKey_PtrAndId);
+	if (key.ptr_and_id.ptr == nullptr) {
+		return nullptr;
+	}
+	auto *m = &cached_type_maps[kind];
+	return map_get(m, key);
+}
+
+void add_cached_type(CachedTypeKind kind, HashKey key, Type *type) {
+	GB_ASSERT(key.kind == HashKey_PtrAndId);
+	if (key.ptr_and_id.ptr == nullptr) {
+		return;
+	}
+	CachedType ct = {};
+	ct.kind = kind;
+	ct.type = type;
+	map_set(&cached_type_maps[kind], key, ct);
+}
 
 
 
 
 i64      type_size_of               (Type *t);
 i64      type_size_of               (Type *t);
@@ -493,28 +554,56 @@ Type *alloc_type_generic(Scope *scope, i64 id, String name, Type *specialized) {
 }
 }
 
 
 Type *alloc_type_pointer(Type *elem) {
 Type *alloc_type_pointer(Type *elem) {
+	auto hkey = hash_cache_type_elem(elem);
+	if (auto found = find_cached_type(CachedType_Pointer, hkey)) {
+		return found->type;
+	}
+
 	Type *t = alloc_type(Type_Pointer);
 	Type *t = alloc_type(Type_Pointer);
 	t->Pointer.elem = elem;
 	t->Pointer.elem = elem;
+
+	add_cached_type(CachedType_Pointer, hkey, t);
 	return t;
 	return t;
 }
 }
 
 
-Type *alloc_type_array(Type *elem, i64 count, Type *generic_type = nullptr) {
+Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = nullptr) {
+	if (generic_count != nullptr) {
+		Type *t = alloc_type(Type_Array);
+		t->Array.elem = elem;
+		t->Array.count = count;
+		t->Array.generic_count = generic_count;
+		return t;
+	}
+	auto hkey = hash_cache_type_array(elem, count);
+	if (auto found = find_cached_type(CachedType_Array, hkey)) {
+		return found->type;
+	}
 	Type *t = alloc_type(Type_Array);
 	Type *t = alloc_type(Type_Array);
 	t->Array.elem = elem;
 	t->Array.elem = elem;
 	t->Array.count = count;
 	t->Array.count = count;
-	t->Array.generic_type = generic_type;
-	return t;
-}
-
-Type *alloc_type_dynamic_array(Type *elem) {
-	Type *t = alloc_type(Type_DynamicArray);
-	t->DynamicArray.elem = elem;
+	add_cached_type(CachedType_Array, hkey, t);
 	return t;
 	return t;
 }
 }
 
 
 Type *alloc_type_slice(Type *elem) {
 Type *alloc_type_slice(Type *elem) {
+	auto hkey = hash_cache_type_elem(elem);
+	if (auto found = find_cached_type(CachedType_Slice, hkey)) {
+		return found->type;
+	}
 	Type *t = alloc_type(Type_Slice);
 	Type *t = alloc_type(Type_Slice);
 	t->Array.elem = elem;
 	t->Array.elem = elem;
+	add_cached_type(CachedType_Slice, hkey, t);
+	return t;
+}
+
+Type *alloc_type_dynamic_array(Type *elem) {
+	auto hkey = hash_cache_type_elem(elem);
+	if (auto found = find_cached_type(CachedType_DynamicArray, hkey)) {
+		return found->type;
+	}
+	Type *t = alloc_type(Type_DynamicArray);
+	t->DynamicArray.elem = elem;
+	add_cached_type(CachedType_DynamicArray, hkey, t);
 	return t;
 	return t;
 }
 }
 
 
@@ -579,12 +668,18 @@ Type *alloc_type_proc(Scope *scope, Type *params, isize param_count, Type *resul
 bool is_type_valid_for_keys(Type *t);
 bool is_type_valid_for_keys(Type *t);
 
 
 Type *alloc_type_map(i64 count, Type *key, Type *value) {
 Type *alloc_type_map(i64 count, Type *key, Type *value) {
-	Type *t = alloc_type(Type_Map);
 	if (key != nullptr) {
 	if (key != nullptr) {
 		GB_ASSERT(is_type_valid_for_keys(key));
 		GB_ASSERT(is_type_valid_for_keys(key));
+		GB_ASSERT(value != nullptr);
 	}
 	}
+	auto hkey = hash_cache_type_map(key, value);
+	if (auto found = find_cached_type(CachedType_Map, hkey)) {
+		return found->type;
+	}
+	Type *t = alloc_type(Type_Map);
 	t->Map.key   = key;
 	t->Map.key   = key;
 	t->Map.value = value;
 	t->Map.value = value;
+	add_cached_type(CachedType_Map, hkey, t);
 	return t;
 	return t;
 }
 }
 
 
@@ -993,7 +1088,7 @@ bool is_type_polymorphic(Type *t) {
 	case Type_Pointer:
 	case Type_Pointer:
 		return is_type_polymorphic(t->Pointer.elem);
 		return is_type_polymorphic(t->Pointer.elem);
 	case Type_Array:
 	case Type_Array:
-		if (t->Array.generic_type != nullptr) {
+		if (t->Array.generic_count != nullptr) {
 			return true;
 			return true;
 		}
 		}
 		return is_type_polymorphic(t->Array.elem);
 		return is_type_polymorphic(t->Array.elem);