Source file
src/hash/maphash/maphash_runtime.go
1
2
3
4
5
6
7 package maphash
8
9 import (
10 "internal/abi"
11 "internal/goarch"
12 "internal/goexperiment"
13 "unsafe"
14 )
15
16 const purego = false
17
18
19 func runtime_rand() uint64
20
21
22
23 func runtime_memhash(p unsafe.Pointer, seed, s uintptr) uintptr
24
25 func rthash(buf []byte, seed uint64) uint64 {
26 if len(buf) == 0 {
27 return seed
28 }
29 len := len(buf)
30
31
32
33 if goarch.PtrSize == 8 {
34 return uint64(runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed), uintptr(len)))
35 }
36 lo := runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed), uintptr(len))
37 hi := runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed>>32), uintptr(len))
38 return uint64(hi)<<32 | uint64(lo)
39 }
40
41 func rthashString(s string, state uint64) uint64 {
42 buf := unsafe.Slice(unsafe.StringData(s), len(s))
43 return rthash(buf, state)
44 }
45
46 func randUint64() uint64 {
47 return runtime_rand()
48 }
49
50 func comparableHash[T comparable](v T, seed Seed) uint64 {
51 s := seed.s
52 var m map[T]struct{}
53 mTyp := abi.TypeOf(m)
54 var hasher func(unsafe.Pointer, uintptr) uintptr
55 if goexperiment.SwissMap {
56 hasher = (*abi.SwissMapType)(unsafe.Pointer(mTyp)).Hasher
57 } else {
58 hasher = (*abi.OldMapType)(unsafe.Pointer(mTyp)).Hasher
59 }
60 if goarch.PtrSize == 8 {
61 return uint64(hasher(abi.NoEscape(unsafe.Pointer(&v)), uintptr(s)))
62 }
63 lo := hasher(abi.NoEscape(unsafe.Pointer(&v)), uintptr(s))
64 hi := hasher(abi.NoEscape(unsafe.Pointer(&v)), uintptr(s>>32))
65 return uint64(hi)<<32 | uint64(lo)
66 }
67
68 func writeComparable[T comparable](h *Hash, v T) {
69 h.state.s = comparableHash(v, h.state)
70 }
71
View as plain text