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