OSDN Git Service

reflect: Fix invalid sharing in valueInterface.
[pf3gnuchains/gcc-fork.git] / libgo / go / reflect / value.go
index b57ed46..5d08900 100644 (file)
@@ -54,6 +54,10 @@ func memmove(adst, asrc unsafe.Pointer, n uintptr) {
 // 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
@@ -207,7 +211,7 @@ func storeIword(p unsafe.Pointer, w iword, n uintptr) {
 
 // emptyInterface is the header for an interface{} value.
 type emptyInterface struct {
-       typ  *runtime.Type
+       typ  *runtimeType
        word iword
 }
 
@@ -215,8 +219,8 @@ type emptyInterface struct {
 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
 }
@@ -448,7 +452,6 @@ func (v Value) call(method string, in []Value) []Value {
                nin++
        }
        params := make([]unsafe.Pointer, nin)
-       delta := 0
        off := 0
        if v.flag&flagMethod != 0 {
                // Hard-wired first argument.
@@ -517,7 +520,7 @@ func isMethod(t *commonType) bool {
                        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
                }
@@ -693,7 +696,7 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value {
        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()
@@ -793,11 +796,15 @@ func (v Value) CanInterface() bool {
        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)
 }
 
@@ -833,6 +840,16 @@ func valueInterface(v Value, safe bool) interface{} {
        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))
 }
 
@@ -1245,7 +1262,8 @@ func (v Value) SetInt(x int64) {
 }
 
 // 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)
@@ -1349,7 +1367,7 @@ func (v Value) Slice(beg, end int) Value {
        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}
@@ -1596,19 +1614,32 @@ func Copy(dst, src Value) int {
  * 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
 
@@ -1627,7 +1658,7 @@ func MakeChan(typ Type, buffer int) Value {
                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.
@@ -1636,11 +1667,11 @@ func MakeMap(typ Type) Value {
                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 {
@@ -1674,10 +1705,11 @@ func ValueOf(i interface{}) Value {
        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)")
@@ -1687,7 +1719,7 @@ func Zero(typ Type) Value {
        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
@@ -1696,11 +1728,18 @@ func New(typ Type) 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.
@@ -1739,20 +1778,20 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
 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