diff options
| author | gingerBill <bill@gingerbill.org> | 2018-03-23 16:35:41 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-03-23 16:35:41 +0000 |
| commit | 2e1e1e6034152fa83a05b7fb47e75eefe758ca62 (patch) | |
| tree | e178a798c89f9a0ef012dee31a64da8a3827c232 /src/types.cpp | |
| parent | 991479fbf921ab04b921bbb8163e5522f78feb3c (diff) | |
Type caching
Diffstat (limited to 'src/types.cpp')
| -rw-r--r-- | src/types.cpp | 117 |
1 files changed, 106 insertions, 11 deletions
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<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); @@ -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); |