1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 // For gccgo, use go:linkname to rename compiler-called functions to
13 // themselves, so that the compiler will export them.
15 //go:linkname memhash0 runtime.memhash0
16 //go:linkname memhash8 runtime.memhash8
17 //go:linkname memhash16 runtime.memhash16
18 //go:linkname memhash32 runtime.memhash32
19 //go:linkname memhash64 runtime.memhash64
20 //go:linkname memhash128 runtime.memhash128
21 //go:linkname strhash runtime.strhash
22 //go:linkname f32hash runtime.f32hash
23 //go:linkname f64hash runtime.f64hash
24 //go:linkname c64hash runtime.c64hash
25 //go:linkname c128hash runtime.c128hash
26 //go:linkname interhash runtime.interhash
27 //go:linkname nilinterhash runtime.nilinterhash
28 //go:linkname memequal0 runtime.memequal0
29 //go:linkname memequal8 runtime.memequal8
30 //go:linkname memequal16 runtime.memequal16
31 //go:linkname memequal32 runtime.memequal32
32 //go:linkname memequal64 runtime.memequal64
33 //go:linkname memequal128 runtime.memequal128
34 //go:linkname strequal runtime.strequal
35 //go:linkname f32equal runtime.f32equal
36 //go:linkname f64equal runtime.f64equal
37 //go:linkname c64equal runtime.c64equal
38 //go:linkname c128equal runtime.c128equal
39 //go:linkname interequal runtime.interequal
40 //go:linkname nilinterequal runtime.nilinterequal
41 //go:linkname efaceeq runtime.efaceeq
42 //go:linkname ifaceeq runtime.ifaceeq
43 //go:linkname ifacevaleq runtime.ifacevaleq
44 //go:linkname ifaceefaceeq runtime.ifaceefaceeq
45 //go:linkname efacevaleq runtime.efacevaleq
46 //go:linkname eqstring runtime.eqstring
47 //go:linkname cmpstring runtime.cmpstring
49 // Temporary to be called from C code.
50 //go:linkname alginit runtime.alginit
53 c0
= uintptr((8-sys
.PtrSize
)/4*2860486313 + (sys
.PtrSize
-4)/4*33054211828000289)
54 c1
= uintptr((8-sys
.PtrSize
)/4*3267000013 + (sys
.PtrSize
-4)/4*23344194077549503)
57 func memhash0(p unsafe
.Pointer
, h
uintptr) uintptr {
61 func memhash8(p unsafe
.Pointer
, h
uintptr) uintptr {
62 return memhash(p
, h
, 1)
65 func memhash16(p unsafe
.Pointer
, h
uintptr) uintptr {
66 return memhash(p
, h
, 2)
69 func memhash128(p unsafe
.Pointer
, h
uintptr) uintptr {
70 return memhash(p
, h
, 16)
76 func aeshashbody(p unsafe
.Pointer
, h
, s
uintptr, sched
[]byte) uintptr
78 func aeshash(p unsafe
.Pointer
, h
, s
uintptr) uintptr {
79 return aeshashbody(p
, h
, s
, aeskeysched
[:])
82 func aeshashstr(p unsafe
.Pointer
, h
uintptr) uintptr {
83 ps
:= (*stringStruct
)(p
)
84 return aeshashbody(unsafe
.Pointer(ps
.str
), h
, uintptr(ps
.len), aeskeysched
[:])
87 func strhash(a unsafe
.Pointer
, h
uintptr) uintptr {
88 x
:= (*stringStruct
)(a
)
89 return memhash(x
.str
, h
, uintptr(x
.len))
92 // NOTE: Because NaN != NaN, a map can contain any
93 // number of (mostly useless) entries keyed with NaNs.
94 // To avoid long hash chains, we assign a random number
95 // as the hash value for a NaN.
97 func f32hash(p unsafe
.Pointer
, h
uintptr) uintptr {
101 return c1
* (c0
^ h
) // +0, -0
103 return c1
* (c0
^ h
^ uintptr(fastrand())) // any kind of NaN
105 return memhash(p
, h
, 4)
109 func f64hash(p unsafe
.Pointer
, h
uintptr) uintptr {
113 return c1
* (c0
^ h
) // +0, -0
115 return c1
* (c0
^ h
^ uintptr(fastrand())) // any kind of NaN
117 return memhash(p
, h
, 8)
121 func c64hash(p unsafe
.Pointer
, h
uintptr) uintptr {
122 x
:= (*[2]float32)(p
)
123 return f32hash(unsafe
.Pointer(&x
[1]), f32hash(unsafe
.Pointer(&x
[0]), h
))
126 func c128hash(p unsafe
.Pointer
, h
uintptr) uintptr {
127 x
:= (*[2]float64)(p
)
128 return f64hash(unsafe
.Pointer(&x
[1]), f64hash(unsafe
.Pointer(&x
[0]), h
))
131 func interhash(p unsafe
.Pointer
, h
uintptr) uintptr {
140 panic(errorString("hash of unhashable type " + *t
.string))
142 if isDirectIface(t
) {
143 return c1
* fn(unsafe
.Pointer(&a
.data
), h
^c0
)
145 return c1
* fn(a
.data
, h
^c0
)
149 func nilinterhash(p unsafe
.Pointer
, h
uintptr) uintptr {
157 panic(errorString("hash of unhashable type " + *t
.string))
159 if isDirectIface(t
) {
160 return c1
* fn(unsafe
.Pointer(&a
.data
), h
^c0
)
162 return c1
* fn(a
.data
, h
^c0
)
166 func memequal0(p
, q unsafe
.Pointer
) bool {
169 func memequal8(p
, q unsafe
.Pointer
) bool {
170 return *(*int8)(p
) == *(*int8)(q
)
172 func memequal16(p
, q unsafe
.Pointer
) bool {
173 return *(*int16)(p
) == *(*int16)(q
)
175 func memequal32(p
, q unsafe
.Pointer
) bool {
176 return *(*int32)(p
) == *(*int32)(q
)
178 func memequal64(p
, q unsafe
.Pointer
) bool {
179 return *(*int64)(p
) == *(*int64)(q
)
181 func memequal128(p
, q unsafe
.Pointer
) bool {
182 return *(*[2]int64)(p
) == *(*[2]int64)(q
)
184 func f32equal(p
, q unsafe
.Pointer
) bool {
185 return *(*float32)(p
) == *(*float32)(q
)
187 func f64equal(p
, q unsafe
.Pointer
) bool {
188 return *(*float64)(p
) == *(*float64)(q
)
190 func c64equal(p
, q unsafe
.Pointer
) bool {
191 return *(*complex64
)(p
) == *(*complex64
)(q
)
193 func c128equal(p
, q unsafe
.Pointer
) bool {
194 return *(*complex128
)(p
) == *(*complex128
)(q
)
196 func strequal(p
, q unsafe
.Pointer
) bool {
197 return *(*string)(p
) == *(*string)(q
)
199 func interequal(p
, q unsafe
.Pointer
) bool {
200 return ifaceeq(*(*iface
)(p
), *(*iface
)(q
))
202 func nilinterequal(p
, q unsafe
.Pointer
) bool {
203 return efaceeq(*(*eface
)(p
), *(*eface
)(q
))
205 func efaceeq(x
, y eface
) bool {
207 if !eqtype(t
, y
._type
) {
215 panic(errorString("comparing uncomparable type " + *t
.string))
217 if isDirectIface(t
) {
218 return x
.data
== y
.data
220 return eq(x
.data
, y
.data
)
222 func ifaceeq(x
, y iface
) bool {
224 if xtab
== nil && y
.tab
== nil {
227 if xtab
== nil || y
.tab
== nil {
230 t
:= *(**_type
)(xtab
)
231 if !eqtype(t
, *(**_type
)(y
.tab
)) {
236 panic(errorString("comparing uncomparable type " + *t
.string))
238 if isDirectIface(t
) {
239 return x
.data
== y
.data
241 return eq(x
.data
, y
.data
)
244 func ifacevaleq(x iface
, t
*_type
, p unsafe
.Pointer
) bool {
248 xt
:= *(**_type
)(x
.tab
)
254 panic(errorString("comparing uncomparable type " + *t
.string))
256 if isDirectIface(t
) {
262 func ifaceefaceeq(x iface
, y eface
) bool {
263 if x
.tab
== nil && y
._type
== nil {
266 if x
.tab
== nil || y
._type
== nil {
269 xt
:= *(**_type
)(x
.tab
)
270 if !eqtype(xt
, y
._type
) {
275 panic(errorString("comparing uncomparable type " + *xt
.string))
277 if isDirectIface(xt
) {
278 return x
.data
== y
.data
280 return eq(x
.data
, y
.data
)
283 func efacevaleq(x eface
, t
*_type
, p unsafe
.Pointer
) bool {
287 if !eqtype(x
._type
, t
) {
292 panic(errorString("comparing uncomparable type " + *t
.string))
294 if isDirectIface(t
) {
300 func cmpstring(x
, y
string) int {
301 a
:= stringStructOf(&x
)
302 b
:= stringStructOf(&y
)
307 i
:= memcmp(unsafe
.Pointer(a
.str
), unsafe
.Pointer(b
.str
), uintptr(l
))
313 } else if a
.len > b
.len {
319 // For the unsafe.Pointer type descriptor in libgo/runtime/go-unsafe-pointer.c.
321 func pointerhash(p unsafe
.Pointer
, h
uintptr) uintptr {
322 return memhash(p
, h
, unsafe
.Sizeof(unsafe
.Pointer
))
325 func pointerequal(p
, q unsafe
.Pointer
) bool {
326 return *(*unsafe
.Pointer
)(p
) == *(*unsafe
.Pointer
)(q
)
329 // Force the creation of function descriptors for equality and hash
330 // functions. These will be referenced directly by the compiler.
357 var _
= nilinterequal
361 // Testing adapters for hash quality tests (see hash_test.go)
362 func stringHash(s
string, seed
uintptr) uintptr {
363 return strhash(noescape(unsafe
.Pointer(&s
)), seed
)
366 func bytesHash(b
[]byte, seed
uintptr) uintptr {
367 s
:= (*slice
)(unsafe
.Pointer(&b
))
368 return memhash(s
.array
, seed
, uintptr(s
.len))
371 func int32Hash(i
uint32, seed
uintptr) uintptr {
372 return memhash32(noescape(unsafe
.Pointer(&i
)), seed
)
375 func int64Hash(i
uint64, seed
uintptr) uintptr {
376 return memhash64(noescape(unsafe
.Pointer(&i
)), seed
)
379 func efaceHash(i
interface{}, seed
uintptr) uintptr {
380 return nilinterhash(noescape(unsafe
.Pointer(&i
)), seed
)
383 func ifaceHash(i
interface {
385 }, seed
uintptr) uintptr {
386 return interhash(noescape(unsafe
.Pointer(&i
)), seed
)
389 const hashRandomBytes
= sys
.PtrSize
/ 4 * 64
391 // used in asm_{386,amd64}.s to seed the hash function
392 var aeskeysched
[hashRandomBytes
]byte
394 // used in hash{32,64}.go to seed the hash function
395 var hashkey
[4]uintptr
398 // Install aes hash algorithm if we have the instructions we need
399 if (GOARCH
== "386" || GOARCH
== "amd64") &&
402 cpuid_ecx
&(1<<25) != 0 && // aes (aesenc)
403 cpuid_ecx
&(1<<9) != 0 && // sse3 (pshufb)
404 cpuid_ecx
&(1<<19) != 0 { // sse4.1 (pinsr{d,q})
406 // Initialize with random data so hash collisions will be hard to engineer.
407 getRandomData(aeskeysched
[:])
410 getRandomData((*[len(hashkey
) * sys
.PtrSize
]byte)(unsafe
.Pointer(&hashkey
))[:])
411 hashkey
[0] |
= 1 // make sure these numbers are odd