// its String method returns "<invalid Value>", and all other methods panic.
// Most functions and methods never return an invalid value.
// If one does, its documentation states the conditions explicitly.
+//
+// A Value can be used concurrently by multiple goroutines provided that
+// the underlying Go value can be used concurrently for the equivalent
+// direct operations.
type Value struct {
// typ holds the type of the value represented by a Value.
typ *commonType
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
- typ *runtime.Type
+ typ *runtimeType
word iword
}
type nonEmptyInterface struct {
// see ../runtime/iface.c:/Itab
itab *struct {
- typ *runtime.Type // dynamic concrete type
- fun [100000]unsafe.Pointer // method table
+ typ *runtimeType // dynamic concrete type
+ fun [100000]unsafe.Pointer // method table
}
word iword
}
nin++
}
params := make([]unsafe.Pointer, nin)
- delta := 0
off := 0
if v.flag&flagMethod != 0 {
// Hard-wired first argument.
params++
} else if c == ')' {
parens--
- } else if parens == 0 && c == ' ' && s[i + 1] != '(' && !sawRet {
+ } else if parens == 0 && c == ' ' && s[i+1] != '(' && !sawRet {
params++
sawRet = true
}
return Value{}
}
-// Float returns v's underlying value, as an float64.
+// Float returns v's underlying value, as a float64.
// It panics if v's Kind is not Float32 or Float64
func (v Value) Float() float64 {
k := v.kind()
return v.flag&(flagMethod|flagRO) == 0
}
-// Interface returns v's value as an interface{}.
+// Interface returns v's current value as an interface{}.
+// It is equivalent to:
+// var i interface{} = (v's underlying value)
// If v is a method obtained by invoking Value.Method
// (as opposed to Type.Method), Interface cannot return an
// interface value, so it panics.
-func (v Value) Interface() interface{} {
+// It also panics if the Value was obtained by accessing
+// unexported struct fields.
+func (v Value) Interface() (i interface{}) {
return valueInterface(v, true)
}
var eface emptyInterface
eface.typ = v.typ.runtimeType()
eface.word = v.iword()
+
+ if v.flag&flagIndir != 0 && v.kind() != Ptr && v.kind() != UnsafePointer {
+ // eface.word is a pointer to the actual data,
+ // which might be changed. We need to return
+ // a pointer to unchanging data, so make a copy.
+ ptr := unsafe_New(v.typ)
+ memmove(ptr, unsafe.Pointer(eface.word), v.typ.size)
+ eface.word = iword(ptr)
+ }
+
return *(*interface{})(unsafe.Pointer(&eface))
}
}
// SetLen sets v's length to n.
-// It panics if v's Kind is not Slice.
+// It panics if v's Kind is not Slice or if n is negative or
+// greater than the capacity of the slice.
func (v Value) SetLen(n int) {
v.mustBeAssignable()
v.mustBe(Slice)
s := (*SliceHeader)(unsafe.Pointer(&x))
s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size()
s.Len = end - beg
- s.Cap = end - beg
+ s.Cap = cap - beg
fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
return Value{typ.common(), unsafe.Pointer(&x), fl}
* constructors
*/
+// implemented in package runtime
+func unsafe_New(Type) unsafe.Pointer
+func unsafe_NewArray(Type, int) unsafe.Pointer
+
// MakeSlice creates a new zero-initialized slice value
// for the specified slice type, length, and capacity.
func MakeSlice(typ Type, len, cap int) Value {
if typ.Kind() != Slice {
panic("reflect.MakeSlice of non-slice type")
}
+ if len < 0 {
+ panic("reflect.MakeSlice: negative len")
+ }
+ if cap < 0 {
+ panic("reflect.MakeSlice: negative cap")
+ }
+ if len > cap {
+ panic("reflect.MakeSlice: len > cap")
+ }
// Declare slice so that gc can see the base pointer in it.
var x []byte
// Reinterpret as *SliceHeader to edit.
s := (*SliceHeader)(unsafe.Pointer(&x))
- s.Data = uintptr(unsafe.NewArray(typ.Elem(), cap))
+ s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap))
s.Len = len
s.Cap = cap
panic("reflect.MakeChan: unidirectional channel type")
}
ch := makechan(typ.runtimeType(), uint32(buffer))
- return Value{typ.common(), unsafe.Pointer(ch), flagIndir | (flag(Chan)<<flagKindShift)}
+ return Value{typ.common(), unsafe.Pointer(ch), flagIndir | (flag(Chan) << flagKindShift)}
}
// MakeMap creates a new map of the specified type.
panic("reflect.MakeMap of non-map type")
}
m := makemap(typ.runtimeType())
- return Value{typ.common(), unsafe.Pointer(m), flagIndir | (flag(Map)<<flagKindShift)}
+ return Value{typ.common(), unsafe.Pointer(m), flagIndir | (flag(Map) << flagKindShift)}
}
// Indirect returns the value that v points to.
-// If v is a nil pointer, Indirect returns a nil Value.
+// If v is a nil pointer, Indirect returns a zero Value.
// If v is not a pointer, Indirect returns v.
func Indirect(v Value) Value {
if v.Kind() != Ptr {
return Value{typ, unsafe.Pointer(eface.word), fl}
}
-// Zero returns a Value representing a zero value for the specified type.
+// Zero returns a Value representing the zero value for the specified type.
// The result is different from the zero value of the Value struct,
// which represents no value at all.
// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
+// The returned value is neither addressable nor settable.
func Zero(typ Type) Value {
if typ == nil {
panic("reflect: Zero(nil)")
if t.Kind() == Ptr || t.Kind() == UnsafePointer {
return Value{t, nil, fl}
}
- return Value{t, unsafe.New(typ), fl | flagIndir}
+ return Value{t, unsafe_New(typ), fl | flagIndir}
}
// New returns a Value representing a pointer to a new zero value
if typ == nil {
panic("reflect: New(nil)")
}
- ptr := unsafe.New(typ)
+ ptr := unsafe_New(typ)
fl := flag(Ptr) << flagKindShift
return Value{typ.common().ptrTo(), ptr, fl}
}
+// NewAt returns a Value representing a pointer to a value of the
+// specified type, using p as that pointer.
+func NewAt(typ Type, p unsafe.Pointer) Value {
+ fl := flag(Ptr) << flagKindShift
+ return Value{typ.common().ptrTo(), p, fl}
+}
+
// assignTo returns a value v that can be assigned directly to typ.
// It panics if v is not assignable to typ.
// For a conversion to an interface type, target is a suggested scratch space to use.
func chancap(ch iword) int32
func chanclose(ch iword)
func chanlen(ch iword) int32
-func chanrecv(t *runtime.Type, ch iword, nb bool) (val iword, selected, received bool)
-func chansend(t *runtime.Type, ch iword, val iword, nb bool) bool
-
-func makechan(typ *runtime.Type, size uint32) (ch iword)
-func makemap(t *runtime.Type) (m iword)
-func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool)
-func mapassign(t *runtime.Type, m iword, key, val iword, ok bool)
-func mapiterinit(t *runtime.Type, m iword) *byte
+func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
+func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
+
+func makechan(typ *runtimeType, size uint32) (ch iword)
+func makemap(t *runtimeType) (m iword)
+func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
+func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
+func mapiterinit(t *runtimeType, m iword) *byte
func mapiterkey(it *byte) (key iword, ok bool)
func mapiternext(it *byte)
func maplen(m iword) int32
func call(typ *commonType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
-func ifaceE2I(t *runtime.Type, src interface{}, dst unsafe.Pointer)
+func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that