github.com/bir3/gocompiler@v0.9.2202/src/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 "github.com/bir3/gocompiler/src/internal/abi" 9 "github.com/bir3/gocompiler/src/internal/goarch" 10 "github.com/bir3/gocompiler/src/internal/unsafeheader" 11 "runtime" 12 "unsafe" 13 ) 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 // Access using the typ method to avoid escape of v. 39 typ_ *abi.Type 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 func (v Value) typ() *abi.Type { 92 // Types are either static (for compiler-created types) or 93 // heap-allocated but always reachable (for reflection-created 94 // types, held in the central map). So there is no need to 95 // escape types. noescape here help avoid unnecessary escape 96 // of v. 97 return (*abi.Type)(noescape(unsafe.Pointer(v.typ_))) 98 } 99 100 // pointer returns the underlying pointer represented by v. 101 // v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer 102 func (v Value) pointer() unsafe.Pointer { 103 if v.typ().Size() != goarch.PtrSize || !v.typ().Pointers() { 104 panic("can't call pointer on a non-pointer Value") 105 } 106 if v.flag&flagIndir != 0 { 107 return *(*unsafe.Pointer)(v.ptr) 108 } 109 return v.ptr 110 } 111 112 // packEface converts v to the empty interface. 113 func packEface(v Value) any { 114 t := v.typ() 115 var i any 116 e := (*emptyInterface)(unsafe.Pointer(&i)) 117 // First, fill in the data portion of the interface. 118 switch { 119 case ifaceIndir(t): 120 if v.flag&flagIndir == 0 { 121 panic("bad indir") 122 } 123 // Value is indirect, and so is the interface we're making. 124 ptr := v.ptr 125 if v.flag&flagAddr != 0 { 126 // TODO: pass safe boolean from valueInterface so 127 // we don't need to copy if safe==true? 128 c := unsafe_New(t) 129 typedmemmove(t, c, ptr) 130 ptr = c 131 } 132 e.word = ptr 133 case v.flag&flagIndir != 0: 134 // Value is indirect, but interface is direct. We need 135 // to load the data at v.ptr into the interface data word. 136 e.word = *(*unsafe.Pointer)(v.ptr) 137 default: 138 // Value is direct, and so is the interface. 139 e.word = v.ptr 140 } 141 // Now, fill in the type portion. We're very careful here not 142 // to have any operation between the e.word and e.typ assignments 143 // that would let the garbage collector observe the partially-built 144 // interface value. 145 e.typ = t 146 return i 147 } 148 149 // unpackEface converts the empty interface i to a Value. 150 func unpackEface(i any) Value { 151 e := (*emptyInterface)(unsafe.Pointer(&i)) 152 // NOTE: don't read e.word until we know whether it is really a pointer or not. 153 t := e.typ 154 if t == nil { 155 return Value{} 156 } 157 f := flag(t.Kind()) 158 if ifaceIndir(t) { 159 f |= flagIndir 160 } 161 return Value{t, e.word, f} 162 } 163 164 // A ValueError occurs when a Value method is invoked on 165 // a Value that does not support it. Such cases are documented 166 // in the description of each method. 167 type ValueError struct { 168 Method string 169 Kind Kind 170 } 171 172 func (e *ValueError) Error() string { 173 if e.Kind == 0 { 174 return "reflect: call of " + e.Method + " on zero Value" 175 } 176 return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value" 177 } 178 179 // methodName returns the name of the calling method, 180 // assumed to be two stack frames above. 181 func methodName() string { 182 pc, _, _, _ := runtime.Caller(2) 183 f := runtime.FuncForPC(pc) 184 if f == nil { 185 return "unknown method" 186 } 187 return f.Name() 188 } 189 190 // emptyInterface is the header for an interface{} value. 191 type emptyInterface struct { 192 typ *abi.Type 193 word unsafe.Pointer 194 } 195 196 // mustBeExported panics if f records that the value was obtained using 197 // an unexported field. 198 func (f flag) mustBeExported() { 199 if f == 0 { 200 panic(&ValueError{methodName(), 0}) 201 } 202 if f&flagRO != 0 { 203 panic("reflect: " + methodName() + " using value obtained using unexported field") 204 } 205 } 206 207 // mustBeAssignable panics if f records that the value is not assignable, 208 // which is to say that either it was obtained using an unexported field 209 // or it is not addressable. 210 func (f flag) mustBeAssignable() { 211 if f == 0 { 212 panic(&ValueError{methodName(), abi.Invalid}) 213 } 214 // Assignable if addressable and not read-only. 215 if f&flagRO != 0 { 216 panic("reflect: " + methodName() + " using value obtained using unexported field") 217 } 218 if f&flagAddr == 0 { 219 panic("reflect: " + methodName() + " using unaddressable value") 220 } 221 } 222 223 // CanSet reports whether the value of v can be changed. 224 // A Value can be changed only if it is addressable and was not 225 // obtained by the use of unexported struct fields. 226 // If CanSet returns false, calling Set or any type-specific 227 // setter (e.g., SetBool, SetInt) will panic. 228 func (v Value) CanSet() bool { 229 return v.flag&(flagAddr|flagRO) == flagAddr 230 } 231 232 // Elem returns the value that the interface v contains 233 // or that the pointer v points to. 234 // It panics if v's Kind is not Interface or Pointer. 235 // It returns the zero Value if v is nil. 236 func (v Value) Elem() Value { 237 k := v.kind() 238 switch k { 239 case abi.Interface: 240 var eface any 241 if v.typ().NumMethod() == 0 { 242 eface = *(*any)(v.ptr) 243 } else { 244 eface = (any)(*(*interface { 245 M() 246 })(v.ptr)) 247 } 248 x := unpackEface(eface) 249 if x.flag != 0 { 250 x.flag |= v.flag.ro() 251 } 252 return x 253 case abi.Pointer: 254 ptr := v.ptr 255 if v.flag&flagIndir != 0 { 256 ptr = *(*unsafe.Pointer)(ptr) 257 } 258 // The returned value's address is v's value. 259 if ptr == nil { 260 return Value{} 261 } 262 tt := (*ptrType)(unsafe.Pointer(v.typ())) 263 typ := tt.Elem 264 fl := v.flag&flagRO | flagIndir | flagAddr 265 fl |= flag(typ.Kind()) 266 return Value{typ, ptr, fl} 267 } 268 panic(&ValueError{"reflectlite.Value.Elem", v.kind()}) 269 } 270 271 func valueInterface(v Value) any { 272 if v.flag == 0 { 273 panic(&ValueError{"reflectlite.Value.Interface", 0}) 274 } 275 276 if v.kind() == abi.Interface { 277 // Special case: return the element inside the interface. 278 // Empty interface has one layout, all interfaces with 279 // methods have a second layout. 280 if v.numMethod() == 0 { 281 return *(*any)(v.ptr) 282 } 283 return *(*interface { 284 M() 285 })(v.ptr) 286 } 287 288 // TODO: pass safe to packEface so we don't need to copy if safe==true? 289 return packEface(v) 290 } 291 292 // IsNil reports whether its argument v is nil. The argument must be 293 // a chan, func, interface, map, pointer, or slice value; if it is 294 // not, IsNil panics. Note that IsNil is not always equivalent to a 295 // regular comparison with nil in Go. For example, if v was created 296 // by calling ValueOf with an uninitialized interface variable i, 297 // i==nil will be true but v.IsNil will panic as v will be the zero 298 // Value. 299 func (v Value) IsNil() bool { 300 k := v.kind() 301 switch k { 302 case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer: 303 // if v.flag&flagMethod != 0 { 304 // return false 305 // } 306 ptr := v.ptr 307 if v.flag&flagIndir != 0 { 308 ptr = *(*unsafe.Pointer)(ptr) 309 } 310 return ptr == nil 311 case abi.Interface, abi.Slice: 312 // Both interface and slice are nil if first word is 0. 313 // Both are always bigger than a word; assume flagIndir. 314 return *(*unsafe.Pointer)(v.ptr) == nil 315 } 316 panic(&ValueError{"reflectlite.Value.IsNil", v.kind()}) 317 } 318 319 // IsValid reports whether v represents a value. 320 // It returns false if v is the zero Value. 321 // If IsValid returns false, all other methods except String panic. 322 // Most functions and methods never return an invalid Value. 323 // If one does, its documentation states the conditions explicitly. 324 func (v Value) IsValid() bool { 325 return v.flag != 0 326 } 327 328 // Kind returns v's Kind. 329 // If v is the zero Value (IsValid returns false), Kind returns Invalid. 330 func (v Value) Kind() Kind { 331 return v.kind() 332 } 333 334 // implemented in runtime: 335 336 //go:noescape 337 func chanlen(unsafe.Pointer) int 338 339 //go:noescape 340 func maplen(unsafe.Pointer) int 341 342 // Len returns v's length. 343 // It panics if v's Kind is not Array, Chan, Map, Slice, or String. 344 func (v Value) Len() int { 345 k := v.kind() 346 switch k { 347 case abi.Array: 348 tt := (*arrayType)(unsafe.Pointer(v.typ())) 349 return int(tt.Len) 350 case abi.Chan: 351 return chanlen(v.pointer()) 352 case abi.Map: 353 return maplen(v.pointer()) 354 case abi.Slice: 355 // Slice is bigger than a word; assume flagIndir. 356 return (*unsafeheader.Slice)(v.ptr).Len 357 case abi.String: 358 // String is bigger than a word; assume flagIndir. 359 return (*unsafeheader.String)(v.ptr).Len 360 } 361 panic(&ValueError{"reflect.Value.Len", v.kind()}) 362 } 363 364 // NumMethod returns the number of exported methods in the value's method set. 365 func (v Value) numMethod() int { 366 if v.typ() == nil { 367 panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid}) 368 } 369 return v.typ().NumMethod() 370 } 371 372 // Set assigns x to the value v. 373 // It panics if CanSet returns false. 374 // As in Go, x's value must be assignable to v's type. 375 func (v Value) Set(x Value) { 376 v.mustBeAssignable() 377 x.mustBeExported() // do not let unexported x leak 378 var target unsafe.Pointer 379 if v.kind() == abi.Interface { 380 target = v.ptr 381 } 382 x = x.assignTo("reflectlite.Set", v.typ(), target) 383 if x.flag&flagIndir != 0 { 384 typedmemmove(v.typ(), v.ptr, x.ptr) 385 } else { 386 *(*unsafe.Pointer)(v.ptr) = x.ptr 387 } 388 } 389 390 // Type returns v's type. 391 func (v Value) Type() Type { 392 f := v.flag 393 if f == 0 { 394 panic(&ValueError{"reflectlite.Value.Type", abi.Invalid}) 395 } 396 // Method values not supported. 397 return toRType(v.typ()) 398 } 399 400 /* 401 * constructors 402 */ 403 404 // implemented in package runtime 405 406 //go:noescape 407 func unsafe_New(*abi.Type) unsafe.Pointer 408 409 // ValueOf returns a new Value initialized to the concrete value 410 // stored in the interface i. ValueOf(nil) returns the zero Value. 411 func ValueOf(i any) Value { 412 if i == nil { 413 return Value{} 414 } 415 return unpackEface(i) 416 } 417 418 // assignTo returns a value v that can be assigned directly to typ. 419 // It panics if v is not assignable to typ. 420 // For a conversion to an interface type, target is a suggested scratch space to use. 421 func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Value { 422 // if v.flag&flagMethod != 0 { 423 // v = makeMethodValue(context, v) 424 // } 425 426 switch { 427 case directlyAssignable(dst, v.typ()): 428 // Overwrite type so that they match. 429 // Same memory layout, so no harm done. 430 fl := v.flag&(flagAddr|flagIndir) | v.flag.ro() 431 fl |= flag(dst.Kind()) 432 return Value{dst, v.ptr, fl} 433 434 case implements(dst, v.typ()): 435 if target == nil { 436 target = unsafe_New(dst) 437 } 438 if v.Kind() == abi.Interface && v.IsNil() { 439 // A nil ReadWriter passed to nil Reader is OK, 440 // but using ifaceE2I below will panic. 441 // Avoid the panic by returning a nil dst (e.g., Reader) explicitly. 442 return Value{dst, nil, flag(abi.Interface)} 443 } 444 x := valueInterface(v) 445 if dst.NumMethod() == 0 { 446 *(*any)(target) = x 447 } else { 448 ifaceE2I(dst, x, target) 449 } 450 return Value{dst, target, flagIndir | flag(abi.Interface)} 451 } 452 453 // Failed. 454 panic(context + ": value of type " + toRType(v.typ()).String() + " is not assignable to type " + toRType(dst).String()) 455 } 456 457 // arrayAt returns the i-th element of p, 458 // an array whose elements are eltSize bytes wide. 459 // The array pointed at by p must have at least i+1 elements: 460 // it is invalid (but impossible to check here) to pass i >= len, 461 // because then the result will point outside the array. 462 // whySafe must explain why i < len. (Passing "i < len" is fine; 463 // the benefit is to surface this assumption at the call site.) 464 func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer { 465 return add(p, uintptr(i)*eltSize, "i < len") 466 } 467 468 func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer) 469 470 // typedmemmove copies a value of type t to dst from src. 471 // 472 //go:noescape 473 func typedmemmove(t *abi.Type, 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 any) { 479 if dummy.b { 480 dummy.x = x 481 } 482 } 483 484 var dummy struct { 485 b bool 486 x any 487 } 488 489 //go:nosplit 490 func noescape(p unsafe.Pointer) unsafe.Pointer { 491 x := uintptr(p) 492 return unsafe.Pointer(x ^ 0) 493 }