github.com/goplus/reflectx@v1.2.2/type.go (about) 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 // Package reflect implements run-time reflection, allowing a program to 6 // manipulate objects with arbitrary types. The typical use is to take a value 7 // with static type interface{} and extract its dynamic type information by 8 // calling TypeOf, which returns a Type. 9 // 10 // A call to ValueOf returns a Value representing the run-time data. 11 // Zero takes a Type and returns a Value representing a zero value 12 // for that type. 13 // 14 // See "The Laws of Reflection" for an introduction to reflection in Go: 15 // https://golang.org/doc/articles/laws_of_reflection.html 16 17 package reflectx 18 19 import ( 20 "reflect" 21 "unsafe" 22 ) 23 24 //go:linkname haveIdenticalUnderlyingType reflect.haveIdenticalUnderlyingType 25 func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool 26 27 //go:linkname haveIdenticalType reflect.haveIdenticalType 28 func haveIdenticalType(T, V reflect.Type, cmpTags bool) bool 29 30 // memmove copies size bytes to dst from src. No write barriers are used. 31 //go:noescape 32 //go:linkname memmove reflect.memmove 33 func memmove(dst, src unsafe.Pointer, size uintptr) 34 35 // typedmemmove copies a value of type t to dst from src. 36 //go:noescape 37 //go:linkname typedmemmove reflect.typedmemmove 38 func typedmemmove(t *rtype, dst, src unsafe.Pointer) 39 40 // resolveTypeOff resolves an *rtype offset from a base type. 41 // The (*rtype).typeOff method is a convenience wrapper for this function. 42 // Implemented in the runtime package. 43 //go:linkname resolveTypeOff reflect.resolveTypeOff 44 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer 45 46 // resolveTextOff resolves a function pointer offset from a base type. 47 // The (*rtype).textOff method is a convenience wrapper for this function. 48 // Implemented in the runtime package. 49 //go:linkname resolveTextOff reflect.resolveTextOff 50 func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer 51 52 // addReflectOff adds a pointer to the reflection lookup map in the runtime. 53 // It returns a new ID that can be used as a typeOff or textOff, and will 54 // be resolved correctly. Implemented in the runtime package. 55 //go:linkname addReflectOff reflect.addReflectOff 56 func addReflectOff(ptr unsafe.Pointer) int32 57 58 //go:linkname newName reflect.newName 59 func newName(n, tag string, exported bool) name 60 61 // resolveReflectName adds a name to the reflection lookup map in the runtime. 62 // It returns a new nameOff that can be used to refer to the pointer. 63 //go:linkname resolveReflectName reflect.resolveReflectName 64 func resolveReflectName(n name) nameOff 65 66 //go:linkname toType reflect.toType 67 func toType(t *rtype) reflect.Type 68 69 //go:linkname rtype_nameOff reflect.(*rtype).nameOff 70 func rtype_nameOff(t *rtype, off nameOff) name 71 72 //go:linkname rtype_typeOff reflect.(*rtype).typeOff 73 func rtype_typeOff(t *rtype, off typeOff) *rtype 74 75 //go:linkname rtype_textOff reflect.(*rtype).textOff 76 func rtype_textOff(t *rtype, off textOff) unsafe.Pointer 77 78 func (t *rtype) nameOff(off nameOff) name { 79 return rtype_nameOff(t, off) 80 } 81 82 func (t *rtype) typeOff(off typeOff) *rtype { 83 return rtype_typeOff(t, off) 84 } 85 86 func (t *rtype) textOff(off textOff) unsafe.Pointer { 87 return rtype_textOff(t, off) 88 } 89 90 // resolveReflectType adds a *rtype to the reflection lookup map in the runtime. 91 // It returns a new typeOff that can be used to refer to the pointer. 92 func resolveReflectType(t *rtype) typeOff { 93 return typeOff(addReflectOff(unsafe.Pointer(t))) 94 } 95 96 // resolveReflectText adds a function pointer to the reflection lookup map in 97 // the runtime. It returns a new textOff that can be used to refer to the 98 // pointer. 99 func resolveReflectText(ptr unsafe.Pointer) textOff { 100 return textOff(addReflectOff(ptr)) 101 } 102 103 type nameOff int32 104 type typeOff int32 105 type textOff int32 106 107 // Method on non-interface type 108 type method struct { 109 name nameOff // name of method 110 mtyp typeOff // method type (without receiver) 111 ifn textOff // fn used in interface call (one-word receiver) 112 tfn textOff // fn used for normal method call 113 } 114 115 type structTypeUncommon struct { 116 structType 117 u uncommonType 118 } 119 120 type tflag uint8 121 122 const ( 123 // tflagUncommon means that there is a pointer, *uncommonType, 124 // just beyond the outer type structure. 125 // 126 // For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0, 127 // then t has uncommonType data and it can be accessed as: 128 // 129 // type tUncommon struct { 130 // structType 131 // u uncommonType 132 // } 133 // u := &(*tUncommon)(unsafe.Pointer(t)).u 134 tflagUncommon tflag = 1 << 0 135 136 // tflagExtraStar means the name in the str field has an 137 // extraneous '*' prefix. This is because for most types T in 138 // a program, the type *T also exists and reusing the str data 139 // saves binary size. 140 tflagExtraStar tflag = 1 << 1 141 142 // tflagNamed means the type has a name. 143 tflagNamed tflag = 1 << 2 144 145 // tflagRegularMemory means that equal and hash functions can treat 146 // this type as a single region of t.size bytes. 147 tflagRegularMemory tflag = 1 << 3 148 149 // tflagUserMethod means the type has reflctx user methods 150 tflagUserMethod tflag = 1 << 7 151 ) 152 153 type rtype struct { 154 size uintptr 155 ptrdata uintptr // number of bytes in the type that can contain pointers 156 hash uint32 // hash of type; avoids computation in hash tables 157 tflag tflag // extra type information flags 158 align uint8 // alignment of variable with this type 159 fieldAlign uint8 // alignment of struct field with this type 160 kind uint8 // enumeration for C 161 // function for comparing objects of this type 162 // (ptr to object A, ptr to object B) -> ==? 163 equal func(unsafe.Pointer, unsafe.Pointer) bool 164 gcdata *byte // garbage collection data 165 str nameOff // string form 166 ptrToThis typeOff // type for pointer to this type, may be zero 167 } 168 169 const ( 170 kindDirectIface = 1 << 5 171 kindGCProg = 1 << 6 // Type.gc points to GC program 172 kindMask = (1 << 5) - 1 173 ) 174 175 func (t *rtype) Kind() reflect.Kind { 176 return reflect.Kind(t.kind & kindMask) 177 } 178 179 // add returns p+x. 180 // 181 // The whySafe string is ignored, so that the function still inlines 182 // as efficiently as p+x, but all call sites should use the string to 183 // record why the addition is safe, which is to say why the addition 184 // does not cause x to advance to the very end of p's allocation 185 // and therefore point incorrectly at the next block in memory. 186 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { 187 return unsafe.Pointer(uintptr(p) + x) 188 } 189 190 // stringHeader is a safe version of StringHeader used within this package. 191 type stringHeader struct { 192 Data unsafe.Pointer 193 Len int 194 } 195 196 // ChanDir represents a channel type's direction. 197 type ChanDir int 198 199 const ( 200 RecvDir ChanDir = 1 << iota // <-chan 201 SendDir // chan<- 202 BothDir = RecvDir | SendDir // chan 203 ) 204 205 // arrayType represents a fixed array type. 206 type arrayType struct { 207 rtype 208 elem *rtype // array element type 209 slice *rtype // slice type 210 len uintptr 211 } 212 213 // chanType represents a channel type. 214 type chanType struct { 215 rtype 216 elem *rtype // channel element type 217 dir uintptr // channel direction (ChanDir) 218 } 219 220 // imethod represents a method on an interface type 221 type imethod struct { 222 name nameOff // name of method 223 typ typeOff // .(*FuncType) underneath 224 } 225 226 // interfaceType represents an interface type. 227 type interfaceType struct { 228 rtype 229 pkgPath name // import path 230 methods []imethod // sorted by hash 231 } 232 233 // mapType represents a map type. 234 type mapType struct { 235 rtype 236 key *rtype // map key type 237 elem *rtype // map element (value) type 238 bucket *rtype // internal bucket structure 239 // function for hashing keys (ptr to key, seed) -> hash 240 hasher func(unsafe.Pointer, uintptr) uintptr 241 keysize uint8 // size of key slot 242 valuesize uint8 // size of value slot 243 bucketsize uint16 // size of bucket 244 flags uint32 245 } 246 247 // ptrType represents a pointer type. 248 type ptrType struct { 249 rtype 250 elem *rtype // pointer element (pointed at) type 251 } 252 253 // sliceType represents a slice type. 254 type sliceType struct { 255 rtype 256 elem *rtype // slice element type 257 } 258 259 // structType represents a struct type. 260 type structType struct { 261 rtype 262 pkgPath name 263 fields []structField // sorted by offset 264 } 265 266 // go/src/cmd/compile/internal/gc/alg.go#algtype1 267 // IsRegularMemory reports whether t can be compared/hashed as regular memory. 268 func isRegularMemory(t reflect.Type) bool { 269 switch t.Kind() { 270 case reflect.Func, reflect.Map, reflect.Slice, reflect.String, reflect.Interface: 271 return false 272 case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: 273 return false 274 case reflect.Array: 275 b := isRegularMemory(t.Elem()) 276 if b { 277 return true 278 } 279 if t.Len() == 0 { 280 return true 281 } 282 return b 283 case reflect.Struct: 284 n := t.NumField() 285 switch n { 286 case 0: 287 return true 288 case 1: 289 f := t.Field(0) 290 if f.Name == "_" { 291 return false 292 } 293 return isRegularMemory(f.Type) 294 default: 295 for i := 0; i < n; i++ { 296 f := t.Field(i) 297 if f.Name == "_" || !isRegularMemory(f.Type) || ispaddedfield(t, i) { 298 return false 299 } 300 } 301 } 302 } 303 return true 304 } 305 306 // ispaddedfield reports whether the i'th field of struct type t is followed 307 // by padding. 308 func ispaddedfield(t reflect.Type, i int) bool { 309 end := t.Size() 310 if i+1 < t.NumField() { 311 end = t.Field(i + 1).Offset 312 } 313 fd := t.Field(i) 314 return fd.Offset+fd.Type.Size() != end 315 }