github.com/fisco-bcos/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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  	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  }