github.com/cockroachdb/swiss@v0.0.0-20240303172742-c161743eb608/runtime_go1.20.go (about) 1 // Copyright 2024 The Cockroach Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // This file introspects into Go runtime internals. In order to prevent 16 // accidental breakage when a new version of Go is released we require manual 17 // bumping of the go versions supported by adjusting the build tags below. The 18 // way go version tags work the tag for goX.Y will be declared for every 19 // subsequent release. So go1.20 will be defined for go1.21, go1.22, etc. The 20 // build tag "go1.20 && !go1.23" defines the range [go1.20, go1.23) (inclusive 21 // on go1.20, exclusive on go1.23). 22 23 //go:build go1.20 && !go1.23 24 25 package swiss 26 27 import "unsafe" 28 29 //go:linkname fastrand64 runtime.fastrand64 30 func fastrand64() uint64 31 32 type hashFn func(key unsafe.Pointer, seed uintptr) uintptr 33 34 // getRuntimeHasher peeks inside the internals of map[K]struct{} and extracts 35 // the function the runtime generated for hashing type K. This is a bit hacky, 36 // but we can't use hash/maphash as that hashes only bytes and strings. While 37 // we could use unsafe.{Slice,String} to pass in arbitrary structs we can't 38 // pass in arbitrary types and have the hash function sometimes hash the type 39 // memory and sometimes hash underlying. 40 // 41 // NOTE(peter): I did try using reflection on the type K to specialize a hash 42 // function depending on the type's Kind, but that was measurably slower than 43 // for integer types. This hackiness is quite localized. If it breaks in a 44 // future Go version we can either repair it or go the reflection route. 45 // 46 // https://github.com/dolthub/maphash provided the inspiration and general 47 // implementation technique. 48 func getRuntimeHasher[K comparable]() hashFn { 49 a := any((map[K]struct{})(nil)) 50 return (*rtEface)(unsafe.Pointer(&a)).typ.Hasher 51 } 52 53 // From runtime/runtime2.go:eface 54 type rtEface struct { 55 typ *rtMapType 56 data unsafe.Pointer 57 } 58 59 // From internal/abi/type.go:MapType 60 type rtMapType struct { 61 rtType 62 Key *rtType 63 Elem *rtType 64 Bucket *rtType // internal type representing a hash bucket 65 // function for hashing keys (ptr to key, seed) -> hash 66 Hasher func(unsafe.Pointer, uintptr) uintptr 67 KeySize uint8 // size of key slot 68 ValueSize uint8 // size of elem slot 69 BucketSize uint16 // size of bucket 70 Flags uint32 71 } 72 73 type rtTFlag uint8 74 type rtNameOff int32 75 type rtTypeOff int32 76 77 // From internal/abi/type.go:Type 78 type rtType struct { 79 Size_ uintptr 80 PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers 81 Hash uint32 // hash of type; avoids computation in hash tables 82 TFlag rtTFlag // extra type information flags 83 Align_ uint8 // alignment of variable with this type 84 FieldAlign_ uint8 // alignment of struct field with this type 85 Kind_ uint8 // enumeration for C 86 // function for comparing objects of this type 87 // (ptr to object A, ptr to object B) -> ==? 88 Equal func(unsafe.Pointer, unsafe.Pointer) bool 89 // GCData stores the GC type data for the garbage collector. 90 // If the KindGCProg bit is set in kind, GCData is a GC program. 91 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 92 GCData *byte 93 Str rtNameOff // string form 94 PtrToThis rtTypeOff // type for pointer to this type, may be zero 95 }