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