]> Cypherpunks.ru repositories - gostls13.git/commitdiff
Revert "reflect: change rtype so that it (not *rtype) implements Type"
authorAustin Clements <austin@google.com>
Fri, 12 May 2023 12:59:19 +0000 (08:59 -0400)
committerGopher Robot <gobot@golang.org>
Fri, 12 May 2023 13:32:40 +0000 (13:32 +0000)
This reverts CL 487558, which is causing test failures in Google. See
b/282133554.

Change-Id: Icafa4ffc6aaa24a363abb90b8ae0b0183aca2b89
Reviewed-on: https://go-review.googlesource.com/c/go/+/494410
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Austin Clements <austin@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Austin Clements <austin@google.com>

src/reflect/all_test.go
src/reflect/benchmark_test.go
src/reflect/export_test.go
src/reflect/makefunc.go
src/reflect/type.go
src/reflect/value.go

index 4898189b248edb0f8725e886bb5993e5f19eec23..31f6416ed9ac0aff89d8610c83547fc97e38dfec 100644 (file)
@@ -7215,11 +7215,11 @@ func join(b ...[]byte) []byte    { return bytes.Join(b, nil) }
 func lit(x ...byte) []byte       { return x }
 
 func TestTypeOfTypeOf(t *testing.T) {
-       // Check that all the type constructors return concrete rtype implementations.
+       // Check that all the type constructors return concrete *rtype implementations.
        // It's difficult to test directly because the reflect package is only at arm's length.
-       // The easiest thing to do is just call a function that crashes if it doesn't get an rtype.
+       // The easiest thing to do is just call a function that crashes if it doesn't get an *rtype.
        check := func(name string, typ Type) {
-               if underlying := TypeOf(typ).String(); underlying != "reflect.rtype" {
+               if underlying := TypeOf(typ).String(); underlying != "*reflect.rtype" {
                        t.Errorf("%v returned %v, not *reflect.rtype", name, underlying)
                }
        }
index aa816ce032bc25b7fdd37d27f6ab1b919cf0f988..9241c2c3d3d9e9d6b12fbaa8b6665c80b957089f 100644 (file)
@@ -247,9 +247,10 @@ func BenchmarkPtrTo(b *testing.B) {
        // Construct a type with a zero ptrToThis.
        type T struct{ int }
        t := SliceOf(TypeOf(T{}))
-       ptrToThis := ValueOf(t).Field(0).Elem().FieldByName("PtrToThis")
+       ptrToThis := ValueOf(t).Elem().FieldByName("PtrToThis")
        if !ptrToThis.IsValid() {
-               b.Fatalf("%v has no ptrToThis field; was it removed from rtype?", t)
+               b.Skipf("%v has no ptrToThis field; was it removed from rtype?", t) // TODO fix this at top of refactoring
+               // b.Fatalf("%v has no ptrToThis field; was it removed from rtype?", t)
        }
        if ptrToThis.Int() != 0 {
                b.Fatalf("%v.ptrToThis unexpectedly nonzero", t)
index a9587fdef18372879a6d599653f9430c75a441a0..2496c8dcd9be97b108720731e2228d4d854bbefb 100644 (file)
@@ -35,7 +35,7 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr,
        if rcvr != nil {
                ft, _, abid = funcLayout((*funcType)(unsafe.Pointer(t.common())), rcvr.common())
        } else {
-               ft, _, abid = funcLayout((*funcType)(unsafe.Pointer(t.common())), nil)
+               ft, _, abid = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), nil)
        }
        // Extract size information.
        argSize = abid.stackCallArgsSize
@@ -80,7 +80,7 @@ func TypeLinks() []string {
        for i, offs := range offset {
                rodata := sections[i]
                for _, off := range offs {
-                       typ := toRType((*abi.Type)(resolveTypeOff(unsafe.Pointer(rodata), off)))
+                       typ := (*rtype)(resolveTypeOff(unsafe.Pointer(rodata), off))
                        r = append(r, typ.String())
                }
        }
@@ -96,11 +96,11 @@ func MapBucketOf(x, y Type) Type {
 }
 
 func CachedBucketOf(m Type) Type {
-       t := m.(rtype)
+       t := m.(*rtype)
        if Kind(t.t.Kind_&kindMask) != Map {
                panic("not map")
        }
-       tt := (*mapType)(unsafe.Pointer(t.t))
+       tt := (*mapType)(unsafe.Pointer(t))
        return toType(tt.Bucket)
 }
 
@@ -122,7 +122,7 @@ func FirstMethodNameBytes(t Type) *byte {
                panic("type has no methods")
        }
        m := ut.Methods()[0]
-       mname := t.(rtype).nameOff(m.Name)
+       mname := t.(*rtype).nameOff(m.Name)
        if *mname.DataChecked(0, "name flag field")&(1<<2) == 0 {
                panic("method name does not have pkgPath *string")
        }
@@ -135,7 +135,7 @@ type OtherPkgFields struct {
 }
 
 func IsExported(t Type) bool {
-       typ := t.(rtype)
+       typ := t.(*rtype)
        n := typ.nameOff(typ.t.Str)
        return n.IsExported()
 }
index f4f17549e2916af6aacefd640d5a387b844dc7d2..6f9be08917722a60556ef440d4779efe8f7afd47 100644 (file)
@@ -104,7 +104,7 @@ func makeMethodValue(op string, v Value) Value {
        rcvr := Value{v.typ, v.ptr, fl}
 
        // v.Type returns the actual type of the method value.
-       ftyp := (*funcType)(unsafe.Pointer(v.Type().common()))
+       ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype)))
 
        code := methodValueCallCodePtr()
 
index b817e811aacdb94638a3da237bd5cbb72f814dc3..b027077aff16dc165f21761aa61436460ea43765 100644 (file)
@@ -279,16 +279,22 @@ const Ptr = Pointer
 // to describe a non-defined type with no methods.
 type uncommonType = abi.UncommonType
 
-// rtype is a wrapper that allows us to define exactly the type.Reflect methods.
+// Embed this type to get common/uncommon
+type common struct {
+       abi.Type
+}
+
+// rtype is the common implementation of most values.
+// It is embedded in other struct types.
 type rtype struct {
-       t *abi.Type
+       t abi.Type
 }
 
-func (t rtype) common() *abi.Type {
-       return t.t
+func (t *rtype) common() *abi.Type {
+       return &t.t
 }
 
-func (t rtype) uncommon() *abi.UncommonType {
+func (t *rtype) uncommon() *abi.UncommonType {
        return t.t.Uncommon()
 }
 
@@ -312,6 +318,16 @@ type arrayType = abi.ArrayType
 type chanType = abi.ChanType
 
 // funcType represents a function type.
+//
+// A *rtype for each in and out parameter is stored in an array that
+// directly follows the funcType (and possibly its uncommonType). So
+// a function type with one method, one input, and one output is:
+//
+//     struct {
+//             funcType
+//             uncommonType
+//             [2]*rtype    // [0] is in, [1] is out
+//     }
 type funcType = abi.FuncType
 
 // interfaceType represents an interface type.
@@ -460,17 +476,17 @@ var kindNames = []string{
 }
 
 // resolveNameOff resolves a name offset from a base pointer.
-// The (rtype).nameOff method is a convenience wrapper for this function.
+// The (*rtype).nameOff method is a convenience wrapper for this function.
 // Implemented in the runtime package.
 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
 
-// resolveTypeOff resolves an rtype offset from a base type.
-// The (rtype).typeOff method is a convenience wrapper for this function.
+// resolveTypeOff resolves an *rtype offset from a base type.
+// The (*rtype).typeOff method is a convenience wrapper for this function.
 // Implemented in the runtime package.
 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
 
 // resolveTextOff resolves a function pointer offset from a base type.
-// The (rtype).textOff method is a convenience wrapper for this function.
+// The (*rtype).textOff method is a convenience wrapper for this function.
 // Implemented in the runtime package.
 func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
 
@@ -485,7 +501,7 @@ func resolveReflectName(n abi.Name) aNameOff {
        return aNameOff(addReflectOff(unsafe.Pointer(n.Bytes)))
 }
 
-// resolveReflectType adds a type to the reflection lookup map in the runtime.
+// resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
 // It returns a new typeOff that can be used to refer to the pointer.
 func resolveReflectType(t *abi.Type) aTypeOff {
        return aTypeOff(addReflectOff(unsafe.Pointer(t)))
@@ -498,23 +514,23 @@ func resolveReflectText(ptr unsafe.Pointer) aTextOff {
        return aTextOff(addReflectOff(ptr))
 }
 
-func (t rtype) nameOff(off aNameOff) abi.Name {
-       return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.t), int32(off)))}
+func (t *rtype) nameOff(off aNameOff) abi.Name {
+       return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
 }
 
-func (t rtype) typeOff(off aTypeOff) *abi.Type {
-       return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.t), int32(off)))
+func (t *rtype) typeOff(off aTypeOff) *abi.Type {
+       return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
 }
 
