Browse Source

Split header table data and the map pointer

gingerBill 2 years ago
parent
commit
1d793ea338
4 changed files with 130 additions and 119 deletions
  1. 90 84
      core/runtime/dynamic_map_internal.odin
  2. 5 16
      src/checker.cpp
  3. 34 19
      src/llvm_backend.cpp
  4. 1 0
      src/types.cpp

+ 90 - 84
core/runtime/dynamic_map_internal.odin

@@ -38,8 +38,7 @@ Map_Entry_Header :: struct {
 */
 */
 }
 }
 
 
-Map_Header :: struct {
-	m:             ^Raw_Map,
+Map_Header_Table :: struct {
 	equal:         Equal_Proc,
 	equal:         Equal_Proc,
 
 
 	entry_size:    int,
 	entry_size:    int,
@@ -52,6 +51,95 @@ Map_Header :: struct {
 	value_size:    int,
 	value_size:    int,
 }
 }
 
 
+Map_Header :: struct {
+	m: ^Raw_Map,
+	using header_table: Map_Header_Table,
+}
+
+// USED INTERNALLY BY THE COMPILER
+__dynamic_map_get :: proc "contextless" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr) -> rawptr {
+	index := __dynamic_map_find(h, key_hash, key_ptr).entry_index
+	if index != MAP_SENTINEL {
+		data := uintptr(__dynamic_map_get_entry(h, index))
+		return rawptr(data + h.value_offset)
+	}
+	return nil
+}
+
+// USED INTERNALLY BY THE COMPILER
+__dynamic_map_set :: proc "odin" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check {
+	add_entry :: proc "odin" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr, loc := #caller_location) -> Map_Index {
+		prev := Map_Index(h.m.entries.len)
+		c := Map_Index(__dynamic_array_append_nothing(&h.m.entries, h.entry_size, h.entry_align, loc))
+		if c != prev {
+			end := __dynamic_map_get_entry(h, c-1)
+			end.hash = key_hash
+			mem_copy(rawptr(uintptr(end) + h.key_offset), key_ptr, h.key_size)
+			end.next = MAP_SENTINEL
+		}
+		return prev
+	}
+
+	index := MAP_SENTINEL
+
+	if len(h.m.hashes) == 0 {
+		__dynamic_map_reserve(h, INITIAL_MAP_CAP, loc)
+		__dynamic_map_grow(h, loc)
+	}
+
+	fr := __dynamic_map_find(h, key_hash, key_ptr)
+	if fr.entry_index != MAP_SENTINEL {
+		index = fr.entry_index
+	} else {
+		index = add_entry(h, key_hash, key_ptr, loc)
+		if fr.entry_prev != MAP_SENTINEL {
+			entry := __dynamic_map_get_entry(h, fr.entry_prev)
+			entry.next = index
+		} else if fr.hash_index != MAP_SENTINEL {
+			h.m.hashes[fr.hash_index] = index
+		} else {
+			return nil
+		}
+	}
+
+	e := __dynamic_map_get_entry(h, index)
+	e.hash = key_hash
+
+	key := rawptr(uintptr(e) + h.key_offset)
+	val := rawptr(uintptr(e) + h.value_offset)
+
+	mem_copy(key, key_ptr, h.key_size)
+	mem_copy(val, value, h.value_size)
+
+	if __dynamic_map_full(h) {
+		__dynamic_map_grow(h, loc)
+	}
+
+	return __dynamic_map_get_entry(h, index)
+}
+
+// USED INTERNALLY BY THE COMPILER
+__dynamic_map_reserve :: proc "odin" (h: Map_Header, cap: uint, loc := #caller_location) {
+	c := context
+	if h.m.entries.allocator.procedure != nil {
+		c.allocator = h.m.entries.allocator
+	}
+	context = c
+
+	cap := cap
+	cap = ceil_to_pow2(cap)
+
+	__dynamic_array_reserve(&h.m.entries, h.entry_size, h.entry_align, int(cap), loc)
+
+	if h.m.entries.len*2 < len(h.m.hashes) {
+		return
+	}
+	if __slice_resize(&h.m.hashes, int(cap*2), h.m.entries.allocator, loc) {
+		__dynamic_map_reset_entries(h, loc)
+	}
+}
+
+
 INITIAL_HASH_SEED :: 0xcbf29ce484222325
 INITIAL_HASH_SEED :: 0xcbf29ce484222325
 
 
 _fnv64a :: proc "contextless" (data: []byte, seed: u64 = INITIAL_HASH_SEED) -> u64 {
 _fnv64a :: proc "contextless" (data: []byte, seed: u64 = INITIAL_HASH_SEED) -> u64 {
@@ -221,26 +309,6 @@ __dynamic_map_reset_entries :: proc "contextless" (h: Map_Header, loc := #caller
 	}
 	}
 }
 }
 
 
