Browse Source

Make `map` get internal calls take the hash value rather than compute it internally

gingerBill 2 years ago
parent
commit
a0bd31646b
3 changed files with 25 additions and 26 deletions
  1. 9 12
      core/runtime/dynamic_map_internal.odin
  2. 2 2
      src/checker.cpp
  3. 14 12
      src/llvm_backend.cpp

+ 9 - 12
core/runtime/dynamic_map_internal.odin

@@ -665,7 +665,8 @@ map_get :: proc "contextless" (m: $T/map[$K]$V, key: K) -> (stored_key: K, store
 	}
 	}
 }
 }
 
 
-__dynamic_map_get_with_hash :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, key: rawptr) -> (ptr: rawptr) {
+// IMPORTANT: USED WITHIN THE COMPILER
+__dynamic_map_get :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, key: rawptr) -> (ptr: rawptr) {
 	if m.len == 0 {
 	if m.len == 0 {
 		return nil
 		return nil
 	}
 	}
@@ -687,28 +688,24 @@ __dynamic_map_get_with_hash :: proc "contextless" (#no_alias m: ^Raw_Map, #no_al
 	}
 	}
 }
 }
 
 
-// IMPORTANT: USED WITHIN THE COMPILER
-__dynamic_map_get :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr) -> (ptr: rawptr) {
-	if m.len == 0 {
-		return nil
+__dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
+	if m.len + 1 >= map_resize_threshold(m^) {
+		return map_grow_dynamic(m, info, loc)
 	}
 	}
-	h := info.key_hasher(key, 0)
-	return __dynamic_map_get_with_hash(m, info, h, key)
+	return nil
 }
 }
 
 
 // IMPORTANT: USED WITHIN THE COMPILER
 // IMPORTANT: USED WITHIN THE COMPILER
 __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr {
 __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr {
 	hash := info.key_hasher(key, 0)
 	hash := info.key_hasher(key, 0)
 
 
-	if found := __dynamic_map_get_with_hash(m, info, hash, key); found != nil {
+	if found := __dynamic_map_get(m, info, hash, key); found != nil {
 		intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type)
 		intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type)
 		return found
 		return found
 	}
 	}
 
 
-	if m.len + 1 >= map_resize_threshold(m^) {
-		if err := map_grow_dynamic(m, info, loc); err != nil {
-			return nil
-		}
+	if __dynamic_map_check_grow(m, info, loc) != nil {
+		return nil
 	}
 	}
 
 
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))

+ 2 - 2
src/checker.cpp

@@ -927,8 +927,8 @@ void init_universal(void) {
 		Type *hasher_args[2] = {t_rawptr, t_uintptr};
 		Type *hasher_args[2] = {t_rawptr, t_uintptr};
 		t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless);
 		t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless);
 
 
-		Type *map_get_args[2] = {/*map*/t_rawptr, /*key*/t_rawptr};
-		t_map_get_proc = alloc_type_proc_from_types(map_get_args, 2, t_rawptr, false, ProcCC_Contextless);
+		Type *map_get_args[3] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr};
+		t_map_get_proc = alloc_type_proc_from_types(map_get_args, 3, t_rawptr, false, ProcCC_Contextless);
 
 
 	}
 	}
 
 

+ 14 - 12
src/llvm_backend.cpp

@@ -498,16 +498,18 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
 
 
 	LLVMValueRef x = LLVMGetParam(p->value, 0);
 	LLVMValueRef x = LLVMGetParam(p->value, 0);
 	LLVMValueRef y = LLVMGetParam(p->value, 1);
 	LLVMValueRef y = LLVMGetParam(p->value, 1);
+	LLVMValueRef z = LLVMGetParam(p->value, 2);
 	lbValue map_ptr = {x, t_rawptr};
 	lbValue map_ptr = {x, t_rawptr};
-	lbValue key_ptr = {y, t_rawptr};
+	lbValue h       = {y, t_uintptr};
+	lbValue key_ptr = {z, t_rawptr};
 
 
 	lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
 	lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
 	lb_add_proc_attribute_at_index(p, 1+0, "noalias");
 	lb_add_proc_attribute_at_index(p, 1+0, "noalias");
 	lb_add_proc_attribute_at_index(p, 1+0, "readonly");
 	lb_add_proc_attribute_at_index(p, 1+0, "readonly");
 
 
-	lb_add_proc_attribute_at_index(p, 1+1, "nonnull");
-	lb_add_proc_attribute_at_index(p, 1+1, "noalias");
-	lb_add_proc_attribute_at_index(p, 1+1, "readonly");
+	lb_add_proc_attribute_at_index(p, 1+2, "nonnull");
+	lb_add_proc_attribute_at_index(p, 1+2, "noalias");
+	lb_add_proc_attribute_at_index(p, 1+2, "readonly");
 
 
 	lbBlock *loop_block = lb_create_block(p, "loop");
 	lbBlock *loop_block = lb_create_block(p, "loop");
 	lbBlock *hash_block = lb_create_block(p, "hash");
 	lbBlock *hash_block = lb_create_block(p, "hash");
@@ -529,7 +531,6 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
 	key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key));
 	key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key));
 	lbValue key = lb_emit_load(p, key_ptr);
 	lbValue key = lb_emit_load(p, key_ptr);
 
 
-	lbValue h = lb_gen_map_key_hash(p, key, type->Map.key, nullptr);
 	lbAddr pos = lb_add_local_generated(p, t_uintptr, false);
 	lbAddr pos = lb_add_local_generated(p, t_uintptr, false);
 	lbAddr distance = lb_add_local_generated(p, t_uintptr, true);
 	lbAddr distance = lb_add_local_generated(p, t_uintptr, true);
 	lbValue capacity = lb_map_cap(p, map);
 	lbValue capacity = lb_map_cap(p, map);
@@ -785,23 +786,24 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr,
 	GB_ASSERT(map_type->kind == Type_Map);
 	GB_ASSERT(map_type->kind == Type_Map);
 
 
 	lbValue ptr = {};
 	lbValue ptr = {};
-
-	lbValue key_ptr = lb_address_from_load_or_generate_local(p, key);
-	key_ptr = lb_emit_conv(p, key_ptr, t_rawptr);
+	lbValue key_ptr = {};
+	lbValue hash = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr);
 
 
 	if (build_context.use_static_map_calls) {
 	if (build_context.use_static_map_calls) {
 		lbValue map_get_proc = lb_map_get_proc_for_type(p->module, map_type);
 		lbValue map_get_proc = lb_map_get_proc_for_type(p->module, map_type);
 
 
-		auto args = array_make<lbValue>(permanent_allocator(), 2);
+		auto args = array_make<lbValue>(permanent_allocator(), 3);
 		args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
 		args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
-		args[1] = key_ptr;
+		args[1] = hash;
+		args[2] = key_ptr;
 
 
 		ptr = lb_emit_call(p, map_get_proc, args);
 		ptr = lb_emit_call(p, map_get_proc, args);
 	} else {
 	} else {
-		auto args = array_make<lbValue>(permanent_allocator(), 3);
+		auto args = array_make<lbValue>(permanent_allocator(), 4);
 		args[0] = lb_emit_transmute(p, map_ptr, t_raw_map_ptr);
 		args[0] = lb_emit_transmute(p, map_ptr, t_raw_map_ptr);
 		args[1] = lb_gen_map_info_ptr(p->module, map_type);
 		args[1] = lb_gen_map_info_ptr(p->module, map_type);
-		args[2] = key_ptr;
+		args[2] = hash;
+		args[3] = key_ptr;
 
 
 		ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args);
 		ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args);
 	}
 	}