Source file src/hash/maphash/maphash_runtime.go

     1  // Copyright 2023 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.
     4  
     5  //go:build !purego
     6  
     7  package maphash
     8  
     9  import (
    10  	"internal/abi"
    11  	"reflect"
    12  	"unsafe"
    13  )
    14  
    15  //go:linkname runtime_rand runtime.rand
    16  func runtime_rand() uint64
    17  
    18  //go:linkname runtime_memhash runtime.memhash
    19  //go:noescape
    20  func runtime_memhash(p unsafe.Pointer, seed, s uintptr) uintptr
    21  
    22  func rthash(buf []byte, seed uint64) uint64 {
    23  	if len(buf) == 0 {
    24  		return seed
    25  	}
    26  	len := len(buf)
    27  	// The runtime hasher only works on uintptr. For 64-bit
    28  	// architectures, we use the hasher directly. Otherwise,
    29  	// we use two parallel hashers on the lower and upper 32 bits.
    30  	if unsafe.Sizeof(uintptr(0)) == 8 {
    31  		return uint64(runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed), uintptr(len)))
    32  	}
    33  	lo := runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed), uintptr(len))
    34  	hi := runtime_memhash(unsafe.Pointer(&buf[0]), uintptr(seed>>32), uintptr(len))
    35  	return uint64(hi)<<32 | uint64(lo)
    36  }
    37  
    38  func rthashString(s string, state uint64) uint64 {
    39  	buf := unsafe.Slice(unsafe.StringData(s), len(s))
    40  	return rthash(buf, state)
    41  }
    42  
    43  func randUint64() uint64 {
    44  	return runtime_rand()
    45  }
    46  
    47  func comparableF[T comparable](h *Hash, v T) {
    48  	t := abi.TypeFor[T]()
    49  	// We can only use the raw memory contents for the hash,
    50  	// if the raw memory contents are used for computing equality.
    51  	// That works for some types (int),
    52  	// but not others (float, string, structs with padding, etc.)
    53  	if t.TFlag&abi.TFlagRegularMemory != 0 {
    54  		ptr := unsafe.Pointer(&v)
    55  		l := t.Size()
    56  		h.Write(unsafe.Slice((*byte)(ptr), l))
    57  		return
    58  	}
    59  	vv := reflect.ValueOf(v)
    60  	appendT(h, vv)
    61  }
    62  

View as plain text