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