1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/byteorder"
10 "internal/cpu"
11 "internal/goarch"
12 "internal/runtime/sys"
13 "unsafe"
14 )
15
16 const (
17 c0 = uintptr((8-goarch.PtrSize)/4*2860486313 + (goarch.PtrSize-4)/4*33054211828000289)
18 c1 = uintptr((8-goarch.PtrSize)/4*3267000013 + (goarch.PtrSize-4)/4*23344194077549503)
19 )
20
21 func memhash0(p unsafe.Pointer, h uintptr) uintptr {
22 return h
23 }
24
25 func memhash8(p unsafe.Pointer, h uintptr) uintptr {
26 return memhash(p, h, 1)
27 }
28
29 func memhash16(p unsafe.Pointer, h uintptr) uintptr {
30 return memhash(p, h, 2)
31 }
32
33 func memhash128(p unsafe.Pointer, h uintptr) uintptr {
34 return memhash(p, h, 16)
35 }
36
37
38 func memhash_varlen(p unsafe.Pointer, h uintptr) uintptr {
39 ptr := sys.GetClosurePtr()
40 size := *(*uintptr)(unsafe.Pointer(ptr + unsafe.Sizeof(h)))
41 return memhash(p, h, size)
42 }
43
44
45
46
47 var useAeshash bool
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 func memhash(p unsafe.Pointer, h, s uintptr) uintptr
69
70 func memhash32(p unsafe.Pointer, h uintptr) uintptr
71
72 func memhash64(p unsafe.Pointer, h uintptr) uintptr
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 func strhash(p unsafe.Pointer, h uintptr) uintptr
88
89 func strhashFallback(a unsafe.Pointer, h uintptr) uintptr {
90 x := (*stringStruct)(a)
91 return memhashFallback(x.str, h, uintptr(x.len))
92 }
93
94
95
96
97
98
99 func f32hash(p unsafe.Pointer, h uintptr) uintptr {
100 f := *(*float32)(p)
101 switch {
102 case f == 0:
103 return c1 * (c0 ^ h)
104 case f != f:
105 return c1 * (c0 ^ h ^ uintptr(rand()))
106 default:
107 return memhash(p, h, 4)
108 }
109 }
110
111 func f64hash(p unsafe.Pointer, h uintptr) uintptr {
112 f := *(*float64)(p)
113 switch {
114 case f == 0:
115 return c1 * (c0 ^ h)
116 case f != f:
117 return c1 * (c0 ^ h ^ uintptr(rand()))
118 default:
119 return memhash(p, h, 8)
120 }
121 }
122
123 func c64hash(p unsafe.Pointer, h uintptr) uintptr {
124 x := (*[2]float32)(p)
125 return f32hash(unsafe.Pointer(&x[1]), f32hash(unsafe.Pointer(&x[0]), h))
126 }
127
128 func c128hash(p unsafe.Pointer, h uintptr) uintptr {
129 x := (*[2]float64)(p)
130 return f64hash(unsafe.Pointer(&x[1]), f64hash(unsafe.Pointer(&x[0]), h))
131 }
132
133 func interhash(p unsafe.Pointer, h uintptr) uintptr {
134 a := (*iface)(p)
135 tab := a.tab
136 if tab == nil {
137 return h
138 }
139 t := tab.Type
140 if t.Equal == nil {
141
142
143
144
145 panic(errorString("hash of unhashable type " + toRType(t).string()))
146 }
147 if isDirectIface(t) {
148 return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
149 } else {
150 return c1 * typehash(t, a.data, h^c0)
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164 func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
165 a := (*eface)(p)
166 t := a._type
167 if t == nil {
168 return h
169 }
170 if t.Equal == nil {
171
172 panic(errorString("hash of unhashable type " + toRType(t).string()))
173 }
174 if isDirectIface(t) {
175 return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
176 } else {
177 return c1 * typehash(t, a.data, h^c0)
178 }
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
203 if t.TFlag&abi.TFlagRegularMemory != 0 {
204
205 switch t.Size_ {
206 case 4:
207 return memhash32(p, h)
208 case 8:
209 return memhash64(p, h)
210 default:
211 return memhash(p, h, t.Size_)
212 }
213 }
214 switch t.Kind_ & abi.KindMask {
215 case abi.Float32:
216 return f32hash(p, h)
217 case abi.Float64:
218 return f64hash(p, h)
219 case abi.Complex64:
220 return c64hash(p, h)
221 case abi.Complex128:
222 return c128hash(p, h)
223 case abi.String:
224 return strhash(p, h)
225 case abi.Interface:
226 i := (*interfacetype)(unsafe.Pointer(t))
227 if len(i.Methods) == 0 {
228 return nilinterhash(p, h)
229 }
230 return interhash(p, h)
231 case abi.Array:
232 a := (*arraytype)(unsafe.Pointer(t))
233 for i := uintptr(0); i < a.Len; i++ {
234 h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
235 }
236 return h
237 case abi.Struct:
238 s := (*structtype)(unsafe.Pointer(t))
239 for _, f := range s.Fields {
240 if f.Name.IsBlank() {
241 continue
242 }
243 h = typehash(f.Typ, add(p, f.Offset), h)
244 }
245 return h
246 default:
247
248
249 panic(errorString("hash of unhashable type " + toRType(t).string()))
250 }
251 }
252
253
254 func reflect_typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
255 return typehash(t, p, h)
256 }
257
258 func memequal0(p, q unsafe.Pointer) bool {
259 return true
260 }
261 func memequal8(p, q unsafe.Pointer) bool {
262 return *(*int8)(p) == *(*int8)(q)
263 }
264 func memequal16(p, q unsafe.Pointer) bool {
265 return *(*int16)(p) == *(*int16)(q)
266 }
267 func memequal32(p, q unsafe.Pointer) bool {
268 return *(*int32)(p) == *(*int32)(q)
269 }
270 func memequal64(p, q unsafe.Pointer) bool {
271 return *(*int64)(p) == *(*int64)(q)
272 }
273 func memequal128(p, q unsafe.Pointer) bool {
274 return *(*[2]int64)(p) == *(*[2]int64)(q)
275 }
276 func f32equal(p, q unsafe.Pointer) bool {
277 return *(*float32)(p) == *(*float32)(q)
278 }
279 func f64equal(p, q unsafe.Pointer) bool {
280 return *(*float64)(p) == *(*float64)(q)
281 }
282 func c64equal(p, q unsafe.Pointer) bool {
283 return *(*complex64)(p) == *(*complex64)(q)
284 }
285 func c128equal(p, q unsafe.Pointer) bool {
286 return *(*complex128)(p) == *(*complex128)(q)
287 }
288 func strequal(p, q unsafe.Pointer) bool {
289 return *(*string)(p) == *(*string)(q)
290 }
291 func interequal(p, q unsafe.Pointer) bool {
292 x := *(*iface)(p)
293 y := *(*iface)(q)
294 return x.tab == y.tab && ifaceeq(x.tab, x.data, y.data)
295 }
296 func nilinterequal(p, q unsafe.Pointer) bool {
297 x := *(*eface)(p)
298 y := *(*eface)(q)
299 return x._type == y._type && efaceeq(x._type, x.data, y.data)
300 }
301 func efaceeq(t *_type, x, y unsafe.Pointer) bool {
302 if t == nil {
303 return true
304 }
305 eq := t.Equal
306 if eq == nil {
307 panic(errorString("comparing uncomparable type " + toRType(t).string()))
308 }
309 if isDirectIface(t) {
310
311
312
313 return x == y
314 }
315 return eq(x, y)
316 }
317 func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
318 if tab == nil {
319 return true
320 }
321 t := tab.Type
322 eq := t.Equal
323 if eq == nil {
324 panic(errorString("comparing uncomparable type " + toRType(t).string()))
325 }
326 if isDirectIface(t) {
327
328 return x == y
329 }
330 return eq(x, y)
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344 func stringHash(s string, seed uintptr) uintptr {
345 return strhash(noescape(unsafe.Pointer(&s)), seed)
346 }
347
348 func bytesHash(b []byte, seed uintptr) uintptr {
349 s := (*slice)(unsafe.Pointer(&b))
350 return memhash(s.array, seed, uintptr(s.len))
351 }
352
353 func int32Hash(i uint32, seed uintptr) uintptr {
354 return memhash32(noescape(unsafe.Pointer(&i)), seed)
355 }
356
357 func int64Hash(i uint64, seed uintptr) uintptr {
358 return memhash64(noescape(unsafe.Pointer(&i)), seed)
359 }
360
361 func efaceHash(i any, seed uintptr) uintptr {
362 return nilinterhash(noescape(unsafe.Pointer(&i)), seed)
363 }
364
365 func ifaceHash(i interface {
366 F()
367 }, seed uintptr) uintptr {
368 return interhash(noescape(unsafe.Pointer(&i)), seed)
369 }
370
371 const hashRandomBytes = goarch.PtrSize / 4 * 64
372
373
374 var aeskeysched [hashRandomBytes]byte
375
376
377 var hashkey [4]uintptr
378
379 func alginit() {
380
381 if (GOARCH == "386" || GOARCH == "amd64") &&
382 cpu.X86.HasAES &&
383 cpu.X86.HasSSSE3 &&
384 cpu.X86.HasSSE41 {
385 initAlgAES()
386 return
387 }
388 if GOARCH == "arm64" && cpu.ARM64.HasAES {
389 initAlgAES()
390 return
391 }
392 for i := range hashkey {
393 hashkey[i] = uintptr(bootstrapRand())
394 }
395 }
396
397 func initAlgAES() {
398 useAeshash = true
399
400 key := (*[hashRandomBytes / 8]uint64)(unsafe.Pointer(&aeskeysched))
401 for i := range key {
402 key[i] = bootstrapRand()
403 }
404 }
405
406
407 func readUnaligned32(p unsafe.Pointer) uint32 {
408 q := (*[4]byte)(p)
409 if goarch.BigEndian {
410 return byteorder.BEUint32(q[:])
411 }
412 return byteorder.LEUint32(q[:])
413 }
414
415 func readUnaligned64(p unsafe.Pointer) uint64 {
416 q := (*[8]byte)(p)
417 if goarch.BigEndian {
418 return byteorder.BEUint64(q[:])
419 }
420 return byteorder.LEUint64(q[:])
421 }
422
View as plain text