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