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