aboutsummaryrefslogtreecommitdiff
path: root/core/runtime
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-11-29 15:27:53 +0000
committergingerBill <bill@gingerbill.org>2020-11-29 15:27:53 +0000
commit97c66c9c732af1e0735ee3f48a8af08b199bddf9 (patch)
treeaaedfa7f85390520f3d6d60064cedd8a4cb9af17 /core/runtime
parent085972bb2ccde65d148b7fdc07b7ea8329e46293 (diff)
Add `intrinsics.type_hasher_proc`; Make `map` work with generic hasher procedure
Diffstat (limited to 'core/runtime')
-rw-r--r--core/runtime/core.odin5
-rw-r--r--core/runtime/dynamic_map_internal.odin64
2 files changed, 44 insertions, 25 deletions
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index 1cc564ff2..74b1338c7 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -42,7 +42,8 @@ Platform_Endianness :: enum u8 {
Big = 2,
}
-Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool;
+Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool;
+Hasher_Proc :: distinct proc "contextless" (data: rawptr, seed: uintptr) -> uintptr;
Type_Info_Struct_Soa_Kind :: enum u8 {
None = 0,
@@ -125,6 +126,8 @@ Type_Info_Map :: struct {
key: ^Type_Info,
value: ^Type_Info,
generated_struct: ^Type_Info,
+ key_equal: Equal_Proc,
+ key_hasher: Hasher_Proc,
};
Type_Info_Bit_Field :: struct {
names: []string,
diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin
index 59661668f..99c2e92ee 100644
--- a/core/runtime/dynamic_map_internal.odin
+++ b/core/runtime/dynamic_map_internal.odin
@@ -11,31 +11,11 @@ Map_Hash :: struct {
key_ptr: rawptr, // address of Map_Entry_Header.key
}
-__get_map_hash :: proc "contextless" (k: ^$K) -> Map_Hash {
- key := k;
- map_hash: Map_Hash;
-
- T :: intrinsics.type_core_type(K);
-
+__get_map_hash :: proc "contextless" (k: ^$K) -> (map_hash: Map_Hash) {
+ hasher := intrinsics.type_hasher_proc(K);
map_hash.key_ptr = k;
-
- when intrinsics.type_is_integer(T) {
- map_hash.hash = default_hash_ptr(key, size_of(T));
- } else when intrinsics.type_is_rune(T) {
- map_hash.hash = default_hash_ptr(key, size_of(T));
- } else when intrinsics.type_is_pointer(T) {
- map_hash.hash = default_hash_ptr(key, size_of(T));
- } else when intrinsics.type_is_float(T) {
- map_hash.hash = default_hash_ptr(key, size_of(T));
- } else when intrinsics.type_is_string(T) {
- #assert(T == string);
- str := (^string)(key)^;
- map_hash.hash = default_hash_string(str);
- } else {
- #panic("Unhandled map key type");
- }
-
- return map_hash;
+ map_hash.hash = hasher(k, 0);
+ return;
}
__get_map_hash_from_entry :: proc "contextless" (h: Map_Header, entry: ^Map_Entry_Header) -> (hash: Map_Hash) {
@@ -96,6 +76,42 @@ default_hash_ptr :: inline proc "contextless" (data: rawptr, size: int) -> uintp
return default_hash(transmute([]byte)(s));
}
+_default_hasher_const :: inline proc "contextless" (data: rawptr, seed: uintptr, $N: uint) -> uintptr {
+ h := u64(seed) + 0xcbf29ce484222325;
+ p := uintptr(data);
+ inline for _ in 0..<N {
+ b := u64((^byte)(p)^);
+ h = (h ~ b) * 0x100000001b3;
+ p += 1;
+ }
+ return uintptr(h);
+}
+_default_hasher_n :: inline proc "contextless" (data: rawptr, seed: uintptr, N: int) -> uintptr {
+ h := u64(seed) + 0xcbf29ce484222325;
+ p := uintptr(data);
+ for _ in 0..<N {
+ b := u64((^byte)(p)^);
+ h = (h ~ b) * 0x100000001b3;
+ p += 1;
+ }
+ return uintptr(h);
+}
+
+default_hasher1 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return inline _default_hasher_const(data, seed, 1); }
+default_hasher2 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return inline _default_hasher_const(data, seed, 2); }
+default_hasher4 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return inline _default_hasher_const(data, seed, 4); }
+default_hasher8 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return inline _default_hasher_const(data, seed, 8); }
+default_hasher16 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return inline _default_hasher_const(data, seed, 16); }
+default_hasher_string :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr {
+ h := u64(seed) + 0xcbf29ce484222325;
+ str := (^[]byte)(data)^;
+ for b in str {
+ h = (h ~ u64(b)) * 0x100000001b3;
+ }
+ return uintptr(h);
+}
+
+
source_code_location_hash :: proc(s: Source_Code_Location) -> uintptr {
hash := _fnv64a(transmute([]byte)s.file_path);