-func (t rtype) textOff(off aTextOff) unsafe.Pointer {
-       return resolveTextOff(unsafe.Pointer(t.t), int32(off))
+func (t *rtype) textOff(off aTextOff) unsafe.Pointer {
+       return resolveTextOff(unsafe.Pointer(t), int32(off))
 }
 
 func textOffFor(t *abi.Type, off aTextOff) unsafe.Pointer {
        return toRType(t).textOff(off)
 }
 
-func (t rtype) String() string {
+func (t *rtype) String() string {
        s := t.nameOff(t.t.Str).Name()
        if t.t.TFlag&abi.TFlagExtraStar != 0 {
                return s[1:]
@@ -522,10 +538,10 @@ func (t rtype) String() string {
        return s
 }
 
-func (t rtype) Size() uintptr { return t.t.Size() }
+func (t *rtype) Size() uintptr { return t.t.Size() }
 
-func (t rtype) Bits() int {
-       if t.t == nil {
+func (t *rtype) Bits() int {
+       if t == nil {
                panic("reflect: Bits of nil Type")
        }
        k := t.Kind()
@@ -535,13 +551,13 @@ func (t rtype) Bits() int {
        return int(t.t.Size_) * 8
 }
 
-func (t rtype) Align() int { return t.t.Align() }
+func (t *rtype) Align() int { return t.t.Align() }
 
-func (t rtype) FieldAlign() int { return t.t.FieldAlign() }
+func (t *rtype) FieldAlign() int { return t.t.FieldAlign() }
 
-func (t rtype) Kind() Kind { return Kind(t.t.Kind()) }
+func (t *rtype) Kind() Kind { return Kind(t.t.Kind()) }
 
-func (t rtype) exportedMethods() []abi.Method {
+func (t *rtype) exportedMethods() []abi.Method {
        ut := t.uncommon()
        if ut == nil {
                return nil
@@ -549,17 +565,17 @@ func (t rtype) exportedMethods() []abi.Method {
        return ut.ExportedMethods()
 }
 
-func (t rtype) NumMethod() int {
+func (t *rtype) NumMethod() int {
        if t.Kind() == Interface {
-               tt := (*interfaceType)(unsafe.Pointer(t.t))
+               tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.NumMethod()
        }
        return len(t.exportedMethods())
 }
 
-func (t rtype) Method(i int) (m Method) {
+func (t *rtype) Method(i int) (m Method) {
        if t.Kind() == Interface {
-               tt := (*interfaceType)(unsafe.Pointer(t.t))
+               tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.Method(i)
        }
        methods := t.exportedMethods()
@@ -585,15 +601,15 @@ func (t rtype) Method(i int) (m Method) {
        m.Type = mt
        tfn := t.textOff(p.Tfn)
        fn := unsafe.Pointer(&tfn)
-       m.Func = Value{mt.common(), fn, fl}
+       m.Func = Value{&mt.(*rtype).t, fn, fl}
 
        m.Index = i
        return m
 }
 
-func (t rtype) MethodByName(name string) (m Method, ok bool) {
+func (t *rtype) MethodByName(name string) (m Method, ok bool) {
        if t.Kind() == Interface {
-               tt := (*interfaceType)(unsafe.Pointer(t.t))
+               tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.MethodByName(name)
        }
        ut := t.uncommon()
@@ -623,7 +639,7 @@ func (t rtype) MethodByName(name string) (m Method, ok bool) {
        return Method{}, false
 }
 
-func (t rtype) PkgPath() string {
+func (t *rtype) PkgPath() string {
        if t.t.TFlag&abi.TFlagNamed == 0 {
                return ""
        }
@@ -638,7 +654,7 @@ func pkgPathFor(t *abi.Type) string {
        return toRType(t).PkgPath()
 }
 
-func (t rtype) Name() string {
+func (t *rtype) Name() string {
        if !t.t.HasName() {
                return ""
        }
@@ -661,16 +677,16 @@ func nameFor(t *abi.Type) string {
        return toRType(t).Name()
 }
 
-func (t rtype) ChanDir() ChanDir {
+func (t *rtype) ChanDir() ChanDir {
        if t.Kind() != Chan {
                panic("reflect: ChanDir of non-chan type " + t.String())
        }
-       tt := (*abi.ChanType)(unsafe.Pointer(t.t))
+       tt := (*abi.ChanType)(unsafe.Pointer(t))
        return ChanDir(tt.Dir)
 }
 
-func toRType(t *abi.Type) rtype {
-       return rtype{t}
+func toRType(t *abi.Type) *rtype {
+       return (*rtype)(unsafe.Pointer(t))
 }
 
 func elem(t *abi.Type) *abi.Type {
@@ -681,131 +697,103 @@ func elem(t *abi.Type) *abi.Type {
        panic("reflect: Elem of invalid type " + stringFor(t))
 }
 
-func (t rtype) Elem() Type {
+func (t *rtype) Elem() Type {
        return toType(elem(t.common()))
 }
 
-func (t rtype) structType() *structType {
+func (t *rtype) Field(i int) StructField {
        if t.Kind() != Struct {
-               return nil
-       }
-       return (*structType)(unsafe.Pointer(t.t))
-}
-
-func (t rtype) mapType() *mapType {
-       if t.Kind() != Map {
-               return nil
-       }
-       return (*mapType)(unsafe.Pointer(t.t))
-}
-
-func (t rtype) arrayType() *arrayType {
-       if t.Kind() != Array {
-               return nil
-       }
-       return (*arrayType)(unsafe.Pointer(t.t))
-}
-
-func (t rtype) funcType() *funcType {
-       if t.Kind() != Func {
-               return nil
-       }
-       return (*funcType)(unsafe.Pointer(t.t))
-}
-
-func (t rtype) Field(i int) StructField {
-       tt := t.structType()
-       if tt == nil {
                panic("reflect: Field of non-struct type " + t.String())
        }
+       tt := (*structType)(unsafe.Pointer(t))
        return tt.Field(i)
 }
 
-func (t rtype) FieldByIndex(index []int) StructField {
-       tt := t.structType()
-       if tt == nil {
+func (t *rtype) FieldByIndex(index []int) StructField {
+       if t.Kind() != Struct {
                panic("reflect: FieldByIndex of non-struct type " + t.String())
        }
+       tt := (*structType)(unsafe.Pointer(t))
        return tt.FieldByIndex(index)
 }
 
-func (t rtype) FieldByName(name string) (StructField, bool) {
-       tt := t.structType()
-       if tt == nil {
+func (t *rtype) FieldByName(name string) (StructField, bool) {
+       if t.Kind() != Struct {
                panic("reflect: FieldByName of non-struct type " + t.String())
        }
+       tt := (*structType)(unsafe.Pointer(t))
        return tt.FieldByName(name)
 }
 
-func (t rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
-       tt := t.structType()
-       if tt == nil {
+func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
+       if t.Kind() != Struct {
                panic("reflect: FieldByNameFunc of non-struct type " + t.String())
        }
+       tt := (*structType)(unsafe.Pointer(t))
        return tt.FieldByNameFunc(match)
 }
 
-func (t rtype) Key() Type {
-       tt := t.mapType()
-       if tt == nil {
+func (t *rtype) Key() Type {
+       if t.Kind() != Map {
                panic("reflect: Key of non-map type " + t.String())
        }
+       tt := (*mapType)(unsafe.Pointer(t))
        return toType(tt.Key)
 }
 
-func (t rtype) Len() int {
-       tt := t.arrayType()
-       if tt == nil {
+func (t *rtype) Len() int {
+       if t.Kind() != Array {
                panic("reflect: Len of non-array type " + t.String())
        }
+       tt := (*arrayType)(unsafe.Pointer(t))
        return int(tt.Len)
 }
 
-func (t rtype) NumField() int {
-       tt := t.structType()
-       if tt == nil {
+func (t *rtype) NumField() int {
+       if t.Kind() != Struct {
                panic("reflect: NumField of non-struct type " + t.String())
        }
+       tt := (*structType)(unsafe.Pointer(t))
        return len(tt.Fields)
 }
 
-func (t rtype) In(i int) Type {
-       tt := t.funcType()
-       if tt == nil {
+func (t *rtype) In(i int) Type {
+       if t.Kind() != Func {
                panic("reflect: In of non-func type " + t.String())
        }
+       tt := (*abi.FuncType)(unsafe.Pointer(t))
        return toType(tt.InSlice()[i])
 }
 
-func (t rtype) NumIn() int {
-       tt := t.funcType()
-       if tt == nil {
+func (t *rtype) NumIn() int {
+       if t.Kind() != Func {
                panic("reflect: NumIn of non-func type " + t.String())
        }
+       tt := (*abi.FuncType)(unsafe.Pointer(t))
        return tt.NumIn()
 }
 
-func (t rtype) NumOut() int {
-       tt := t.funcType()
-       if tt == nil {
+func (t *rtype) NumOut() int {
+       if t.Kind() != Func {
                panic("reflect: NumOut of non-func type " + t.String())
        }
+       tt := (*abi.FuncType)(unsafe.Pointer(t))
        return tt.NumOut()
 }
 
-func (t rtype) Out(i int) Type {
-       tt := t.funcType()
-       if tt == nil {
+func (t *rtype) Out(i int) Type {
+       if t.Kind() != Func {
                panic("reflect: Out of non-func type " + t.String())
        }
+       tt := (*abi.FuncType)(unsafe.Pointer(t))
        return toType(tt.OutSlice()[i])
 }
 
-func (t rtype) IsVariadic() bool {
-       tt := t.funcType()
-       if tt == nil {
+func (t *rtype) IsVariadic() bool {
+       if t.Kind() != Func {
                panic("reflect: IsVariadic of non-func type " + t.String())
        }
+       tt := (*abi.FuncType)(unsafe.Pointer(t))
        return tt.IsVariadic()
 }
 
@@ -1159,7 +1147,7 @@ func TypeOf(i any) Type {
        return toType(eface.typ)
 }
 
-// rtypeOf directly extracts the type of the provided value.
+// rtypeOf directly extracts the *rtype of the provided value.
 func rtypeOf(i any) *abi.Type {
        eface := *(*emptyInterface)(unsafe.Pointer(&i))
        return eface.typ
@@ -1178,11 +1166,11 @@ func PtrTo(t Type) Type { return PointerTo(t) }
 // PointerTo returns the pointer type with element t.
 // For example, if t represents type Foo, PointerTo(t) represents *Foo.
 func PointerTo(t Type) Type {
-       return toRType(t.(rtype).ptrTo())
+       return toRType(t.(*rtype).ptrTo())
 }
 
-func (t rtype) ptrTo() *abi.Type {
-       at := t.t
+func (t *rtype) ptrTo() *abi.Type {
+       at := &t.t
        if at.PtrToThis != 0 {
                return t.typeOff(at.PtrToThis)
        }
@@ -1196,7 +1184,7 @@ func (t rtype) ptrTo() *abi.Type {
        s := "*" + t.String()
        for _, tt := range typesByString(s) {
                p := (*ptrType)(unsafe.Pointer(tt))
-               if p.Elem != t.t {
+               if p.Elem != &t.t {
                        continue
                }
                pi, _ := ptrMap.LoadOrStore(t, p)
@@ -1237,7 +1225,7 @@ func fnv1(x uint32, list ...byte) uint32 {
        return x
 }
 
-func (t rtype) Implements(u Type) bool {
+func (t *rtype) Implements(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.Implements")
        }
@@ -1247,7 +1235,7 @@ func (t rtype) Implements(u Type) bool {
        return implements(u.common(), t.common())
 }
 
-func (t rtype) AssignableTo(u Type) bool {
+func (t *rtype) AssignableTo(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.AssignableTo")
        }
@@ -1255,14 +1243,14 @@ func (t rtype) AssignableTo(u Type) bool {
        return directlyAssignable(uu, t.common()) || implements(uu, t.common())
 }
 
-func (t rtype) ConvertibleTo(u Type) bool {
+func (t *rtype) ConvertibleTo(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.ConvertibleTo")
        }
        return convertOp(u.common(), t.common()) != nil
 }
 
-func (t rtype) Comparable() bool {
+func (t *rtype) Comparable() bool {
        return t.t.Equal != nil
 }
 
@@ -1494,14 +1482,14 @@ func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
 
 // typelinks is implemented in package runtime.
 // It returns a slice of the sections in each module,
-// and a slice of *abi.Type offsets in each module.
+// and a slice of *rtype offsets in each module.
 //
 // The types in each module are sorted by string. That is, the first
 // two linked types of the first module are:
 //
 //     d0 := sections[0]
-//     t1 := (*abi.Type)(add(d0, offset[0][0]))
-//     t2 := (*abi.Type)(add(d0, offset[0][1]))
+//     t1 := (*rtype)(add(d0, offset[0][0]))
+//     t2 := (*rtype)(add(d0, offset[0][1]))
 //
 // and
 //
@@ -1557,7 +1545,7 @@ func typesByString(s string) []*abi.Type {
 }
 
 // The lookupCache caches ArrayOf, ChanOf, MapOf and SliceOf lookups.
-var lookupCache sync.Map // map[cacheKey]rtype
+var lookupCache sync.Map // map[cacheKey]*rtype
 
 // A cacheKey is the key for use in the lookupCache.
 // Four values describe any of the types we are looking for:
@@ -1575,7 +1563,7 @@ type cacheKey struct {
 var funcLookupCache struct {
        sync.Mutex // Guards stores (but not loads) on m.
 
-       // m is a map[uint32][]rtype keyed by the hash calculated in FuncOf.
+       // m is a map[uint32][]*rtype keyed by the hash calculated in FuncOf.
        // Elements of m are append-only and thus safe for concurrent reading.
        m sync.Map
 }
@@ -1591,7 +1579,7 @@ func ChanOf(dir ChanDir, t Type) Type {
        // Look in cache.
        ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
        if ch, ok := lookupCache.Load(ckey); ok {
-               return ch.(rtype)
+               return ch.(*rtype)
        }
 
        // This restriction is imposed by the gc compiler and the runtime.
@@ -1766,13 +1754,13 @@ func FuncOf(in, out []Type, variadic bool) Type {
 
        o := New(initFuncTypes(n)).Elem()
        ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
-       args := unsafe.Slice((*rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
+       args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
        *ft = *prototype
 
        // Build a hash and minimally populate ft.
        var hash uint32
        for _, in := range in {
-               t := in.(rtype)
+               t := in.(*rtype)
                args = append(args, t)
                hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
        }
@@ -1781,7 +1769,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
        }
        hash = fnv1(hash, '.')
        for _, out := range out {
-               t := out.(rtype)
+               t := out.(*rtype)
                args = append(args, t)
                hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
        }
@@ -2020,6 +2008,10 @@ func bucketOf(ktyp, etyp *abi.Type) *abi.Type {
        return b
 }
 
+func (t *rtype) gcSlice(begin, end uintptr) []byte {
+       return (*[1 << 30]byte)(unsafe.Pointer(t.t.GCData))[begin:end:end]
+}
+
 // emitGCMask writes the GC mask for [n]typ into out, starting at bit
 // offset base.
 func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
@@ -2668,7 +2660,7 @@ func ArrayOf(length int, elem Type) Type {
        array.Align_ = typ.Align_
        array.FieldAlign_ = typ.FieldAlign_
        array.Len = uintptr(length)
-       array.Slice = SliceOf(elem).common()
+       array.Slice = &(SliceOf(elem).(*rtype).t)
 
        switch {
        case typ.PtrBytes == 0 || array.Size_ == 0:
@@ -2762,9 +2754,9 @@ func appendVarint(x []byte, v uintptr) []byte {
        return x
 }
 
-// toType converts from a *abi.Type to a Type that can be returned
+// toType converts from a *rtype to a Type that can be returned
 // to the client of package reflect. In gc, the only concern is that
-// a nil *abi.Type must be replaced by a nil Type, but in gccgo this
+// a nil *rtype must be replaced by a nil Type, but in gccgo this
 // function takes care of ensuring that multiple *rtype for the same
 // type are coalesced into a single Type.
 func toType(t *abi.Type) Type {
index 849e00fa44643dc9b2229e54fc88f1b71c7a3558..f079b8228bd68577a22ec79e3240d5e341af77f6 100644 (file)
@@ -517,11 +517,11 @@ func (v Value) call(op string, in []Value) []Value {
        // Handle arguments.
        for i, v := range in {
                v.mustBeExported()
-               targ := t.In(i)
+               targ := toRType(t.In(i))
                // TODO(mknyszek): Figure out if it's possible to get some
                // scratch space for this assignment check. Previously, it
                // was possible to use space in the argument frame.
-               v = v.assignTo("reflect.Value.Call", targ, nil)
+               v = v.assignTo("reflect.Value.Call", &targ.t, nil)
        stepsLoop:
                for _, st := range abid.call.stepsForValue(i + inStart) {
                        switch st.kind {
@@ -529,7 +529,7 @@ func (v Value) call(op string, in []Value) []Value {
                                // Copy values to the "stack."
                                addr := add(stackArgs, st.stkOff, "precomputed stack arg offset")
                                if v.flag&flagIndir != 0 {
-                                       typedmemmove(targ, addr, v.ptr)
+                                       typedmemmove(&targ.t, addr, v.ptr)
                                } else {
                                        *(*unsafe.Pointer)(addr) = v.ptr
                                }
@@ -2600,7 +2600,7 @@ func (v Value) TrySend(x Value) bool {
 // Type returns v's type.
 func (v Value) Type() Type {
        if v.flag != 0 && v.flag&flagMethod == 0 {
-               return rtype{v.typ} // inline of toRType(v.typ), for own inlining in inline test
+               return (*rtype)(unsafe.Pointer(v.typ)) // inline of toRType(v.typ), for own inlining in inline test
        }
        return v.typeSlow()
 }
@@ -2929,7 +2929,7 @@ func Copy(dst, src Value) int {
 // This must match ../runtime/select.go:/runtimeSelect
 type runtimeSelect struct {
        dir SelectDir      // SelectSend, SelectRecv or SelectDefault
-       typ *abi.Type      // channel type
+       typ *rtype         // channel type
        ch  unsafe.Pointer // channel
        val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir)
 }
@@ -3032,7 +3032,7 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
                                panic("reflect.Select: SendDir case using recv-only channel")
                        }
                        rc.ch = ch.pointer()
-                       rc.typ = &tt.Type
+                       rc.typ = toRType(&tt.Type)
                        v := c.Send
                        if !v.IsValid() {
                                panic("reflect.Select: SendDir case missing Send value")
@@ -3060,7 +3060,7 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
                                panic("reflect.Select: RecvDir case using send-only channel")
                        }
                        rc.ch = ch.pointer()
-                       rc.typ = &tt.Type
+                       rc.typ = toRType(&tt.Type)
                        rc.val = unsafe_New(tt.Elem)
                }
        }
@@ -3104,8 +3104,8 @@ func MakeSlice(typ Type, len, cap int) Value {
                panic("reflect.MakeSlice: len > cap")
        }
 
-       s := unsafeheader.Slice{Data: unsafe_NewArray(typ.Elem().common(), cap), Len: len, Cap: cap}
-       return Value{typ.common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
+       s := unsafeheader.Slice{Data: unsafe_NewArray(&(typ.Elem().(*rtype).t), cap), Len: len, Cap: cap}
+       return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
 }
 
 // MakeChan creates a new channel with the specified type and buffer size.
@@ -3175,7 +3175,7 @@ func Zero(typ Type) Value {
        if typ == nil {
                panic("reflect: Zero(nil)")
        }
-       t := typ.common()
+       t := &typ.(*rtype).t
        fl := flag(t.Kind())
        if t.IfaceIndir() {
                var p unsafe.Pointer
@@ -3201,7 +3201,7 @@ func New(typ Type) Value {
        if typ == nil {
                panic("reflect: New(nil)")
        }
-       t := typ.common()
+       t := &typ.(*rtype).t
        pt := ptrTo(t)
        if ifaceIndir(pt) {
                // This is a pointer to a not-in-heap type.
@@ -3216,7 +3216,7 @@ func New(typ Type) Value {
 // specified type, using p as that pointer.
 func NewAt(typ Type, p unsafe.Pointer) Value {
        fl := flag(Pointer)
-       t := typ.(rtype)
+       t := typ.(*rtype)
        return Value{t.ptrTo(), p, fl}
 }