...

Source file src/pkg/internal/reflectlite/value.go

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

View as plain text