-__dynamic_map_reserve :: proc "odin" (h: Map_Header, cap: uint, loc := #caller_location) {
-	c := context
-	if h.m.entries.allocator.procedure != nil {
-		c.allocator = h.m.entries.allocator
-	}
-	context = c
-
-	cap := cap
-	cap = ceil_to_pow2(cap)
-		
-	__dynamic_array_reserve(&h.m.entries, h.entry_size, h.entry_align, int(cap), loc)
-
-	if h.m.entries.len*2 < len(h.m.hashes) {
-		return
-	}
-	if __slice_resize(&h.m.hashes, int(cap*2), h.m.entries.allocator, loc) {
-		__dynamic_map_reset_entries(h, loc)
-	}
-}
-
 __dynamic_map_shrink :: proc "odin" (h: Map_Header, cap: int, loc := #caller_location) -> (did_shrink: bool) {
 __dynamic_map_shrink :: proc "odin" (h: Map_Header, cap: int, loc := #caller_location) -> (did_shrink: bool) {
 	c := context
 	c := context
 	if h.m.entries.allocator.procedure != nil {
 	if h.m.entries.allocator.procedure != nil {
@@ -251,68 +319,6 @@ __dynamic_map_shrink :: proc "odin" (h: Map_Header, cap: int, loc := #caller_loc
 	return __dynamic_array_shrink(&h.m.entries, h.entry_size, h.entry_align, cap, loc)
 	return __dynamic_array_shrink(&h.m.entries, h.entry_size, h.entry_align, cap, loc)
 }
 }
 
 
-// USED INTERNALLY BY THE COMPILER
-__dynamic_map_get :: proc "contextless" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr) -> rawptr {
-	index := __dynamic_map_find(h, key_hash, key_ptr).entry_index
-	if index != MAP_SENTINEL {
-		data := uintptr(__dynamic_map_get_entry(h, index))
-		return rawptr(data + h.value_offset)
-	}
-	return nil
-}
-
-// USED INTERNALLY BY THE COMPILER
-__dynamic_map_set :: proc "odin" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check {
-	add_entry :: proc "odin" (h: Map_Header, key_hash: uintptr, key_ptr: rawptr, loc := #caller_location) -> Map_Index {
-		prev := Map_Index(h.m.entries.len)
-		c := Map_Index(__dynamic_array_append_nothing(&h.m.entries, h.entry_size, h.entry_align, loc))
-		if c != prev {
-			end := __dynamic_map_get_entry(h, c-1)
-			end.hash = key_hash
-			mem_copy(rawptr(uintptr(end) + h.key_offset), key_ptr, h.key_size)
-			end.next = MAP_SENTINEL
-		}
-		return prev
-	}
-
-	index := MAP_SENTINEL
-
-	if len(h.m.hashes) == 0 {
-		__dynamic_map_reserve(h, INITIAL_MAP_CAP, loc)
-		__dynamic_map_grow(h, loc)
-	}
-
-	fr := __dynamic_map_find(h, key_hash, key_ptr)
-	if fr.entry_index != MAP_SENTINEL {
-		index = fr.entry_index
-	} else {
-		index = add_entry(h, key_hash, key_ptr, loc)
-		if fr.entry_prev != MAP_SENTINEL {
-			entry := __dynamic_map_get_entry(h, fr.entry_prev)
-			entry.next = index
-		} else if fr.hash_index != MAP_SENTINEL {
-			h.m.hashes[fr.hash_index] = index
-		} else {
-			return nil
-		}
-	}
-
-	e := __dynamic_map_get_entry(h, index)
-	e.hash = key_hash
-	
-	key := rawptr(uintptr(e) + h.key_offset)
-	val := rawptr(uintptr(e) + h.value_offset)
-
-	mem_copy(key, key_ptr, h.key_size)
-	mem_copy(val, value, h.value_size)
-
-	if __dynamic_map_full(h) {
-		__dynamic_map_grow(h, loc)
-	}
-	
-	return __dynamic_map_get_entry(h, index)
-}
-
 
 
 @(private="file")
 @(private="file")
 ceil_to_pow2 :: proc "contextless" (n: uint) -> uint {
 ceil_to_pow2 :: proc "contextless" (n: uint) -> uint {

+ 5 - 16
src/checker.cpp

@@ -2831,23 +2831,12 @@ void init_core_source_code_location(Checker *c) {
 }
 }
 
 
 void init_core_map_type(Checker *c) {
 void init_core_map_type(Checker *c) {
-	if (t_map_hash == nullptr) {
-		Entity *e = find_core_entity(c, str_lit("Map_Hash"));
-		if (e->state == EntityState_Unresolved) {
-			check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
-		}
-		t_map_hash = e->type;
-		GB_ASSERT(t_map_hash != nullptr);
-	}
-
-	if (t_map_header == nullptr) {
-		Entity *e = find_core_entity(c, str_lit("Map_Header"));
-		if (e->state == EntityState_Unresolved) {
-			check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
-		}
-		t_map_header = e->type;
-		GB_ASSERT(t_map_header != nullptr);
+	if (t_map_hash != nullptr) {
+		return;
 	}
 	}
+	t_map_hash = find_core_type(c, str_lit("Map_Hash"));
+	t_map_header = find_core_type(c, str_lit("Map_Header"));
+	t_map_header_table = find_core_type(c, str_lit("Map_Header_Table"));
 }
 }
 
 
 void init_preload(Checker *c) {
 void init_preload(Checker *c) {

+ 34 - 19
src/llvm_backend.cpp

@@ -500,20 +500,11 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
 	return value;
 	return value;
 }
 }
 
 
-lbAddr lb_gen_map_header_internal(lbProcedure *p, lbValue map_val_ptr, Type *map_type) {
+LLVMValueRef lb_gen_map_header_table_internal(lbModule *m, Type *map_type) {
 	map_type = base_type(map_type);
 	map_type = base_type(map_type);
 	GB_ASSERT(map_type->kind == Type_Map);
 	GB_ASSERT(map_type->kind == Type_Map);
 
 
-	lbAddr h = lb_add_local_generated(p, t_map_header, true); // all the values will be initialzed later
-
-	Type *key_type = map_type->Map.key;
-	Type *val_type = map_type->Map.value;
-	gb_unused(val_type);
-
 	GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
 	GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
-	map_type->Map.entry_type->cached_size = -1;
-	map_type->Map.entry_type->Struct.are_offsets_set = false;
-
 	i64 entry_size   = type_size_of  (map_type->Map.entry_type);
 	i64 entry_size   = type_size_of  (map_type->Map.entry_type);
 	i64 entry_align  = type_align_of (map_type->Map.entry_type);
 	i64 entry_align  = type_align_of (map_type->Map.entry_type);
 
 
@@ -524,18 +515,42 @@ lbAddr lb_gen_map_header_internal(lbProcedure *p, lbValue map_val_ptr, Type *map
 	i64 value_size   = type_size_of  (map_type->Map.value);
 	i64 value_size   = type_size_of  (map_type->Map.value);
 
 
 
 
+	Type *key_type = map_type->Map.key;
+	Type *val_type = map_type->Map.value;
+	gb_unused(val_type);
+
+	Type *st = base_type(t_map_header_table);
+	GB_ASSERT(st->Struct.fields.count == 7);
+
+	LLVMValueRef const_values[7] = {};
+	const_values[0] = lb_get_equal_proc_for_type(m, key_type)    .value;
+	const_values[1] = lb_const_int(m, t_int,        entry_size)  .value;
+	const_values[2] = lb_const_int(m, t_int,        entry_align) .value;
+	const_values[3] = lb_const_int(m, t_uintptr,    key_offset)  .value;
+	const_values[4] = lb_const_int(m, t_int,        key_size)    .value;
+	const_values[5] = lb_const_int(m, t_uintptr,    value_offset).value;
+	const_values[6] = lb_const_int(m, t_int,        value_size)  .value;
+
+	return llvm_const_named_struct(m, t_map_header_table, const_values, gb_count_of(const_values));
+}
+
+
+lbAddr lb_gen_map_header_internal(lbProcedure *p, lbValue map_val_ptr, Type *map_type) {
+	map_type = base_type(map_type);
+	GB_ASSERT(map_type->kind == Type_Map);
+
+	lbAddr h = lb_add_local_generated(p, t_map_header, true); // all the values will be initialzed later
+
+	GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
+	map_type->Map.entry_type->cached_size = -1;
+	map_type->Map.entry_type->Struct.are_offsets_set = false;
+
 	Type *map_header_base = base_type(t_map_header);
 	Type *map_header_base = base_type(t_map_header);
-	GB_ASSERT(map_header_base->Struct.fields.count == 8);
+	GB_ASSERT(map_header_base->Struct.fields.count == 2);
 	Type *raw_map_ptr_type = map_header_base->Struct.fields[0]->type;
 	Type *raw_map_ptr_type = map_header_base->Struct.fields[0]->type;
-	LLVMValueRef const_values[8] = {};
+	LLVMValueRef const_values[2] = {};
 	const_values[0] = LLVMConstNull(lb_type(p->module, raw_map_ptr_type));
 	const_values[0] = LLVMConstNull(lb_type(p->module, raw_map_ptr_type));
-	const_values[1] = lb_get_equal_proc_for_type(p->module, key_type)    .value;
-	const_values[2] = lb_const_int(p->module, t_int,        entry_size)  .value;
-	const_values[3] = lb_const_int(p->module, t_int,        entry_align) .value;
-	const_values[4] = lb_const_int(p->module, t_uintptr,    key_offset)  .value;
-	const_values[5] = lb_const_int(p->module, t_int,        key_size)    .value;
-	const_values[6] = lb_const_int(p->module, t_uintptr,    value_offset).value;
-	const_values[7] = lb_const_int(p->module, t_int,        value_size)  .value;
+	const_values[1] = lb_gen_map_header_table_internal(p->module, map_type);
 
 
 	LLVMValueRef const_value = llvm_const_named_struct(p->module, t_map_header, const_values, gb_count_of(const_values));
 	LLVMValueRef const_value = llvm_const_named_struct(p->module, t_map_header, const_values, gb_count_of(const_values));
 	LLVMBuildStore(p->builder, const_value, h.addr.value);
 	LLVMBuildStore(p->builder, const_value, h.addr.value);

+ 1 - 0
src/types.cpp

@@ -688,6 +688,7 @@ gb_global Type *t_source_code_location_ptr       = nullptr;
 
 
 gb_global Type *t_map_hash                       = nullptr;
 gb_global Type *t_map_hash                       = nullptr;
 gb_global Type *t_map_header                     = nullptr;
 gb_global Type *t_map_header                     = nullptr;
+gb_global Type *t_map_header_table               = nullptr;
 
 
 
 
 gb_global Type *t_equal_proc  = nullptr;
 gb_global Type *t_equal_proc  = nullptr;