1// Copyright 2009 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// Runtime type representation. 6 7package runtime 8 9import ( 10 "runtime/internal/atomic" 11 "runtime/internal/sys" 12 "unsafe" 13) 14 15// tflag is documented in reflect/type.go. 16// 17// tflag values must be kept in sync with copies in: 18// go/types.cc 19// reflect/type.go 20// internal/reflectlite/type.go 21type tflag uint8 22 23const ( 24 tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes 25) 26 27type _type struct { 28 size uintptr 29 ptrdata uintptr 30 hash uint32 31 tflag tflag 32 align uint8 33 fieldAlign uint8 34 kind uint8 35 // function for comparing objects of this type 36 // (ptr to object A, ptr to object B) -> ==? 37 equal func(unsafe.Pointer, unsafe.Pointer) bool 38 // gcdata stores the GC type data for the garbage collector. 39 // If the KindGCProg bit is set in kind, gcdata is a GC program. 40 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 41 gcdata *byte 42 _string *string 43 *uncommontype 44 ptrToThis *_type 45} 46 47func (t *_type) string() string { 48 return *t._string 49} 50 51// pkgpath returns the path of the package where t was defined, if 52// available. This is not the same as the reflect package's PkgPath 53// method, in that it returns the package path for struct and interface 54// types, not just named types. 55func (t *_type) pkgpath() string { 56 if u := t.uncommontype; u != nil { 57 if u.pkgPath == nil { 58 return "" 59 } 60 return *u.pkgPath 61 } 62 return "" 63} 64 65type method struct { 66 name *string 67 pkgPath *string 68 mtyp *_type 69 typ *_type 70 tfn unsafe.Pointer 71} 72 73type uncommontype struct { 74 name *string 75 pkgPath *string 76 methods []method 77} 78 79type imethod struct { 80 name *string 81 pkgPath *string 82 typ *_type 83} 84 85type interfacetype struct { 86 typ _type 87 methods []imethod 88} 89 90type maptype struct { 91 typ _type 92 key *_type 93 elem *_type 94 bucket *_type // internal type representing a hash bucket 95 // function for hashing keys (ptr to key, seed) -> hash 96 hasher func(unsafe.Pointer, uintptr) uintptr 97 keysize uint8 // size of key slot 98 elemsize uint8 // size of elem slot 99 bucketsize uint16 // size of bucket 100 flags uint32 101} 102 103// Note: flag values must match those used in the TMAP case 104// in ../cmd/compile/internal/gc/reflect.go:dtypesym. 105func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself 106 return mt.flags&1 != 0 107} 108func (mt *maptype) indirectelem() bool { // store ptr to elem instead of elem itself 109 return mt.flags&2 != 0 110} 111func (mt *maptype) reflexivekey() bool { // true if k==k for all keys 112 return mt.flags&4 != 0 113} 114func (mt *maptype) needkeyupdate() bool { // true if we need to update key on an overwrite 115 return mt.flags&8 != 0 116} 117func (mt *maptype) hashMightPanic() bool { // true if hash function might panic 118 return mt.flags&16 != 0 119} 120 121type arraytype struct { 122 typ _type 123 elem *_type 124 slice *_type 125 len uintptr 126} 127 128type chantype struct { 129 typ _type 130 elem *_type 131 dir uintptr 132} 133 134type slicetype struct { 135 typ _type 136 elem *_type 137} 138 139type functype struct { 140 typ _type 141 dotdotdot bool 142 in []*_type 143 out []*_type 144} 145 146type ptrtype struct { 147 typ _type 148 elem *_type 149} 150 151type structfield struct { 152 name *string // nil for embedded fields 153 pkgPath *string // nil for exported Names; otherwise import path 154 typ *_type // type of field 155 tag *string // nil if no tag 156 offsetAnon uintptr // byte offset of field<<1 | isAnonymous 157} 158 159func (f *structfield) offset() uintptr { 160 return f.offsetAnon >> 1 161} 162 163func (f *structfield) anon() bool { 164 return f.offsetAnon&1 != 0 165} 166 167type structtype struct { 168 typ _type 169 fields []structfield 170} 171 172// typeDescriptorList holds a list of type descriptors generated 173// by the compiler. This is used for the compiler to register 174// type descriptors to the runtime. 175// The layout is known to the compiler. 176//go:notinheap 177type typeDescriptorList struct { 178 count int 179 types [1]uintptr // variable length 180} 181 182// typelist holds all type descriptors generated by the comiler. 183// This is for the reflect package to deduplicate type descriptors 184// when it creates a type that is also a compiler-generated type. 185var typelist struct { 186 initialized uint32 187 lists []*typeDescriptorList // one element per package 188 types map[string]uintptr // map from a type's string to *_type, lazily populated 189 // TODO: use a sorted array instead? 190} 191var typelistLock mutex 192 193// The compiler generates a call of this function in the main 194// package's init function, to register compiler-generated 195// type descriptors. 196// p points to a list of *typeDescriptorList, n is the length 197// of the list. 198//go:linkname registerTypeDescriptors 199func registerTypeDescriptors(n int, p unsafe.Pointer) { 200 *(*slice)(unsafe.Pointer(&typelist.lists)) = slice{p, n, n} 201} 202 203// The reflect package uses this function to look up a compiler- 204// generated type descriptor. 205//go:linkname reflect_lookupType reflect.lookupType 206func reflect_lookupType(s string) *_type { 207 // Lazy initialization. We don't need to do this if we never create 208 // types through reflection. 209 if atomic.Load(&typelist.initialized) == 0 { 210 lock(&typelistLock) 211 if atomic.Load(&typelist.initialized) == 0 { 212 n := 0 213 for _, list := range typelist.lists { 214 n += list.count 215 } 216 typelist.types = make(map[string]uintptr, n) 217 for _, list := range typelist.lists { 218 for i := 0; i < list.count; i++ { 219 typ := *(**_type)(add(unsafe.Pointer(&list.types), uintptr(i)*sys.PtrSize)) 220 typelist.types[typ.string()] = uintptr(unsafe.Pointer(typ)) 221 } 222 } 223 atomic.Store(&typelist.initialized, 1) 224 } 225 unlock(&typelistLock) 226 } 227 228 return (*_type)(unsafe.Pointer(typelist.types[s])) 229} 230