summaryrefslogtreecommitdiff
path: root/libgo/go/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/value.go')
-rw-r--r--libgo/go/reflect/value.go593
1 files changed, 181 insertions, 412 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index c36e9954427..09210b37b70 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -7,40 +7,12 @@ package reflect
import (
"math"
"runtime"
- "strconv"
"unsafe"
)
-const bigEndian = false // can be smarter if we find a big-endian machine
const ptrSize = unsafe.Sizeof((*byte)(nil))
const cannotSet = "cannot set value obtained from unexported struct field"
-// TODO: This will have to go away when
-// the new gc goes in.
-func memmove(adst, asrc unsafe.Pointer, n uintptr) {
- dst := uintptr(adst)
- src := uintptr(asrc)
- switch {
- case src < dst && src+n > dst:
- // byte copy backward
- // careful: i is unsigned
- for i := n; i > 0; {
- i--
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- case (n|src|dst)&(ptrSize-1) != 0:
- // byte copy forward
- for i := uintptr(0); i < n; i++ {
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- default:
- // word copy forward
- for i := uintptr(0); i < n; i += ptrSize {
- *(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
- }
- }
-}
-
// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
@@ -64,16 +36,8 @@ type Value struct {
// Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true.
- // Gccgo always uses this field.
ptr unsafe.Pointer
- // Non-pointer-valued data. When the data is smaller
- // than a word, it begins at the first byte (in the memory
- // address sense) of this field.
- // Valid when flagIndir is not set and typ.pointers() is false.
- // Gccgo never uses this field.
- // scalar uintptr
-
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagRO: obtained via unexported field, so read-only
@@ -84,7 +48,7 @@ type Value struct {
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
- // If typ.size > ptrSize, code can assume that flagIndir is set.
+ // If ifaceIndir(typ), code can assume that flagIndir is set.
flag
// A method value represents a curried method invocation
@@ -97,19 +61,18 @@ type Value struct {
type flag uintptr
const (
- flagRO flag = 1 << iota
- flagIndir
- flagAddr
- flagMethod
- flagMethodFn // gccgo: first fn parameter is always pointer
- flagKindShift = iota
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
- flagMethodShift = flagKindShift + flagKindWidth
+ flagRO flag = 1 << 5
+ flagIndir flag = 1 << 6
+ flagAddr flag = 1 << 7
+ flagMethod flag = 1 << 8
+ flagMethodFn flag = 1 << 9 // gccgo: first fn parameter is always pointer
+ flagMethodShift = 10
)
func (f flag) kind() Kind {
- return Kind((f >> flagKindShift) & flagKindMask)
+ return Kind(f & flagKindMask)
}
// pointer returns the underlying pointer represented by v.
@@ -131,11 +94,11 @@ func packEface(v Value) interface{} {
e := (*emptyInterface)(unsafe.Pointer(&i))
// First, fill in the data portion of the interface.
switch {
- case v.Kind() != Ptr && v.Kind() != UnsafePointer:
- // Value is indirect, and so is the interface we're making.
+ case ifaceIndir(t):
if v.flag&flagIndir == 0 {
- panic("reflect: missing flagIndir")
+ panic("bad indir")
}
+ // Value is indirect, and so is the interface we're making.
ptr := v.ptr
if v.flag&flagAddr != 0 {
// TODO: pass safe boolean from valueInterface so
@@ -144,23 +107,14 @@ func packEface(v Value) interface{} {
memmove(c, ptr, t.size)
ptr = c
}
- e.word = iword(ptr)
+ e.word = ptr
case v.flag&flagIndir != 0:
// Value is indirect, but interface is direct. We need
// to load the data at v.ptr into the interface data word.
- if t.pointers() {
- e.word = iword(*(*unsafe.Pointer)(v.ptr))
- } else {
- e.word = iword(loadScalar(v.ptr, t.size))
- }
+ e.word = *(*unsafe.Pointer)(v.ptr)
default:
// Value is direct, and so is the interface.
- if t.pointers() {
- e.word = iword(v.ptr)
- } else {
- // e.word = iword(v.scalar)
- panic("reflect: missing flagIndir")
- }
+ e.word = v.ptr
}
// Now, fill in the type portion. We're very careful here not
// to have any operation between the e.word and e.typ assignments
@@ -178,8 +132,8 @@ func unpackEface(i interface{}) Value {
if t == nil {
return Value{}
}
- f := flag(t.Kind()) << flagKindShift
- if t.Kind() != Ptr && t.Kind() != UnsafePointer {
+ f := flag(t.Kind())
+ if ifaceIndir(t) {
f |= flagIndir
}
return Value{t, unsafe.Pointer(e.word), f}
@@ -211,78 +165,10 @@ func methodName() string {
return f.Name()
}
-// An iword is the word that would be stored in an
-// interface to represent a given value v. Specifically, if v is
-// bigger than a pointer, its word is a pointer to v's data.
-// Otherwise, its word holds the data stored
-// in its leading bytes (so is not a pointer).
-// This type is very dangerous for the garbage collector because
-// it must be treated conservatively. We try to never expose it
-// to the GC here so that GC remains precise.
-type iword unsafe.Pointer
-
-// loadScalar loads n bytes at p from memory into a uintptr
-// that forms the second word of an interface. The data
-// must be non-pointer in nature.
-func loadScalar(p unsafe.Pointer, n uintptr) uintptr {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- var w uintptr
- switch n {
- default:
- panic("reflect: internal error: loadScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
- case 2:
- *(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
- case 3:
- *(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
- case 4:
- *(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
- case 5:
- *(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
- case 6:
- *(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
- case 7:
- *(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
- case 8:
- *(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
- }
- return w
-}
-
-// storeScalar stores n bytes from w into p.
-func storeScalar(p unsafe.Pointer, w uintptr, n uintptr) {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- switch n {
- default:
- panic("reflect: internal error: storeScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
- case 2:
- *(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
- case 3:
- *(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
- case 4:
- *(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
- case 5:
- *(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
- case 6:
- *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
- case 7:
- *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
- case 8:
- *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
- }
-}
-
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
- word iword
+ word unsafe.Pointer
}
// nonEmptyInterface is the header for a interface value with methods.
@@ -292,7 +178,7 @@ type nonEmptyInterface struct {
typ *rtype // dynamic concrete type
fun [100000]unsafe.Pointer // method table
}
- word iword
+ word unsafe.Pointer
}
// mustBe panics if f's kind is not expected.
@@ -302,9 +188,8 @@ type nonEmptyInterface struct {
// v.flag.mustBe(Bool), which will only bother to copy the
// single important word for the receiver.
func (f flag) mustBe(expected Kind) {
- k := f.kind()
- if k != expected {
- panic(&ValueError{methodName(), k})
+ if f.kind() != expected {
+ panic(&ValueError{methodName(), f.kind()})
}
}
@@ -344,18 +229,14 @@ func (v Value) Addr() Value {
if v.flag&flagAddr == 0 {
panic("reflect.Value.Addr of unaddressable value")
}
- return Value{v.typ.ptrTo(), v.ptr /* 0, */, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
+ return Value{v.typ.ptrTo(), v.ptr, (v.flag & flagRO) | flag(Ptr)}
}
// Bool returns v's underlying value.
// It panics if v's kind is not Bool.
func (v Value) Bool() bool {
v.mustBe(Bool)
- if v.flag&flagIndir != 0 {
- return *(*bool)(v.ptr)
- }
- // return *(*bool)(unsafe.Pointer(&v.scalar))
- panic("reflect: missing flagIndir")
+ return *(*bool)(v.ptr)
}
// Bytes returns v's underlying value.
@@ -594,7 +475,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
@@ -611,7 +492,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
} else {
rcvrtype = v.typ
ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
+ if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
@@ -634,19 +515,10 @@ func storeRcvr(v Value, p unsafe.Pointer) {
// the interface data word becomes the receiver word
iface := (*nonEmptyInterface)(v.ptr)
*(*unsafe.Pointer)(p) = unsafe.Pointer(iface.word)
- } else if v.flag&flagIndir != 0 {
- if t.size > ptrSize {
- *(*unsafe.Pointer)(p) = v.ptr
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
- } else {
- *(*uintptr)(p) = loadScalar(v.ptr, t.size)
- }
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = v.ptr
+ } else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
+ *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
} else {
- // *(*uintptr)(p) = v.scalar
- panic("reflect: missing flagIndir")
+ *(*unsafe.Pointer)(p) = v.ptr
}
}
@@ -679,7 +551,7 @@ func (v Value) Cap() int {
// Slice is always bigger than a word; assume flagIndir.
return (*sliceHeader)(v.ptr).Cap
}
- panic(&ValueError{"reflect.Value.Cap", k})
+ panic(&ValueError{"reflect.Value.Cap", v.kind()})
}
// Close closes the channel v.
@@ -696,16 +568,11 @@ func (v Value) Complex() complex128 {
k := v.kind()
switch k {
case Complex64:
- if v.flag&flagIndir != 0 {
- return complex128(*(*complex64)(v.ptr))
- }
- // return complex128(*(*complex64)(unsafe.Pointer(&v.scalar)))
- panic("reflect: missing flagIndir")
+ return complex128(*(*complex64)(v.ptr))
case Complex128:
- // complex128 is always bigger than a word; assume flagIndir.
return *(*complex128)(v.ptr)
}
- panic(&ValueError{"reflect.Value.Complex", k})
+ panic(&ValueError{"reflect.Value.Complex", v.kind()})
}
// Elem returns the value that the interface v contains
@@ -725,7 +592,9 @@ func (v Value) Elem() Value {
})(v.ptr))
}
x := unpackEface(eface)
- x.flag |= v.flag & flagRO
+ if x.flag != 0 {
+ x.flag |= v.flag & flagRO
+ }
return x
case Ptr:
ptr := v.ptr
@@ -739,58 +608,46 @@ func (v Value) Elem() Value {
tt := (*ptrType)(unsafe.Pointer(v.typ))
typ := tt.elem
fl := v.flag&flagRO | flagIndir | flagAddr
- fl |= flag(typ.Kind() << flagKindShift)
- return Value{typ, ptr /* 0, */, fl}
+ fl |= flag(typ.Kind())
+ return Value{typ, ptr, fl}
}
- panic(&ValueError{"reflect.Value.Elem", k})
+ panic(&ValueError{"reflect.Value.Elem", v.kind()})
}
// Field returns the i'th field of the struct v.
// It panics if v's Kind is not Struct or i is out of range.
func (v Value) Field(i int) Value {
- v.mustBe(Struct)
+ if v.kind() != Struct {
+ panic(&ValueError{"reflect.Value.Field", v.kind()})
+ }
tt := (*structType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.fields) {
+ if uint(i) >= uint(len(tt.fields)) {
panic("reflect: Field index out of range")
}
field := &tt.fields[i]
typ := field.typ
// Inherit permission bits from v.
- fl := v.flag & (flagRO | flagIndir | flagAddr)
+ fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if field.pkgPath != nil {
fl |= flagRO
}
- fl |= flag(typ.Kind()) << flagKindShift
-
- var ptr unsafe.Pointer
- // var scalar uintptr
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- ptr = unsafe.Pointer(uintptr(v.ptr) + field.offset)
- case typ.pointers():
- if field.offset != 0 {
- panic("field access of ptr value isn't at offset 0")
- }
- ptr = v.ptr
- case bigEndian:
- // Must be scalar. Discard leading bytes.
- // scalar = v.scalar << (field.offset * 8)
- panic("reflect: missing flagIndir")
- default:
- // Must be scalar. Discard leading bytes.
- // scalar = v.scalar >> (field.offset * 8)
- panic("reflect: missing flagIndir")
- }
-
- return Value{typ, ptr /* scalar, */, fl}
+ // Either flagIndir is set and v.ptr points at struct,
+ // or flagIndir is not set and v.ptr is the actual struct data.
+ // In the former case, we want v.ptr + offset.
+ // In the latter case, we must be have field.offset = 0,
+ // so v.ptr + field.offset is still okay.
+ ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset)
+ return Value{typ, ptr, fl}
}
// FieldByIndex returns the nested field corresponding to index.
// It panics if v's Kind is not struct.
func (v Value) FieldByIndex(index []int) Value {
+ if len(index) == 1 {
+ return v.Field(index[0])
+ }
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
@@ -822,7 +679,6 @@ func (v Value) FieldByName(name string) Value {
// It panics if v's Kind is not struct.
// It returns the zero Value if no field was found.
func (v Value) FieldByNameFunc(match func(string) bool) Value {
- v.mustBe(Struct)
if f, ok := v.typ.FieldByNameFunc(match); ok {
return v.FieldByIndex(f.Index)
}
@@ -835,19 +691,11 @@ func (v Value) Float() float64 {
k := v.kind()
switch k {
case Float32:
- if v.flag&flagIndir != 0 {
- return float64(*(*float32)(v.ptr))
- }
- // return float64(*(*float32)(unsafe.Pointer(&v.scalar)))
- panic("reflect: missing flagIndir")
+ return float64(*(*float32)(v.ptr))
case Float64:
- if v.flag&flagIndir != 0 {
- return *(*float64)(v.ptr)
- }
- // return *(*float64)(unsafe.Pointer(&v.scalar))
- panic("reflect: missing flagIndir")
+ return *(*float64)(v.ptr)
}
- panic(&ValueError{"reflect.Value.Float", k})
+ panic(&ValueError{"reflect.Value.Float", v.kind()})
}
var uint8Type = TypeOf(uint8(0)).(*rtype)
@@ -855,82 +703,54 @@ var uint8Type = TypeOf(uint8(0)).(*rtype)
// Index returns v's i'th element.
// It panics if v's Kind is not Array, Slice, or String or i is out of range.
func (v Value) Index(i int) Value {
- k := v.kind()
- switch k {
+ switch v.kind() {
case Array:
tt := (*arrayType)(unsafe.Pointer(v.typ))
- if i < 0 || i > int(tt.len) {
+ if uint(i) >= uint(tt.len) {
panic("reflect: array index out of range")
}
typ := tt.elem
- fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
- fl |= flag(typ.Kind()) << flagKindShift
offset := uintptr(i) * typ.size
- var val unsafe.Pointer
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- val = unsafe.Pointer(uintptr(v.ptr) + offset)
- case typ.pointers():
- if offset != 0 {
- panic("can't Index(i) with i!=0 on ptrLike value")
- }
- val = v.ptr
- case bigEndian:
- // Direct. Discard leading bytes.
- // scalar = v.scalar << (offset * 8)
- panic("reflect: missing flagIndir")
- default:
- // Direct. Discard leading bytes.
- // scalar = v.scalar >> (offset * 8)
- panic("reflect: missing flagIndir")
- }
- return Value{typ, val /* scalar, */, fl}
+ // Either flagIndir is set and v.ptr points at array,
+ // or flagIndir is not set and v.ptr is the actual array data.
+ // In the former case, we want v.ptr + offset.
+ // In the latter case, we must be doing Index(0), so offset = 0,
+ // so v.ptr + offset is still okay.
+ val := unsafe.Pointer(uintptr(v.ptr) + offset)
+ fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind()) // bits same as overall array
+ return Value{typ, val, fl}
case Slice:
// Element flag same as Elem of Ptr.
// Addressable, indirect, possibly read-only.
- fl := flagAddr | flagIndir | v.flag&flagRO
s := (*sliceHeader)(v.ptr)
- if i < 0 || i >= s.Len {
+ if uint(i) >= uint(s.Len) {
panic("reflect: slice index out of range")
}
tt := (*sliceType)(unsafe.Pointer(v.typ))
typ := tt.elem
- fl |= flag(typ.Kind()) << flagKindShift
val := unsafe.Pointer(uintptr(s.Data) + uintptr(i)*typ.size)
- return Value{typ, val /* 0, */, fl}
+ fl := flagAddr | flagIndir | v.flag&flagRO | flag(typ.Kind())
+ return Value{typ, val, fl}
case String:
- fl := v.flag&flagRO | flag(Uint8<<flagKindShift) | flagIndir
- s := (*StringHeader)(v.ptr)
- if i < 0 || i >= s.Len {
+ s := (*stringHeader)(v.ptr)
+ if uint(i) >= uint(s.Len) {
panic("reflect: string index out of range")
}
- b := uintptr(0)
- *(*byte)(unsafe.Pointer(&b)) = *(*byte)(unsafe.Pointer(uintptr(s.Data) + uintptr(i)))
- return Value{uint8Type, unsafe.Pointer(&b) /* 0, */, fl | flagIndir}
+ p := unsafe.Pointer(uintptr(s.Data) + uintptr(i))
+ fl := v.flag&flagRO | flag(Uint8) | flagIndir
+ return Value{uint8Type, p, fl}
}
- panic(&ValueError{"reflect.Value.Index", k})
+ panic(&ValueError{"reflect.Value.Index", v.kind()})
}
// Int returns v's underlying value, as an int64.
// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
func (v Value) Int() int64 {
k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- // p = unsafe.Pointer(&v.scalar)
- switch k {
- case Int, Int8, Int16, Int32, Int64:
- panic("reflect: missing flagIndir")
- }
- }
+ p := v.ptr
switch k {
case Int:
return int64(*(*int)(p))
@@ -943,7 +763,7 @@ func (v Value) Int() int64 {
case Int64:
return int64(*(*int64)(p))
}
- panic(&ValueError{"reflect.Value.Int", k})
+ panic(&ValueError{"reflect.Value.Int", v.kind()})
}
// CanInterface returns true if Interface can be used without panicking.
@@ -1040,7 +860,7 @@ func (v Value) IsNil() bool {
// Both are always bigger than a word; assume flagIndir.
return *(*unsafe.Pointer)(v.ptr) == nil
}
- panic(&ValueError{"reflect.Value.IsNil", k})
+ panic(&ValueError{"reflect.Value.IsNil", v.kind()})
}
// IsValid returns true if v represents a value.
@@ -1077,7 +897,7 @@ func (v Value) Len() int {
// String is bigger than a word; assume flagIndir.
return (*stringHeader)(v.ptr).Len
}
- panic(&ValueError{"reflect.Value.Len", k})
+ panic(&ValueError{"reflect.Value.Len", v.kind()})
}
// MapIndex returns the value associated with key in the map v.
@@ -1100,11 +920,8 @@ func (v Value) MapIndex(key Value) Value {
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
} else {
- // k = unsafe.Pointer(&key.scalar)
- panic("reflect: missing flagIndir")
+ k = unsafe.Pointer(&key.ptr)
}
e := mapaccess(v.typ, v.pointer(), k)
if e == nil {
@@ -1112,17 +929,15 @@ func (v Value) MapIndex(key Value) Value {
}
typ := tt.elem
fl := (v.flag | key.flag) & flagRO
- fl |= flag(typ.Kind()) << flagKindShift
- if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flag(typ.Kind())
+ if ifaceIndir(typ) {
// Copy result so future changes to the map
// won't change the underlying value.
c := unsafe_New(typ)
memmove(c, e, typ.size)
- return Value{typ, c /* 0, */, fl | flagIndir}
- } else if typ.pointers() {
- return Value{typ, *(*unsafe.Pointer)(e) /* 0, */, fl}
+ return Value{typ, c, fl | flagIndir}
} else {
- panic("reflect: can't happen")
+ return Value{typ, *(*unsafe.Pointer)(e), fl}
}
}
@@ -1135,10 +950,7 @@ func (v Value) MapKeys() []Value {
tt := (*mapType)(unsafe.Pointer(v.typ))
keyType := tt.key
- fl := v.flag&flagRO | flag(keyType.Kind())<<flagKindShift
- if keyType.Kind() != Ptr && keyType.Kind() != UnsafePointer {
- fl |= flagIndir
- }
+ fl := v.flag&flagRO | flag(keyType.Kind())
m := v.pointer()
mlen := int(0)
@@ -1156,16 +968,14 @@ func (v Value) MapKeys() []Value {
// we can do about it.
break
}
- if keyType.Kind() != Ptr && keyType.Kind() != UnsafePointer {
+ if ifaceIndir(keyType) {
// Copy result so future changes to the map
// won't change the underlying value.
c := unsafe_New(keyType)
memmove(c, key, keyType.size)
- a[i] = Value{keyType, c /* 0, */, fl | flagIndir}
- } else if keyType.pointers() {
- a[i] = Value{keyType, *(*unsafe.Pointer)(key) /* 0, */, fl}
+ a[i] = Value{keyType, c, fl | flagIndir}
} else {
- panic("reflect: can't happen")
+ a[i] = Value{keyType, *(*unsafe.Pointer)(key), fl}
}
mapiternext(it)
}
@@ -1180,16 +990,16 @@ func (v Value) Method(i int) Value {
if v.typ == nil {
panic(&ValueError{"reflect.Value.Method", Invalid})
}
- if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
+ if v.flag&flagMethod != 0 || uint(i) >= uint(v.typ.NumMethod()) {
panic("reflect: Method index out of range")
}
if v.typ.Kind() == Interface && v.IsNil() {
panic("reflect: Method on nil interface value")
}
fl := v.flag & (flagRO | flagIndir)
- fl |= flag(Func) << flagKindShift
+ fl |= flag(Func)
fl |= flag(i)<<flagMethodShift | flagMethod
- return Value{v.typ, v.ptr /* v.scalar, */, fl}
+ return Value{v.typ, v.ptr, fl}
}
// NumMethod returns the number of methods in the value's method set.
@@ -1240,7 +1050,7 @@ func (v Value) OverflowComplex(x complex128) bool {
case Complex128:
return false
}
- panic(&ValueError{"reflect.Value.OverflowComplex", k})
+ panic(&ValueError{"reflect.Value.OverflowComplex", v.kind()})
}
// OverflowFloat returns true if the float64 x cannot be represented by v's type.
@@ -1253,7 +1063,7 @@ func (v Value) OverflowFloat(x float64) bool {
case Float64:
return false
}
- panic(&ValueError{"reflect.Value.OverflowFloat", k})
+ panic(&ValueError{"reflect.Value.OverflowFloat", v.kind()})
}
func overflowFloat32(x float64) bool {
@@ -1273,7 +1083,7 @@ func (v Value) OverflowInt(x int64) bool {
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
- panic(&ValueError{"reflect.Value.OverflowInt", k})
+ panic(&ValueError{"reflect.Value.OverflowInt", v.kind()})
}
// OverflowUint returns true if the uint64 x cannot be represented by v's type.
@@ -1286,7 +1096,7 @@ func (v Value) OverflowUint(x uint64) bool {
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
- panic(&ValueError{"reflect.Value.OverflowUint", k})
+ panic(&ValueError{"reflect.Value.OverflowUint", v.kind()})
}
// Pointer returns v's value as a uintptr.
@@ -1331,7 +1141,7 @@ func (v Value) Pointer() uintptr {
case Slice:
return (*SliceHeader)(v.ptr).Data
}
- panic(&ValueError{"reflect.Value.Pointer", k})
+ panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}
// Recv receives and returns a value from the channel v.
@@ -1353,9 +1163,9 @@ func (v Value) recv(nb bool) (val Value, ok bool) {
panic("reflect: recv on send-only channel")
}
t := tt.elem
- val = Value{t, nil /* 0, */, flag(t.Kind()) << flagKindShift}
+ val = Value{t, nil, flag(t.Kind())}
var p unsafe.Pointer
- if t.Kind() != Ptr && t.Kind() != UnsafePointer {
+ if ifaceIndir(t) {
p = unsafe_New(t)
val.ptr = p
val.flag |= flagIndir
@@ -1390,11 +1200,8 @@ func (v Value) send(x Value, nb bool) (selected bool) {
var p unsafe.Pointer
if x.flag&flagIndir != 0 {
p = x.ptr
- } else if x.typ.pointers() {
- p = unsafe.Pointer(&x.ptr)
} else {
- // p = unsafe.Pointer(&x.scalar)
- panic("reflect: missing flagIndir")
+ p = unsafe.Pointer(&x.ptr)
}
return chansend(v.typ, v.pointer(), p, nb)
}
@@ -1412,11 +1219,8 @@ func (v Value) Set(x Value) {
x = x.assignTo("reflect.Set", v.typ, target)
if x.flag&flagIndir != 0 {
memmove(v.ptr, x.ptr, v.typ.size)
- } else if x.typ.pointers() {
- *(*unsafe.Pointer)(v.ptr) = x.ptr
} else {
- // memmove(v.ptr, unsafe.Pointer(&x.scalar), v.typ.size)
- panic("reflect: missing flagIndir")
+ *(*unsafe.Pointer)(v.ptr) = x.ptr
}
}
@@ -1456,7 +1260,7 @@ func (v Value) SetComplex(x complex128) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetComplex", k})
+ panic(&ValueError{"reflect.Value.SetComplex", v.kind()})
case Complex64:
*(*complex64)(v.ptr) = complex64(x)
case Complex128:
@@ -1470,7 +1274,7 @@ func (v Value) SetFloat(x float64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetFloat", k})
+ panic(&ValueError{"reflect.Value.SetFloat", v.kind()})
case Float32:
*(*float32)(v.ptr) = float32(x)
case Float64:
@@ -1484,7 +1288,7 @@ func (v Value) SetInt(x int64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetInt", k})
+ panic(&ValueError{"reflect.Value.SetInt", v.kind()})
case Int:
*(*int)(v.ptr) = int(x)
case Int8:
@@ -1505,7 +1309,7 @@ func (v Value) SetLen(n int) {
v.mustBeAssignable()
v.mustBe(Slice)
s := (*sliceHeader)(v.ptr)
- if n < 0 || n > int(s.Cap) {
+ if uint(n) > uint(s.Cap) {
panic("reflect: slice length out of range in SetLen")
}
s.Len = n
@@ -1539,11 +1343,8 @@ func (v Value) SetMapIndex(key, val Value) {
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
} else {
- // k = unsafe.Pointer(&key.scalar)
- panic("reflect: missing flagIndir")
+ k = unsafe.Pointer(&key.ptr)
}
if val.typ == nil {
mapdelete(v.typ, v.pointer(), k)
@@ -1554,11 +1355,8 @@ func (v Value) SetMapIndex(key, val Value) {
var e unsafe.Pointer
if val.flag&flagIndir != 0 {
e = val.ptr
- } else if val.typ.pointers() {
- e = unsafe.Pointer(&val.ptr)
} else {
- // e = unsafe.Pointer(&val.scalar)
- panic("reflect: missing flagIndir")
+ e = unsafe.Pointer(&val.ptr)
}
mapassign(v.typ, v.pointer(), k, e)
}
@@ -1569,7 +1367,7 @@ func (v Value) SetUint(x uint64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetUint", k})
+ panic(&ValueError{"reflect.Value.SetUint", v.kind()})
case Uint:
*(*uint)(v.ptr) = uint(x)
case Uint8:
@@ -1612,7 +1410,7 @@ func (v Value) Slice(i, j int) Value {
)
switch kind := v.kind(); kind {
default:
- panic(&ValueError{"reflect.Value.Slice", kind})
+ panic(&ValueError{"reflect.Value.Slice", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
@@ -1635,7 +1433,7 @@ func (v Value) Slice(i, j int) Value {
panic("reflect.Value.Slice: string slice index out of bounds")
}
t := stringHeader{unsafe.Pointer(uintptr(s.Data) + uintptr(i)), j - i}
- return Value{v.typ, unsafe.Pointer(&t) /* 0, */, v.flag}
+ return Value{v.typ, unsafe.Pointer(&t), v.flag}
}
if i < 0 || j < i || j > cap {
@@ -1647,12 +1445,17 @@ func (v Value) Slice(i, j int) Value {
// Reinterpret as *sliceHeader to edit.
s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
s.Len = j - i
s.Cap = cap - i
+ if cap-i > 0 {
+ s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+ } else {
+ // do not advance pointer, to avoid pointing beyond end of slice
+ s.Data = base
+ }
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x) /* 0, */, fl}
+ fl := v.flag&flagRO | flagIndir | flag(Slice)
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
}
// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
@@ -1666,7 +1469,7 @@ func (v Value) Slice3(i, j, k int) Value {
)
switch kind := v.kind(); kind {
default:
- panic(&ValueError{"reflect.Value.Slice3", kind})
+ panic(&ValueError{"reflect.Value.Slice3", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
@@ -1694,12 +1497,17 @@ func (v Value) Slice3(i, j, k int) Value {
// Reinterpret as *sliceHeader to edit.
s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
s.Len = j - i
s.Cap = k - i
+ if k-i > 0 {
+ s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+ } else {
+ // do not advance pointer, to avoid pointing beyond end of slice
+ s.Data = base
+ }
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x) /* 0, */, fl}
+ fl := v.flag&flagRO | flagIndir | flag(Slice)
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
}
// String returns the string v's underlying value, as a string.
@@ -1715,7 +1523,7 @@ func (v Value) String() string {
}
// If you call String on a reflect.Value of other type, it's better to
// print something than to panic. Useful in debugging.
- return "<" + v.typ.String() + " Value>"
+ return "<" + v.Type().String() + " Value>"
}
// TryRecv attempts to receive a value from the channel v but will not block.
@@ -1756,7 +1564,7 @@ func (v Value) Type() Type {
if v.typ.Kind() == Interface {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
@@ -1764,7 +1572,7 @@ func (v Value) Type() Type {
}
// Method on concrete type.
ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
+ if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
@@ -1775,18 +1583,7 @@ func (v Value) Type() Type {
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
func (v Value) Uint() uint64 {
k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- // p = unsafe.Pointer(&v.scalar)
- switch k {
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- panic("reflect: missing flagIndir")
- }
- }
+ p := v.ptr
switch k {
case Uint:
return uint64(*(*uint)(p))
@@ -1801,7 +1598,7 @@ func (v Value) Uint() uint64 {
case Uintptr:
return uint64(*(*uintptr)(p))
}
- panic(&ValueError{"reflect.Value.Uint", k})
+ panic(&ValueError{"reflect.Value.Uint", v.kind()})
}
// UnsafeAddr returns a pointer to v's data.
@@ -1940,17 +1737,6 @@ func Copy(dst, src Value) int {
n = sn
}
- // If sk is an in-line array, cannot take its address.
- // Instead, copy element by element.
- // TODO: memmove would be ok for this (sa = unsafe.Pointer(&v.scalar))
- // if we teach the compiler that ptrs don't escape from memmove.
- if src.flag&flagIndir == 0 {
- for i := 0; i < n; i++ {
- dst.Index(i).Set(src.Index(i))
- }
- return n
- }
-
// Copy via memmove.
var da, sa unsafe.Pointer
if dk == Array {
@@ -1958,7 +1744,9 @@ func Copy(dst, src Value) int {
} else {
da = (*sliceHeader)(dst.ptr).Data
}
- if sk == Array {
+ if src.flag&flagIndir == 0 {
+ sa = unsafe.Pointer(&src.ptr)
+ } else if sk == Array {
sa = src.ptr
} else {
sa = (*sliceHeader)(src.ptr).Data
@@ -1968,7 +1756,7 @@ func Copy(dst, src Value) int {
}
// A runtimeSelect is a single case passed to rselect.
-// This must match ../runtime/chan.c:/runtimeSelect
+// This must match ../runtime/select.go:/runtimeSelect
type runtimeSelect struct {
dir uintptr // 0, SendDir, or RecvDir
typ *rtype // channel type
@@ -1986,7 +1774,7 @@ func rselect([]runtimeSelect) (chosen int, recvOK bool)
// A SelectDir describes the communication direction of a select case.
type SelectDir int
-// NOTE: These values must match ../runtime/chan.c:/SelectDir.
+// NOTE: These values must match ../runtime/select.go:/selectDir.
const (
_ SelectDir = iota
@@ -2071,11 +1859,8 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
v = v.assignTo("reflect.Select", tt.elem, nil)
if v.flag&flagIndir != 0 {
rc.val = v.ptr
- } else if v.typ.pointers() {
- rc.val = unsafe.Pointer(&v.ptr)
} else {
- // rc.val = unsafe.Pointer(&v.scalar)
- panic("reflect: missing flagIndir")
+ rc.val = unsafe.Pointer(&v.ptr)
}
case SelectRecv:
@@ -2103,11 +1888,11 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
t := tt.elem
p := runcases[chosen].val
- fl := flag(t.Kind()) << flagKindShift
- if t.Kind() != Ptr && t.Kind() != UnsafePointer {
- recv = Value{t, p /* 0, */, fl | flagIndir}
+ fl := flag(t.Kind())
+ if ifaceIndir(t) {
+ recv = Value{t, p, fl | flagIndir}
} else {
- recv = Value{t, *(*unsafe.Pointer)(p) /* 0, */, fl}
+ recv = Value{t, *(*unsafe.Pointer)(p), fl}
}
}
return chosen, recv, recvOK
@@ -2138,7 +1923,7 @@ func MakeSlice(typ Type, len, cap int) Value {
}
s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
- return Value{typ.common(), unsafe.Pointer(&s) /* 0, */, flagIndir | flag(Slice)<<flagKindShift}
+ return Value{typ.common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
// MakeChan creates a new channel with the specified type and buffer size.
@@ -2153,7 +1938,7 @@ func MakeChan(typ Type, buffer int) Value {
panic("reflect.MakeChan: unidirectional channel type")
}
ch := makechan(typ.(*rtype), uint64(buffer))
- return Value{typ.common(), unsafe.Pointer(&ch) /* 0, */, flagIndir | (flag(Chan) << flagKindShift)}
+ return Value{typ.common(), unsafe.Pointer(&ch), flag(Chan) | flagIndir}
}
// MakeMap creates a new map of the specified type.
@@ -2162,7 +1947,7 @@ func MakeMap(typ Type) Value {
panic("reflect.MakeMap of non-map type")
}
m := makemap(typ.(*rtype))
- return Value{typ.common(), unsafe.Pointer(&m) /* 0, */, flagIndir | (flag(Map) << flagKindShift)}
+ return Value{typ.common(), unsafe.Pointer(&m), flag(Map) | flagIndir}
}
// Indirect returns the value that v points to.
@@ -2202,11 +1987,11 @@ func Zero(typ Type) Value {
panic("reflect: Zero(nil)")
}
t := typ.common()
- fl := flag(t.Kind()) << flagKindShift
- if t.Kind() == Ptr || t.Kind() == UnsafePointer {
- return Value{t, nil /* 0, */, fl}
+ fl := flag(t.Kind())
+ if ifaceIndir(t) {
+ return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir}
}
- return Value{t, unsafe_New(typ.(*rtype)) /* 0, */, fl | flagIndir}
+ return Value{t, nil, fl}
}
// New returns a Value representing a pointer to a new zero value
@@ -2216,15 +2001,15 @@ func New(typ Type) Value {
panic("reflect: New(nil)")
}
ptr := unsafe_New(typ.(*rtype))
- fl := flag(Ptr) << flagKindShift
- return Value{typ.common().ptrTo(), ptr /* 0, */, fl}
+ fl := flag(Ptr)
+ 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 /* 0, */, fl}
+ fl := flag(Ptr)
+ return Value{typ.common().ptrTo(), p, fl}
}
// assignTo returns a value v that can be assigned directly to typ.
@@ -2241,8 +2026,8 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
// Same memory layout, so no harm done.
v.typ = dst
fl := v.flag & (flagRO | flagAddr | flagIndir)
- fl |= flag(dst.Kind()) << flagKindShift
- return Value{dst, v.ptr /* v.scalar, */, fl}
+ fl |= flag(dst.Kind())
+ return Value{dst, v.ptr, fl}
case implements(dst, v.typ):
if target == nil {
@@ -2254,7 +2039,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
} else {
ifaceE2I(dst, x, target)
}
- return Value{dst, target /* 0, */, flagIndir | flag(Interface)<<flagKindShift}
+ return Value{dst, target, flagIndir | flag(Interface)}
}
// Failed.
@@ -2362,86 +2147,66 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
// where t is a signed or unsigned int type.
func makeInt(f flag, bits uint64, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- // Assume ptrSize >= 4, so this must be uint64.
- ptr := unsafe_New(typ)
- *(*uint64)(unsafe.Pointer(ptr)) = bits
- return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
- var s uintptr
+ ptr := unsafe_New(typ)
switch typ.size {
case 1:
- *(*uint8)(unsafe.Pointer(&s)) = uint8(bits)
+ *(*uint8)(unsafe.Pointer(ptr)) = uint8(bits)
case 2:
- *(*uint16)(unsafe.Pointer(&s)) = uint16(bits)
+ *(*uint16)(unsafe.Pointer(ptr)) = uint16(bits)
case 4:
- *(*uint32)(unsafe.Pointer(&s)) = uint32(bits)
+ *(*uint32)(unsafe.Pointer(ptr)) = uint32(bits)
case 8:
- *(*uint64)(unsafe.Pointer(&s)) = uint64(bits)
+ *(*uint64)(unsafe.Pointer(ptr)) = bits
}
- return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
// where t is a float32 or float64 type.
func makeFloat(f flag, v float64, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- // Assume ptrSize >= 4, so this must be float64.
- ptr := unsafe_New(typ)
- *(*float64)(unsafe.Pointer(ptr)) = v
- return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
-
- var s uintptr
+ ptr := unsafe_New(typ)
switch typ.size {
case 4:
- *(*float32)(unsafe.Pointer(&s)) = float32(v)
+ *(*float32)(unsafe.Pointer(ptr)) = float32(v)
case 8:
- *(*float64)(unsafe.Pointer(&s)) = v
+ *(*float64)(unsafe.Pointer(ptr)) = v
}
- return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
// where t is a complex64 or complex128 type.
func makeComplex(f flag, v complex128, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- ptr := unsafe_New(typ)
- switch typ.size {
- case 8:
- *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
- case 16:
- *(*complex128)(unsafe.Pointer(ptr)) = v
- }
- return Value{typ, ptr /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+ ptr := unsafe_New(typ)
+ switch typ.size {
+ case 8:
+ *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
+ case 16:
+ *(*complex128)(unsafe.Pointer(ptr)) = v
}
-
- // Assume ptrSize <= 8 so this must be complex64.
- var s uintptr
- *(*complex64)(unsafe.Pointer(&s)) = complex64(v)
- return Value{typ, unsafe.Pointer(&s) /* 0, */, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeString(f flag, v string, t Type) Value {
ret := New(t).Elem()
ret.SetString(v)
- ret.flag = ret.flag&^flagAddr | f | flagIndir
+ ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeBytes(f flag, v []byte, t Type) Value {
ret := New(t).Elem()
ret.SetBytes(v)
- ret.flag = ret.flag&^flagAddr | f | flagIndir
+ ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeRunes(f flag, v []rune, t Type) Value {
ret := New(t).Elem()
ret.setRunes(v)
- ret.flag = ret.flag&^flagAddr | f | flagIndir
+ ret.flag = ret.flag&^flagAddr | f
return ret
}
@@ -2532,7 +2297,7 @@ func cvtDirect(v Value, typ Type) Value {
ptr = c
f &^= flagAddr
}
- return Value{t, ptr /* v.scalar, */, v.flag&flagRO | f} // v.flag&flagRO|f == f?
+ return Value{t, ptr, v.flag&flagRO | f} // v.flag&flagRO|f == f?
}
// convertOp: concrete -> interface
@@ -2544,7 +2309,7 @@ func cvtT2I(v Value, typ Type) Value {
} else {
ifaceE2I(typ.(*rtype), x, target)
}
- return Value{typ.common(), target /* 0, */, v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+ return Value{typ.common(), target, v.flag&flagRO | flagIndir | flag(Interface)}
}
// convertOp: interface -> interface
@@ -2557,7 +2322,7 @@ func cvtI2I(v Value, typ Type) Value {
return cvtT2I(v.Elem(), typ)
}
-// implemented in ../pkg/runtime
+// implemented in ../runtime
func chancap(ch unsafe.Pointer) int
func chanclose(ch unsafe.Pointer)
func chanlen(ch unsafe.Pointer) int
@@ -2577,10 +2342,14 @@ func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
func mapiternext(it unsafe.Pointer)
func maplen(m unsafe.Pointer) int
-
func call(typ *rtype, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
+
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
+//go:noescape
+//extern memmove
+func memmove(adst, asrc unsafe.Pointer, n uintptr)
+
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.