github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/runtime/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 // Runtime type representation. 6 7 package runtime 8 9 import ( 10 "runtime/internal/sys" 11 "unsafe" 12 ) 13 14 // tflag is documented in ../reflect/type.go. 15 type tflag uint8 16 17 const tflagUncommon tflag = 1 18 19 // Needs to be in sync with ../cmd/compile/internal/ld/decodesym.go:/^func.commonsize, 20 // ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and 21 // ../reflect/type.go:/^type.rtype. 22 type _type struct { 23 size uintptr 24 ptrdata uintptr // size of memory prefix holding all pointers 25 hash uint32 26 tflag tflag 27 align uint8 28 fieldalign uint8 29 kind uint8 30 alg *typeAlg 31 // gcdata stores the GC type data for the garbage collector. 32 // If the KindGCProg bit is set in kind, gcdata is a GC program. 33 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 34 gcdata *byte 35 _string string 36 } 37 38 func (t *_type) uncommon() *uncommontype { 39 if t.tflag&tflagUncommon == 0 { 40 return nil 41 } 42 switch t.kind & kindMask { 43 case kindStruct: 44 type u struct { 45 structtype 46 u uncommontype 47 } 48 return &(*u)(unsafe.Pointer(t)).u 49 case kindPtr: 50 type u struct { 51 ptrtype 52 u uncommontype 53 } 54 return &(*u)(unsafe.Pointer(t)).u 55 case kindFunc: 56 type u struct { 57 functype 58 u uncommontype 59 } 60 return &(*u)(unsafe.Pointer(t)).u 61 case kindSlice: 62 type u struct { 63 slicetype 64 u uncommontype 65 } 66 return &(*u)(unsafe.Pointer(t)).u 67 case kindArray: 68 type u struct { 69 arraytype 70 u uncommontype 71 } 72 return &(*u)(unsafe.Pointer(t)).u 73 case kindChan: 74 type u struct { 75 chantype 76 u uncommontype 77 } 78 return &(*u)(unsafe.Pointer(t)).u 79 case kindMap: 80 type u struct { 81 maptype 82 u uncommontype 83 } 84 return &(*u)(unsafe.Pointer(t)).u 85 case kindInterface: 86 type u struct { 87 interfacetype 88 u uncommontype 89 } 90 return &(*u)(unsafe.Pointer(t)).u 91 default: 92 type u struct { 93 _type 94 u uncommontype 95 } 96 return &(*u)(unsafe.Pointer(t)).u 97 } 98 } 99 100 func hasPrefix(s, prefix string) bool { 101 return len(s) >= len(prefix) && s[:len(prefix)] == prefix 102 } 103 104 func (t *_type) name() string { 105 if hasPrefix(t._string, "map[") { 106 return "" 107 } 108 if hasPrefix(t._string, "struct {") { 109 return "" 110 } 111 if hasPrefix(t._string, "chan ") { 112 return "" 113 } 114 if hasPrefix(t._string, "chan<-") { 115 return "" 116 } 117 if hasPrefix(t._string, "func(") { 118 return "" 119 } 120 switch t._string[0] { 121 case '[', '*', '<': 122 return "" 123 } 124 i := len(t._string) - 1 125 for i >= 0 { 126 if t._string[i] == '.' { 127 break 128 } 129 i-- 130 } 131 return t._string[i+1:] 132 } 133 134 func (t *functype) in() []*_type { 135 // See funcType in reflect/type.go for details on data layout. 136 uadd := uintptr(unsafe.Sizeof(functype{})) 137 if t.typ.tflag&tflagUncommon != 0 { 138 uadd += unsafe.Sizeof(uncommontype{}) 139 } 140 return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[:t.inCount] 141 } 142 143 func (t *functype) out() []*_type { 144 // See funcType in reflect/type.go for details on data layout. 145 uadd := uintptr(unsafe.Sizeof(functype{})) 146 if t.typ.tflag&tflagUncommon != 0 { 147 uadd += unsafe.Sizeof(uncommontype{}) 148 } 149 outCount := t.outCount & (1<<15 - 1) 150 return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount] 151 } 152 153 func (t *functype) dotdotdot() bool { 154 return t.outCount&(1<<15) != 0 155 } 156 157 type method struct { 158 name name 159 mtyp *_type 160 ifn unsafe.Pointer 161 tfn unsafe.Pointer 162 } 163 164 type uncommontype struct { 165 pkgpath *string 166 mhdr []method 167 } 168 169 type imethod struct { 170 name name 171 _type *_type 172 } 173 174 type interfacetype struct { 175 typ _type 176 pkgpath *string 177 mhdr []imethod 178 } 179 180 type maptype struct { 181 typ _type 182 key *_type 183 elem *_type 184 bucket *_type // internal type representing a hash bucket 185 hmap *_type // internal type representing a hmap 186 keysize uint8 // size of key slot 187 indirectkey bool // store ptr to key instead of key itself 188 valuesize uint8 // size of value slot 189 indirectvalue bool // store ptr to value instead of value itself 190 bucketsize uint16 // size of bucket 191 reflexivekey bool // true if k==k for all keys 192 needkeyupdate bool // true if we need to update key on an overwrite 193 } 194 195 type arraytype struct { 196 typ _type 197 elem *_type 198 slice *_type 199 len uintptr 200 } 201 202 type chantype struct { 203 typ _type 204 elem *_type 205 dir uintptr 206 } 207 208 type slicetype struct { 209 typ _type 210 elem *_type 211 } 212 213 type functype struct { 214 typ _type 215 inCount uint16 216 outCount uint16 217 } 218 219 type ptrtype struct { 220 typ _type 221 elem *_type 222 } 223 224 type structfield struct { 225 name name 226 typ *_type 227 offset uintptr 228 } 229 230 type structtype struct { 231 typ _type 232 pkgPath *string 233 fields []structfield 234 } 235 236 // name is an encoded type name with optional extra data. 237 // See reflect/type.go for details. 238 type name struct { 239 bytes *byte 240 } 241 242 func (n *name) data(off int) *byte { 243 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off))) 244 } 245 246 func (n *name) isExported() bool { 247 return (*n.bytes)&(1<<0) != 0 248 } 249 250 func (n *name) nameLen() int { 251 return int(uint16(*n.data(1))<<8 | uint16(*n.data(2))) 252 } 253 254 func (n *name) tagLen() int { 255 if *n.data(0)&(1<<1) == 0 { 256 return 0 257 } 258 off := 3 + n.nameLen() 259 return int(uint16(*n.data(off))<<8 | uint16(*n.data(off + 1))) 260 } 261 262 func (n *name) name() (s string) { 263 nl := n.nameLen() 264 if nl == 0 { 265 return "" 266 } 267 hdr := (*stringStruct)(unsafe.Pointer(&s)) 268 hdr.str = unsafe.Pointer(n.data(3)) 269 hdr.len = nl 270 return s 271 } 272 273 func (n *name) pkgPath() *string { 274 if *n.data(0)&(1<<2) == 0 { 275 return nil 276 } 277 off := 3 + n.nameLen() 278 if tl := n.tagLen(); tl > 0 { 279 off += 2 + tl 280 } 281 off = int(round(uintptr(off), sys.PtrSize)) 282 return *(**string)(unsafe.Pointer(n.data(off))) 283 }