Source file src/internal/runtime/maps/runtime_alg.go

     1  // Copyright 2026 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  package maps
     6  
     7  import (
     8  	"internal/byteorder"
     9  	"internal/cpu"
    10  	"internal/goarch"
    11  	"unsafe"
    12  )
    13  
    14  // runtime variable to check if the processor we're running on
    15  // actually supports the instructions used by the AES-based
    16  // hash implementation.
    17  var UseAeshash bool
    18  
    19  const hashRandomBytes = goarch.PtrSize / 4 * 64
    20  
    21  // used to seed the hash function
    22  var aeskeysched [hashRandomBytes]byte
    23  
    24  // used in hash{32,64}.go to seed the hash function
    25  var hashkey [4]uintptr
    26  
    27  func AlgInit() {
    28  	// Always intialize hashkey.
    29  	//
    30  	// See #78073
    31  	for i := range hashkey {
    32  		hashkey[i] = uintptr(bootstrapRand())
    33  	}
    34  
    35  	// Install AES hash algorithms if the instructions needed are present.
    36  	if (goarch.GOARCH == "386" || goarch.GOARCH == "amd64") &&
    37  		cpu.X86.HasAES && // AESENC
    38  		cpu.X86.HasSSSE3 && // PSHUFB
    39  		cpu.X86.HasSSE41 { // PINSR{D,Q}
    40  
    41  		// In memHashAES we have global variables that should be properly aligned.
    42  		//
    43  		// See #12415
    44  		if !checkMasksAndShiftsAlignment() {
    45  			fatal("maps: global variables for AES hashing are not properly aligned!")
    46  		}
    47  		initAlgAES()
    48  
    49  		if memHashUsesVAES {
    50  			// We are using intrinsics hash implementation.
    51  			// Override the UseAeshash in this case, since it uses VAES (AVX) instructions.
    52  			// While assembly implementation used AES-NI instructions,
    53  			// simd intrinsics only provide access to AVX ones.
    54  			UseAeshash = cpu.X86.HasAVX
    55  		}
    56  		return
    57  	}
    58  	if goarch.GOARCH == "arm64" && cpu.ARM64.HasAES {
    59  		initAlgAES()
    60  		return
    61  	}
    62  }
    63  
    64  func initAlgAES() {
    65  	UseAeshash = true
    66  	// Initialize with random data so hash collisions will be hard to engineer.
    67  	key := (*[hashRandomBytes / 8]uint64)(unsafe.Pointer(&aeskeysched))
    68  	for i := range key {
    69  		key[i] = bootstrapRand()
    70  	}
    71  }
    72  
    73  //go:nosplit
    74  func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
    75  	return unsafe.Pointer(uintptr(p) + x)
    76  }
    77  
    78  // Note: These routines perform the read with a native endianness.
    79  func readUnaligned32(p unsafe.Pointer) uint32 {
    80  	q := (*[4]byte)(p)
    81  	if goarch.BigEndian {
    82  		return byteorder.BEUint32(q[:])
    83  	}
    84  	return byteorder.LEUint32(q[:])
    85  }
    86  
    87  func readUnaligned64(p unsafe.Pointer) uint64 {
    88  	q := (*[8]byte)(p)
    89  	if goarch.BigEndian {
    90  		return byteorder.BEUint64(q[:])
    91  	}
    92  	return byteorder.LEUint64(q[:])
    93  }
    94  

View as plain text