github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/internal/reflectlite/value.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 reflectlite 6 7 import ( 8 "runtime" 9 "unsafe" 10 ) 11 12 const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const 13 14 // Value is the reflection interface to a Go value. 15 // 16 // Not all methods apply to all kinds of values. Restrictions, 17 // if any, are noted in the documentation for each method. 18 // Use the Kind method to find out the kind of value before 19 // calling kind-specific methods. Calling a method 20 // inappropriate to the kind of type causes a run time panic. 21 // 22 // The zero Value represents no value. 23 // Its IsValid method returns false, its Kind method returns Invalid, 24 // its String method returns "<invalid Value>", and all other methods panic. 25 // Most functions and methods never return an invalid value. 26 // If one does, its documentation states the conditions explicitly. 27 // 28 // A Value can be used concurrently by multiple goroutines provided that 29 // the underlying Go value can be used concurrently for the equivalent 30 // direct operations. 31 // 32 // To compare two Values, compare the results of the Interface method. 33 // Using == on two Values does not compare the underlying values 34 // they represent. 35 type Value struct { 36 // typ holds the type of the value represented by a Value. 37 typ *rtype 38 39 // Pointer-valued data or, if flagIndir is set, pointer to data. 40 // Valid when either flagIndir is set or typ.pointers() is true. 41 ptr unsafe.Pointer 42 43 // flag holds metadata about the value. 44 // The lowest bits are flag bits: 45 // - flagStickyRO: obtained via unexported not embedded field, so read-only 46 // - flagEmbedRO: obtained via unexported embedded field, so read-only 47 // - flagIndir: val holds a pointer to the data 48 // - flagAddr: v.CanAddr is true (implies flagIndir) 49 // Value cannot represent method values. 50 // The next five bits give the Kind of the value. 51 // This repeats typ.Kind() except for method values. 52 // The remaining 23+ bits give a method number for method values. 53 // If flag.kind() != Func, code can assume that flagMethod is unset. 54 // If ifaceIndir(typ), code can assume that flagIndir is set. 55 flag 56 57 // A method value represents a curried method invocation 58 // like r.Read for some receiver r. The typ+val+flag bits describe 59 // the receiver r, but the flag's Kind bits say Func (methods are 60 // functions), and the top bits of the flag give the method number 61 // in r's type's method table. 62 } 63 64 type flag uintptr 65 66 const ( 67 flagKindWidth = 5 // there are 27 kinds 68 flagKindMask flag = 1<<flagKindWidth - 1 69 flagStickyRO flag = 1 << 5 70 flagEmbedRO flag = 1 << 6 71 flagIndir flag = 1 << 7 72 flagAddr flag = 1 << 8 73 flagMethod flag = 1 << 9 74 flagMethodFn flag = 1 << 10 // gccgo: first fn parameter is always pointer 75 flagMethodShift = 11 76 flagRO flag = flagStickyRO | flagEmbedRO 77 ) 78 79 func (f flag) kind() Kind { 80 return Kind(f & flagKindMask) 81 } 82 83 func (f flag) ro() flag { 84 if f&flagRO != 0 { 85 return flagStickyRO 86 } 87 return 0 88 } 89 90 // pointer returns the underlying pointer represented by v. 91 // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer 92 func (v Value) pointer() unsafe.Pointer { 93 if v.typ.size != ptrSize || !v.typ.pointers() { 94 panic("can't call pointer on a non-pointer Value") 95 } 96 if v.flag&flagIndir != 0 { 97 return *(*unsafe.Pointer)(v.ptr) 98 } 99 return v.ptr 100 } 101 102 // packEface converts v to the empty interface. 103 func packEface(v Value) interface{} { 104 t := v.typ 105 var i interface{} 106 e := (*emptyInterface)(unsafe.Pointer(&i)) 107 // First, fill in the data portion of the interface. 108 switch { 109 case ifaceIndir(t): 110 if v.flag&flagIndir == 0 { 111 panic("bad indir") 112 } 113 // Value is indirect, and so is the interface we're making. 114 ptr := v.ptr 115 if v.flag&flagAddr != 0 { 116 // TODO: pass safe boolean from valueInterface so 117 // we don't need to copy if safe==true? 118 c := unsafe_New(t) 119 typedmemmove(t, c, ptr) 120 ptr = c 121 } 122 e.word = ptr 123 case v.flag&flagIndir != 0: 124 // Value is indirect, but interface is direct. We need 125 // to load the data at v.ptr into the interface data word. 126 e.word = *(*unsafe.Pointer)(v.ptr) 127 default: 128 // Value is direct, and so is the interface. 129 e.word = v.ptr 130 } 131 // Now, fill in the type portion. We're very careful here not 132 // to have any operation between the e.word and e.typ assignments 133 // that would let the garbage collector observe the partially-built 134 // interface value. 135 e.typ = t 136 return i 137 } 138 139 // unpackEface converts the empty interface i to a Value. 140 func unpackEface(i interface{}) Value { 141 e := (*emptyInterface)(unsafe.Pointer(&i)) 142 // NOTE: don't read e.word until we know whether it is really a pointer or not. 143 t := e.typ 144 if t == nil { 145 return Value{} 146 } 147 f := flag(t.Kind()) 148 if ifaceIndir(t) { 149 f |= flagIndir 150 } 151 return Value{t, e.word, f} 152 } 153 154 // A ValueError occurs when a Value method is invoked on 155 // a Value that does not support it. Such cases are documented 156 // in the description of each method. 157 type ValueError struct { 158 Method string 159 Kind Kind 160 } 161 162 func (e *ValueError) Error() string { 163 return "reflect: call of " + e.Method + " on zero Value" 164 } 165 166 // methodName returns the name of the calling method, 167 // assumed to be two stack frames above. 168 func methodName() string { 169 pc, _, _, _ := runtime.Caller(2) 170 f := runtime.FuncForPC(pc) 171 if f == nil { 172 return "unknown method" 173 } 174 return f.Name() 175 } 176 177 // emptyInterface is the header for an interface{} value. 178 type emptyInterface struct { 179 typ *rtype 180 word unsafe.Pointer 181 } 182 183 // mustBeExported panics if f records that the value was obtained using 184 // an unexported field. 185 func (f flag) mustBeExported() { 186 if f == 0 { 187 panic(&ValueError{methodName(), 0}) 188 } 189 if f&flagRO != 0 { 190 panic("reflect: " + methodName() + " using value obtained using unexported field") 191 } 192 } 193 194 // mustBeAssignable panics if f records that the value is not assignable, 195 // which is to say that either it was obtained using an unexported field 196 // or it is not addressable. 197 func (f flag) mustBeAssignable() { 198 if f == 0 { 199 panic(&ValueError{methodName(), Invalid}) 200 } 201 // Assignable if addressable and not read-only. 202 if f&flagRO != 0 { 203 panic("reflect: " + methodName() + " using value obtained using unexported field") 204 } 205 if f&flagAddr == 0 { 206 panic("reflect: " + methodName() + " using unaddressable value") 207 } 208 } 209 210 // CanSet reports whether the value of v can be changed. 211 // A Value can be changed only if it is addressable and was not 212 // obtained by the use of unexported struct fields. 213 // If CanSet returns false, calling Set or any type-specific 214 // setter (e.g., SetBool, SetInt) will panic. 215 func (v Value) CanSet() bool { 216 return v.flag&(flagAddr|flagRO) == flagAddr 217 } 218 219 // Elem returns the value that the interface v contains 220 // or that the pointer v points to. 221 // It panics if v's Kind is not Interface or Ptr. 222 // It returns the zero Value if v is nil. 223 func (v Value) Elem() Value { 224 k := v.kind() 225 switch k { 226 case Interface: 227 var eface interface{} 228 if v.typ.NumMethod() == 0 { 229 eface = *(*interface{})(v.ptr) 230 } else { 231 eface = (interface{})(*(*interface { 232 M() 233 })(v.ptr)) 234 } 235 x := unpackEface(eface) 236 if x.flag != 0 { 237 x.flag |= v.flag.ro() 238 } 239 return x 240 case Ptr: 241 ptr := v.ptr 242 if v.flag&flagIndir != 0 { 243 ptr = *(*unsafe.Pointer)(ptr) 244 } 245 // The returned value's address is v's value. 246 if ptr == nil { 247 return Value{} 248 } 249 tt := (*ptrType)(unsafe.Pointer(v.typ)) 250 typ := tt.elem 251 fl := v.flag&flagRO | flagIndir | flagAddr 252 fl |= flag(typ.Kind()) 253 return Value{typ, ptr, fl} 254 } 255 panic(&ValueError{"reflectlite.Value.Elem", v.kind()}) 256 } 257 258 func valueInterface(v Value) interface{} { 259 if v.flag == 0 { 260 panic(&ValueError{"reflectlite.Value.Interface", 0}) 261 } 262 263 if v.kind() == Interface { 264 // Special case: return the element inside the interface. 265 // Empty interface has one layout, all interfaces with 266 // methods have a second layout. 267 if v.numMethod() == 0 { 268 return *(*interface{})(v.ptr) 269 } 270 return *(*interface { 271 M() 272 })(v.ptr) 273 } 274 275 // TODO: pass safe to packEface so we don't need to copy if safe==true? 276 return packEface(v) 277 } 278 279 // IsNil reports whether its argument v is nil. The argument must be 280 // a chan, func, interface, map, pointer, or slice value; if it is 281 // not, IsNil panics. Note that IsNil is not always equivalent to a 282 // regular comparison with nil in Go. For example, if v was created 283 // by calling ValueOf with an uninitialized interface variable i, 284 // i==nil will be true but v.IsNil will panic as v will be the zero 285 // Value. 286 func (v Value) IsNil() bool { 287 k := v.kind() 288 switch k { 289 case Chan, Func, Map, Ptr, UnsafePointer: 290 // if v.flag&flagMethod != 0 { 291 // return false 292 // } 293 ptr := v.ptr 294 if v.flag&flagIndir != 0 { 295 ptr = *(*unsafe.Pointer)(ptr) 296 } 297 return ptr == nil 298 case Interface, Slice: 299 // Both interface and slice are nil if first word is 0. 300 // Both are always bigger than a word; assume flagIndir. 301 return *(*unsafe.Pointer)(v.ptr) == nil 302 } 303 panic(&ValueError{"reflectlite.Value.IsNil", v.kind()}) 304 } 305 306 // IsValid reports whether v represents a value. 307 // It returns false if v is the zero Value. 308 // If IsValid returns false, all other methods except String panic. 309 // Most functions and methods never return an invalid Value. 310 // If one does, its documentation states the conditions explicitly. 311 func (v Value) IsValid() bool { 312 return v.flag != 0 313 } 314 315 // Kind returns v's Kind. 316 // If v is the zero Value (IsValid returns false), Kind returns Invalid. 317 func (v Value) Kind() Kind { 318 return v.kind() 319 } 320 321 // implemented in runtime: 322 func chanlen(unsafe.Pointer) int 323 func maplen(unsafe.Pointer) int 324 325 // Len returns v's length. 326 // It panics if v's Kind is not Array, Chan, Map, Slice, or String. 327 func (v Value) Len() int { 328 k := v.kind() 329 switch k { 330 case Array: 331 tt := (*arrayType)(unsafe.Pointer(v.typ)) 332 return int(tt.len) 333 case Chan: 334 return chanlen(v.pointer()) 335 case Map: 336 return maplen(v.pointer()) 337 case Slice: 338 // Slice is bigger than a word; assume flagIndir. 339 return (*sliceHeader)(v.ptr).Len 340 case String: 341 // String is bigger than a word; assume flagIndir. 342 return (*stringHeader)(v.ptr).Len 343 } 344 panic(&ValueError{"reflect.Value.Len", v.kind()}) 345 } 346 347 // NumMethod returns the number of exported methods in the value's method set. 348 func (v Value) numMethod() int { 349 if v.typ == nil { 350 panic(&ValueError{"reflectlite.Value.NumMethod", Invalid}) 351 } 352 return v.typ.NumMethod() 353 } 354 355 // Set assigns x to the value v. 356 // It panics if CanSet returns false. 357 // As in Go, x's value must be assignable to v's type. 358 func (v Value) Set(x Value) { 359 v.mustBeAssignable() 360 x.mustBeExported() // do not let unexported x leak 361 var target unsafe.Pointer 362 if v.kind() == Interface { 363 target = v.ptr 364 } 365 x = x.assignTo("reflectlite.Set", v.typ, target) 366 if x.flag&flagIndir != 0 { 367 typedmemmove(v.typ, v.ptr, x.ptr) 368 } else { 369 *(*unsafe.Pointer)(v.ptr) = x.ptr 370 } 371 } 372 373 // Type returns v's type. 374 func (v Value) Type() Type { 375 f := v.flag 376 if f == 0 { 377 panic(&ValueError{"reflectlite.Value.Type", Invalid}) 378 } 379 // Method values not supported. 380 return v.typ 381 } 382 383 // stringHeader is a safe version of StringHeader used within this package. 384 type stringHeader struct { 385 Data unsafe.Pointer 386 Len int 387 } 388 389 // sliceHeader is a safe version of SliceHeader used within this package. 390 type sliceHeader struct { 391 Data unsafe.Pointer 392 Len int 393 Cap int 394 } 395 396 /* 397 * constructors 398 */ 399 400 // implemented in package runtime 401 func unsafe_New(*rtype) unsafe.Pointer 402 403 // ValueOf returns a new Value initialized to the concrete value 404 // stored in the interface i. ValueOf(nil) returns the zero Value. 405 func ValueOf(i interface{}) Value { 406 if i == nil { 407 return Value{} 408 } 409 410 // TODO: Maybe allow contents of a Value to live on the stack. 411 // For now we make the contents always escape to the heap. It 412 // makes life easier in a few places (see chanrecv/mapassign 413 // comment below). 414 escapes(i) 415 416 return unpackEface(i) 417 } 418 419 // assignTo returns a value v that can be assigned directly to typ. 420 // It panics if v is not assignable to typ. 421 // For a conversion to an interface type, target is a suggested scratch space to use. 422 func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value { 423 // if v.flag&flagMethod != 0 { 424 // v = makeMethodValue(context, v) 425 // } 426 427 switch { 428 case directlyAssignable(dst, v.typ): 429 // Overwrite type so that they match. 430 // Same memory layout, so no harm done. 431 fl := v.flag&(flagAddr|flagIndir) | v.flag.ro() 432 fl |= flag(dst.Kind()) 433 return Value{dst, v.ptr, fl} 434 435 case implements(dst, v.typ): 436 if target == nil { 437 target = unsafe_New(dst) 438 } 439 if v.Kind() == Interface && v.IsNil() { 440 // A nil ReadWriter passed to nil Reader is OK, 441 // but using ifaceE2I below will panic. 442 // Avoid the panic by returning a nil dst (e.g., Reader) explicitly. 443 return Value{dst, nil, flag(Interface)} 444 } 445 x := valueInterface(v) 446 if dst.NumMethod() == 0 { 447 *(*interface{})(target) = x 448 } else { 449 ifaceE2I(dst, x, target) 450 } 451 return Value{dst, target, flagIndir | flag(Interface)} 452 } 453 454 // Failed. 455 panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String()) 456 } 457 458 // arrayAt returns the i-th element of p, 459 // an array whose elements are eltSize bytes wide. 460 // The array pointed at by p must have at least i+1 elements: 461 // it is invalid (but impossible to check here) to pass i >= len, 462 // because then the result will point outside the array. 463 // whySafe must explain why i < len. (Passing "i < len" is fine; 464 // the benefit is to surface this assumption at the call site.) 465 func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer { 466 return add(p, uintptr(i)*eltSize, "i < len") 467 } 468 469 func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer) 470 471 // typedmemmove copies a value of type t to dst from src. 472 //go:noescape 473 func typedmemmove(t *rtype, dst, src unsafe.Pointer) 474 475 // Dummy annotation marking that the value x escapes, 476 // for use in cases where the reflect code is so clever that 477 // the compiler cannot follow. 478 func escapes(x interface{}) { 479 if dummy.b { 480 dummy.x = x 481 } 482 } 483 484 var dummy struct { 485 b bool 486 x interface{} 487 }