mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 04:38:16 +00:00
Type caching
This commit is contained in:
+5
-5
@@ -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_count != nullptr && modify_type) {
|
||||||
if (poly->Array.generic_type != nullptr) {
|
if (poly->Array.generic_count != nullptr) {
|
||||||
Type *gt = poly->Array.generic_type;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
add_cached_type(CachedType_Array, hkey, t);
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *alloc_type_dynamic_array(Type *elem) {
|
|
||||||
Type *t = alloc_type(Type_DynamicArray);
|
|
||||||
t->DynamicArray.elem = elem;
|
|
||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user