From 2e1e1e6034152fa83a05b7fb47e75eefe758ca62 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 23 Mar 2018 16:35:41 +0000 Subject: [PATCH] Type caching --- src/check_expr.cpp | 10 ++-- src/main.cpp | 1 + src/map.cpp | 4 +- src/types.cpp | 117 ++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d5c39690e..4996d7853 100644 --- a/src/check_expr.cpp +++ b/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) { // 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); Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name); GB_ASSERT(e != nullptr); if (e->kind == Entity_TypeName) { - poly->Array.generic_type = nullptr; + poly->Array.generic_count = nullptr; poly->Array.count = source->Array.count; e->kind = Entity_Constant; e->Constant.value = exact_value_i64(source->Array.count); e->type = t_untyped_integer; } else if (e->kind == Entity_Constant) { - poly->Array.generic_type = nullptr; + poly->Array.generic_count = nullptr; if (e->Constant.value.kind != ExactValue_Integer) { return false; } diff --git a/src/main.cpp b/src/main.cpp index 5a9f57ade..c1999e766 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -698,6 +698,7 @@ int main(int arg_count, char **arg_ptr) { init_string_buffer_memory(); init_scratch_memory(gb_megabytes(10)); init_global_error_collector(); + init_cached_type_maps(); array_init(&library_collections, heap_allocator()); // NOTE(bill): 'core' cannot be (re)defined by the user diff --git a/src/map.cpp b/src/map.cpp index abc42231f..aa4152696 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -22,7 +22,7 @@ enum HashKeyKind { struct PtrAndId { void *ptr; - u32 id; + u64 id; }; struct HashKey { @@ -58,7 +58,7 @@ gb_inline HashKey hash_pointer(void *ptr) { h.ptr = ptr; 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}; h.key = cast(u64)cast(uintptr)ptr; h.ptr_and_id.ptr = ptr; diff --git a/src/types.cpp b/src/types.cpp index 309dfd29c..7ff1517be 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -114,7 +114,7 @@ struct TypeStruct { TYPE_KIND(Array, struct { \ Type *elem; \ i64 count; \ - Type *generic_type; \ + Type *generic_count; \ }) \ TYPE_KIND(Slice, 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 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); @@ -493,28 +554,56 @@ Type *alloc_type_generic(Scope *scope, i64 id, String name, Type *specialized) { } 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); t->Pointer.elem = elem; + + add_cached_type(CachedType_Pointer, hkey, 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); t->Array.elem = elem; 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; } 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); 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; } @@ -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); Type *alloc_type_map(i64 count, Type *key, Type *value) { - Type *t = alloc_type(Type_Map); if (key != nullptr) { 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.value = value; + add_cached_type(CachedType_Map, hkey, t); return t; } @@ -993,7 +1088,7 @@ bool is_type_polymorphic(Type *t) { case Type_Pointer: return is_type_polymorphic(t->Pointer.elem); case Type_Array: - if (t->Array.generic_type != nullptr) { + if (t->Array.generic_count != nullptr) { return true; } return is_type_polymorphic(t->Array.elem);