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