]> Cypherpunks repositories - gostls13.git/commitdiff
internal/abi: move direct/indirect flag from Kind to TFlag
authorKeith Randall <khr@golang.org>
Sun, 15 Jun 2025 00:06:20 +0000 (17:06 -0700)
committerKeith Randall <khr@golang.org>
Tue, 29 Jul 2025 21:03:07 +0000 (14:03 -0700)
This info makes more sense in the flags instead of as a high
bit of the kind. This makes kind access simpler because we now
don't need to mask anything.

Cleaned up most direct field accesses to use methods instead.
(reflect making new types is the only remaining direct accessor.)

IfaceIndir -> !IsDirectIface everywhere.

gocore has been updated to handle the new location. So has delve.
TODO: any other tools need updating?

Change-Id: I123f97a4d4bdd0bff1641ee7e276d1cc0bd7e8eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/681936
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

29 files changed:
src/cmd/compile/internal/reflectdata/reflect.go
src/cmd/compile/internal/test/inl_test.go
src/cmd/link/internal/ld/decodesym.go
src/internal/abi/type.go
src/internal/reflectlite/export_test.go
src/internal/reflectlite/value.go
src/internal/runtime/maps/map.go
src/reflect/abi.go
src/reflect/badlinkname.go
src/reflect/export_noswiss_test.go
src/reflect/map_swiss.go
src/reflect/type.go
src/reflect/value.go
src/runtime/alg.go
src/runtime/arena.go
src/runtime/cgocall.go
src/runtime/debuglog.go
src/runtime/error.go
src/runtime/export_debug_test.go
src/runtime/export_test.go
src/runtime/heapdump.go
src/runtime/mbitmap.go
src/runtime/mfinal.go
src/runtime/pinner.go
src/runtime/plugin.go
src/runtime/race.go
src/runtime/syscall_windows.go
src/runtime/type.go
src/runtime/typekind.go [deleted file]

index fb60569670ea662d042a5eb57dc9e21171341a03..62cef16816c61a851b607c965be8c125f66e5c7c 100644 (file)
@@ -491,6 +491,9 @@ func dcommontype(c rttype.Cursor, t *types.Type) {
                        exported = types.IsExported(t.Elem().Sym().Name)
                }
        }
+       if types.IsDirectIface(t) {
+               tflag |= abi.TFlagDirectIface
+       }
 
        if tflag != abi.TFlag(uint8(tflag)) {
                // this should optimize away completely
@@ -511,9 +514,6 @@ func dcommontype(c rttype.Cursor, t *types.Type) {
        c.Field("FieldAlign_").WriteUint8(uint8(t.Alignment()))
 
        kind := kinds[t.Kind()]
-       if types.IsDirectIface(t) {
-               kind |= abi.KindDirectIface
-       }
        c.Field("Kind_").WriteUint8(uint8(kind))
 
        c.Field("Equal").WritePtr(eqfunc)
index 091933e1e75ed25ebf20ee1e9710d6cba7facf30..ace95f78a6c3ded5de86f4ad222d9f5fd221915f 100644 (file)
@@ -47,7 +47,6 @@ func TestIntendedInlining(t *testing.T) {
                        "getMCache",
                        "heapSetTypeNoHeader",
                        "heapSetTypeSmallHeader",
-                       "isDirectIface",
                        "itabHashFunc",
                        "nextslicecap",
                        "noescape",
@@ -109,6 +108,7 @@ func TestIntendedInlining(t *testing.T) {
                        "(*Buffer).tryGrowByReslice",
                },
                "internal/abi": {
+                       "(*Type).IsDirectIface",
                        "UseInterfaceSwitchCache",
                },
                "internal/runtime/math": {
index 4d38ec1a776e2341b1bbfc8875f4d96b57ca4fba..248205539d458b0c38aa8e54e64a97292debfc89 100644 (file)
@@ -38,7 +38,7 @@ func uncommonSize(arch *sys.Arch) int    { return int(abi.UncommonSize()) }
 
 // Type.commonType.kind
 func decodetypeKind(arch *sys.Arch, p []byte) abi.Kind {
-       return abi.Kind(p[2*arch.PtrSize+7]) & abi.KindMask //  0x13 / 0x1f
+       return abi.Kind(p[2*arch.PtrSize+7]) //  0x13
 }
 
 // Type.commonType.size
index 786fb9cd66e053f02e04005a5ffacfb02811fa11..29e17cf6a2d67e89b1c6b858b8a8c3127aaee338 100644 (file)
@@ -24,7 +24,7 @@ type Type struct {
        TFlag       TFlag   // extra type information flags
        Align_      uint8   // alignment of variable with this type
        FieldAlign_ uint8   // alignment of struct field with this type
-       Kind_       Kind    // enumeration for C
+       Kind_       Kind    // what kind of type this is (string, int, ...)
        // function for comparing objects of this type
        // (ptr to object A, ptr to object B) -> ==?
        Equal func(unsafe.Pointer, unsafe.Pointer) bool
@@ -78,12 +78,6 @@ const (
        UnsafePointer
 )
 
-const (
-       // TODO (khr, drchase) why aren't these in TFlag?  Investigate, fix if possible.
-       KindDirectIface Kind = 1 << 5
-       KindMask        Kind = (1 << 5) - 1
-)
-
 // TFlag is used by a Type to signal what extra type information is
 // available in the memory directly following the Type value.
 type TFlag uint8
@@ -125,6 +119,15 @@ const (
        // has type **byte instead of *byte. The runtime will store a
        // pointer to the GC pointer bitmask in *GCData.
        TFlagGCMaskOnDemand TFlag = 1 << 4
+
+       // TFlagDirectIface means that a value of this type is stored directly
+       // in the data field of an interface, instead of indirectly. Normally
+       // this means the type is pointer-ish.
+       TFlagDirectIface TFlag = 1 << 5
+
+       // Leaving this breadcrumb behind for dlv. It should not be used, and no
+       // Kind should be big enough to set this bit.
+       KindDirectIface Kind = 1 << 5
 )
 
 // NameOff is the offset to a name from moduledata.types.  See resolveNameOff in runtime.
@@ -190,7 +193,7 @@ func TypeFor[T any]() *Type {
        return (*PtrType)(unsafe.Pointer(TypeOf((*T)(nil)))).Elem
 }
 
-func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
+func (t *Type) Kind() Kind { return t.Kind_ }
 
 func (t *Type) HasName() bool {
        return t.TFlag&TFlagNamed != 0
@@ -199,14 +202,9 @@ func (t *Type) HasName() bool {
 // Pointers reports whether t contains pointers.
 func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
 
-// IfaceIndir reports whether t is stored indirectly in an interface value.
-func (t *Type) IfaceIndir() bool {
-       return t.Kind_&KindDirectIface == 0
-}
-
-// isDirectIface reports whether t is stored directly in an interface value.
+// IsDirectIface reports whether t is stored directly in an interface value.
 func (t *Type) IsDirectIface() bool {
-       return t.Kind_&KindDirectIface != 0
+       return t.TFlag&TFlagDirectIface != 0
 }
 
 func (t *Type) GcSlice(begin, end uintptr) []byte {
index 0ad3d97c15f9957423e2230bef129e801da9d956..93762a83874106ef7dfbfabee1721a5714f14e88 100644 (file)
@@ -70,7 +70,7 @@ func Zero(typ Type) Value {
        }
        t := typ.common()
        fl := flag(t.Kind())
-       if t.IfaceIndir() {
+       if !t.IsDirectIface() {
                return Value{t, unsafe_New(t), fl | flagIndir}
        }
        return Value{t, nil, fl}
index 7b231d554f50d11aaae1aeb9d8a4916b6f77ae7b..a92df613f55d1eb1ecf73f469788d86f07a9ae2f 100644 (file)
@@ -52,7 +52,7 @@ type Value struct {
        //      - flagIndir: val holds a pointer to the data
        //      - flagAddr: v.CanAddr is true (implies flagIndir and ptr is non-nil)
        //      - flagMethod: v is a method value.
-       // If ifaceIndir(typ), code can assume that flagIndir is set.
+       // If !typ.IsDirectIface(), code can assume that flagIndir is set.
        //
        // The remaining 22+ bits give a method number for method values.
        // If flag.kind() != Func, code can assume that flagMethod is unset.
@@ -118,7 +118,7 @@ func packEface(v Value) any {
        e := (*abi.EmptyInterface)(unsafe.Pointer(&i))
        // First, fill in the data portion of the interface.
        switch {
-       case t.IfaceIndir():
+       case !t.IsDirectIface():
                if v.flag&flagIndir == 0 {
                        panic("bad indir")
                }
@@ -155,7 +155,7 @@ func unpackEface(i any) Value {
                return Value{}
        }
        f := flag(t.Kind())
-       if t.IfaceIndir() {
+       if !t.IsDirectIface() {
                f |= flagIndir
        }
        return Value{t, e.Data, f}
index 78fed6a5b7a01821254aefbae5a1a87ebc825788..017942cfad24fbc9764aa214da34cf005cf8cf41 100644 (file)
@@ -859,7 +859,7 @@ func mapKeyError2(t *abi.Type, p unsafe.Pointer) error {
                        return unhashableTypeError{t}
                }
 
-               if t.Kind_&abi.KindDirectIface != 0 {
+               if t.IsDirectIface() {
                        return mapKeyError2(t, unsafe.Pointer(pdata))
                } else {
                        return mapKeyError2(t, *pdata)
index b67d8217430d6882239596237f2ab2111ab927e7..bcd0a95f1b6c62f8cea4d855844121d8a5a334b7 100644 (file)
@@ -166,7 +166,7 @@ func (a *abiSeq) addRcvr(rcvr *abi.Type) (*abiStep, bool) {
        // The receiver is always one word.
        a.valueStart = append(a.valueStart, len(a.steps))
        var ok, ptr bool
-       if rcvr.IfaceIndir() || rcvr.Pointers() {
+       if !rcvr.IsDirectIface() || rcvr.Pointers() {
                ok = a.assignIntN(0, goarch.PtrSize, 1, 0b1)
                ptr = true
        } else {
index eb701bff033d145739d704b0fd6ecf185a38dafc..8a9bea6721de6b02b314bde3c674968a9a2c4135 100644 (file)
@@ -27,7 +27,7 @@ import (
 //
 //go:linkname unusedIfaceIndir reflect.ifaceIndir
 func unusedIfaceIndir(t *abi.Type) bool {
-       return t.Kind_&abi.KindDirectIface == 0
+       return !t.IsDirectIface()
 }
 
 //go:linkname valueInterface
index 34e5e92055cbd94f0a46b4d6d6523df74041183c..286ba6300d8cea409fe09256d00319547380950d 100644 (file)
@@ -7,7 +7,6 @@
 package reflect
 
 import (
-       "internal/abi"
        "unsafe"
 )
 
@@ -17,7 +16,7 @@ func MapBucketOf(x, y Type) Type {
 
 func CachedBucketOf(m Type) Type {
        t := m.(*rtype)
-       if Kind(t.t.Kind_&abi.KindMask) != Map {
+       if Kind(t.t.Kind()) != Map {
                panic("not map")
        }
        tt := (*mapType)(unsafe.Pointer(t))
index 2eac51e57dba5df282e507c4700f6be891580ae8..2f31d6689ffde5115bc4f55f4d78ada6c6fad657 100644 (file)
@@ -65,7 +65,7 @@ func MapOf(key, elem Type) Type {
        var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil)
        mt := **(**mapType)(unsafe.Pointer(&imap))
        mt.Str = resolveReflectName(newName(s, "", false, false))
-       mt.TFlag = 0
+       mt.TFlag = abi.TFlagDirectIface
        mt.Hash = fnv1(etyp.Hash, 'm', byte(ktyp.Hash>>24), byte(ktyp.Hash>>16), byte(ktyp.Hash>>8), byte(ktyp.Hash))
        mt.Key = ktyp
        mt.Elem = etyp
index 0004cab985a1f8aa2b063fdabeaa5be023d5f307..cec8662c01a28d687e304c09736bb3faab53821e 100644 (file)
@@ -1813,7 +1813,7 @@ func ChanOf(dir ChanDir, t Type) Type {
        var ichan any = (chan unsafe.Pointer)(nil)
        prototype := *(**chanType)(unsafe.Pointer(&ichan))
        ch := *prototype
-       ch.TFlag = abi.TFlagRegularMemory
+       ch.TFlag = abi.TFlagRegularMemory | abi.TFlagDirectIface
        ch.Dir = abi.ChanDir(dir)
        ch.Str = resolveReflectName(newName(s, "", false, false))
        ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
@@ -1894,7 +1894,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
                hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
        }
 
-       ft.TFlag = 0
+       ft.TFlag = abi.TFlagDirectIface
        ft.Hash = hash
        ft.InCount = uint16(len(in))
        ft.OutCount = uint16(len(out))
@@ -2313,7 +2313,7 @@ func StructOf(fields []StructField) Type {
                                                // Issue 15924.
                                                panic("reflect: embedded type with methods not implemented if type is not first field")
                                        }
-                                       if len(fields) > 1 && ft.Kind_&abi.KindDirectIface != 0 {
+                                       if len(fields) > 1 && ft.IsDirectIface() {
                                                panic("reflect: embedded type with methods not implemented for non-pointer type")
                                        }
                                        for _, m := range unt.Methods() {
@@ -2524,11 +2524,11 @@ func StructOf(fields []StructField) Type {
        }
 
        switch {
-       case len(fs) == 1 && !fs[0].Typ.IfaceIndir():
+       case len(fs) == 1 && fs[0].Typ.IsDirectIface():
                // structs of 1 direct iface type can be direct
-               typ.Kind_ |= abi.KindDirectIface
+               typ.TFlag |= abi.TFlagDirectIface
        default:
-               typ.Kind_ &^= abi.KindDirectIface
+               typ.TFlag &^= abi.TFlagDirectIface
        }
 
        return addToCache(toType(&typ.Type))
@@ -2694,11 +2694,11 @@ func ArrayOf(length int, elem Type) Type {
        }
 
        switch {
-       case length == 1 && !typ.IfaceIndir():
+       case length == 1 && typ.IsDirectIface():
                // array of 1 direct iface type can be direct
-               array.Kind_ |= abi.KindDirectIface
+               array.TFlag |= abi.TFlagDirectIface
        default:
-               array.Kind_ &^= abi.KindDirectIface
+               array.TFlag &^= abi.TFlagDirectIface
        }
 
        ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
@@ -2834,7 +2834,7 @@ func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
                return
        }
 
-       switch Kind(t.Kind_ & abi.KindMask) {
+       switch Kind(t.Kind()) {
        case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
                // 1 pointer at start of representation
                for bv.n < uint32(offset/goarch.PtrSize) {
index ffdf7896482f7e189a37b724cece4bc55c146736..6f65ef81dc3ae3dea0c989572319c7011c1d4a23 100644 (file)
@@ -55,7 +55,7 @@ type Value struct {
        //      - flagIndir: val holds a pointer to the data
        //      - flagAddr: v.CanAddr is true (implies flagIndir and ptr is non-nil)
        //      - flagMethod: v is a method value.
-       // If ifaceIndir(typ), code can assume that flagIndir is set.
+       // If !typ.IsDirectIface(), code can assume that flagIndir is set.
        //
        // The remaining 22+ bits give a method number for method values.
        // If flag.kind() != Func, code can assume that flagMethod is unset.
@@ -125,7 +125,7 @@ func packEface(v Value) any {
        e := abi.EmptyInterface{}
        // First, fill in the data portion of the interface.
        switch {
-       case t.IfaceIndir():
+       case !t.IsDirectIface():
                if v.flag&flagIndir == 0 {
                        panic("bad indir")
                }
@@ -159,7 +159,7 @@ func unpackEface(i any) Value {
                return Value{}
        }
        f := flag(t.Kind())
-       if t.IfaceIndir() {
+       if !t.IsDirectIface() {
                f |= flagIndir
        }
        return Value{t, e.Data, f}
@@ -624,7 +624,7 @@ func (v Value) call(op string, in []Value) []Value {
                        }
 
                        // Handle pointers passed in registers.
-                       if !tv.IfaceIndir() {
+                       if tv.IsDirectIface() {
                                // Pointer-valued data gets put directly
                                // into v.ptr.
                                if steps[0].kind != abiStepPointer {
@@ -714,7 +714,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs
                v := Value{typ, nil, flag(typ.Kind())}
                steps := abid.call.stepsForValue(i)
                if st := steps[0]; st.kind == abiStepStack {
-                       if typ.IfaceIndir() {
+                       if !typ.IsDirectIface() {
                                // value cannot be inlined in interface data.
                                // Must make a copy, because f might keep a reference to it,
                                // and we cannot let f keep a reference to the stack frame
@@ -728,7 +728,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs
                                v.ptr = *(*unsafe.Pointer)(add(ptr, st.stkOff, "1-ptr"))
                        }
                } else {
-                       if typ.IfaceIndir() {
+                       if !typ.IsDirectIface() {
                                // All that's left is values passed in registers that we need to
                                // create space for the values.
                                v.flag |= flagIndir
@@ -914,7 +914,7 @@ func storeRcvr(v Value, p unsafe.Pointer) {
                // the interface data word becomes the receiver word
                iface := (*nonEmptyInterface)(v.ptr)
                *(*unsafe.Pointer)(p) = iface.word
-       } else if v.flag&flagIndir != 0 && !t.IfaceIndir() {
+       } else if v.flag&flagIndir != 0 && t.IsDirectIface() {
                *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
        } else {
                *(*unsafe.Pointer)(p) = v.ptr
@@ -1224,7 +1224,7 @@ func (v Value) Elem() Value {
        case Pointer:
                ptr := v.ptr
                if v.flag&flagIndir != 0 {
-                       if v.typ().IfaceIndir() {
+                       if !v.typ().IsDirectIface() {
                                // This is a pointer to a not-in-heap object. ptr points to a uintptr
                                // in the heap. That uintptr is the address of a not-in-heap object.
                                // In general, pointers to not-in-heap objects can be total junk.
@@ -1852,7 +1852,7 @@ func (v Value) lenNonSlice() int {
 // copyVal returns a Value containing the map key or value at ptr,
 // allocating a new variable as needed.
 func copyVal(typ *abi.Type, fl flag, ptr unsafe.Pointer) Value {
-       if typ.IfaceIndir() {
+       if !typ.IsDirectIface() {
                // Copy result so future changes to the map
                // won't change the underlying value.
                c := unsafe_New(typ)
@@ -2076,7 +2076,7 @@ func (v Value) recv(nb bool) (val Value, ok bool) {
        t := tt.Elem
        val = Value{t, nil, flag(t.Kind())}
        var p unsafe.Pointer
-       if t.IfaceIndir() {
+       if !t.IsDirectIface() {
                p = unsafe_New(t)
                val.ptr = p
                val.flag |= flagIndir
@@ -2952,7 +2952,7 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
                t := tt.Elem
                p := runcases[chosen].val
                fl := flag(t.Kind())
-               if t.IfaceIndir() {
+               if !t.IsDirectIface() {
                        recv = Value{t, p, fl | flagIndir}
                } else {
                        recv = Value{t, *(*unsafe.Pointer)(p), fl}
@@ -3065,7 +3065,7 @@ func Zero(typ Type) Value {
        }
        t := &typ.(*rtype).t
        fl := flag(t.Kind())
-       if t.IfaceIndir() {
+       if !t.IsDirectIface() {
                var p unsafe.Pointer
                if t.Size() <= abi.ZeroValSize {
                        p = unsafe.Pointer(&zeroVal[0])
@@ -3088,7 +3088,7 @@ func New(typ Type) Value {
        }
        t := &typ.(*rtype).t
        pt := ptrTo(t)
-       if pt.IfaceIndir() {
+       if !pt.IsDirectIface() {
                // This is a pointer to a not-in-heap type.
                panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)")
        }
index df32bc79414d279fee2447456826392a1d7f16d0..b956f9d05af0118847fd44e5bc6cc3d1e5914448 100644 (file)
@@ -144,7 +144,7 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr {
                // we want to report the struct, not the slice).
                panic(errorString("hash of unhashable type " + toRType(t).string()))
        }
-       if isDirectIface(t) {
+       if t.IsDirectIface() {
                return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
        } else {
                return c1 * typehash(t, a.data, h^c0)
@@ -171,7 +171,7 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
                // See comment in interhash above.
                panic(errorString("hash of unhashable type " + toRType(t).string()))
        }
-       if isDirectIface(t) {
+       if t.IsDirectIface() {
                return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
        } else {
                return c1 * typehash(t, a.data, h^c0)
@@ -211,7 +211,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
                        return memhash(p, h, t.Size_)
                }
        }
-       switch t.Kind_ & abi.KindMask {
+       switch t.Kind() {
        case abi.Float32:
                return f32hash(p, h)
        case abi.Float64:
@@ -306,7 +306,7 @@ func efaceeq(t *_type, x, y unsafe.Pointer) bool {
        if eq == nil {
                panic(errorString("comparing uncomparable type " + toRType(t).string()))
        }
-       if isDirectIface(t) {
+       if t.IsDirectIface() {
                // Direct interface types are ptr, chan, map, func, and single-element structs/arrays thereof.
                // Maps and funcs are not comparable, so they can't reach here.
                // Ptrs, chans, and single-element items can be compared directly using ==.
@@ -323,7 +323,7 @@ func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
        if eq == nil {
                panic(errorString("comparing uncomparable type " + toRType(t).string()))
        }
-       if isDirectIface(t) {
+       if t.IsDirectIface() {
                // See comment in efaceeq.
                return x == y
        }
index 0aa3876aaa1a74b57f180299537674bc2f3ff15f..52a2a99d6cae8744239c6f9c93f7cb9fec453bb9 100644 (file)
@@ -111,7 +111,7 @@ func arena_newArena() unsafe.Pointer {
 //go:linkname arena_arena_New arena.runtime_arena_arena_New
 func arena_arena_New(arena unsafe.Pointer, typ any) any {
        t := (*_type)(efaceOf(&typ).data)
-       if t.Kind_&abi.KindMask != abi.Pointer {
+       if t.Kind() != abi.Pointer {
                throw("arena_New: non-pointer type")
        }
        te := (*ptrtype)(unsafe.Pointer(t)).Elem
@@ -145,7 +145,7 @@ func arena_heapify(s any) any {
        var v unsafe.Pointer
        e := efaceOf(&s)
        t := e._type
-       switch t.Kind_ & abi.KindMask {
+       switch t.Kind() {
        case abi.String:
                v = stringStructOf((*string)(e.data)).str
        case abi.Slice:
@@ -162,7 +162,7 @@ func arena_heapify(s any) any {
        }
        // Heap-allocate storage for a copy.
        var x any
-       switch t.Kind_ & abi.KindMask {
+       switch t.Kind() {
        case abi.String:
                s1 := s.(string)
                s2, b := rawstring(len(s1))
@@ -293,11 +293,11 @@ func (a *userArena) slice(sl any, cap int) {
        }
        i := efaceOf(&sl)
        typ := i._type
-       if typ.Kind_&abi.KindMask != abi.Pointer {
+       if typ.Kind() != abi.Pointer {
                panic("slice result of non-ptr type")
        }
        typ = (*ptrtype)(unsafe.Pointer(typ)).Elem
-       if typ.Kind_&abi.KindMask != abi.Slice {
+       if typ.Kind() != abi.Slice {
                panic("slice of non-ptr-to-slice type")
        }
        typ = (*slicetype)(unsafe.Pointer(typ)).Elem
index 5bb6f58bc2e0614b1e3069a1ca1a7ea9913ed6da..18e1dc8bafc4aa2b6f3b68cbc598d169608ecba7 100644 (file)
@@ -543,18 +543,18 @@ func cgoCheckPointer(ptr any, arg any) {
        t := ep._type
 
        top := true
-       if arg != nil && (t.Kind_&abi.KindMask == abi.Pointer || t.Kind_&abi.KindMask == abi.UnsafePointer) {
+       if arg != nil && (t.Kind() == abi.Pointer || t.Kind() == abi.UnsafePointer) {
                p := ep.data
-               if t.Kind_&abi.KindDirectIface == 0 {
+               if !t.IsDirectIface() {
                        p = *(*unsafe.Pointer)(p)
                }
                if p == nil || !cgoIsGoPointer(p) {
                        return
                }
                aep := efaceOf(&arg)
-               switch aep._type.Kind_ & abi.KindMask {
+               switch aep._type.Kind() {
                case abi.Bool:
-                       if t.Kind_&abi.KindMask == abi.UnsafePointer {
+                       if t.Kind() == abi.UnsafePointer {
                                // We don't know the type of the element.
                                break
                        }
@@ -578,7 +578,7 @@ func cgoCheckPointer(ptr any, arg any) {
                        // Check the array rather than the pointer.
                        pt := (*abi.PtrType)(unsafe.Pointer(aep._type))
                        t = pt.Elem
-                       if t.Kind_&abi.KindMask != abi.Array {
+                       if t.Kind() != abi.Array {
                                throw("can't happen")
                        }
                        ep = aep
@@ -588,7 +588,7 @@ func cgoCheckPointer(ptr any, arg any) {
                }
        }
 
-       cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, top, cgoCheckPointerFail)
+       cgoCheckArg(t, ep.data, !t.IsDirectIface(), top, cgoCheckPointerFail)
 }
 
 const cgoCheckPointerFail = "cgo argument has Go pointer to unpinned Go pointer"
@@ -605,7 +605,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
                return
        }
 
-       switch t.Kind_ & abi.KindMask {
+       switch t.Kind() {
        default:
                throw("can't happen")
        case abi.Array:
@@ -614,7 +614,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
                        if at.Len != 1 {
                                throw("can't happen")
                        }
-                       cgoCheckArg(at.Elem, p, at.Elem.Kind_&abi.KindDirectIface == 0, top, msg)
+                       cgoCheckArg(at.Elem, p, !at.Elem.IsDirectIface(), top, msg)
                        return
                }
                for i := uintptr(0); i < at.Len; i++ {
@@ -652,7 +652,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
                if !top && !isPinned(p) {
                        panic(errorString(msg))
                }
-               cgoCheckArg(it, p, it.Kind_&abi.KindDirectIface == 0, false, msg)
+               cgoCheckArg(it, p, !it.IsDirectIface(), false, msg)
        case abi.Slice:
                st := (*slicetype)(unsafe.Pointer(t))
                s := (*slice)(p)
@@ -684,7 +684,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
                        if len(st.Fields) != 1 {
                                throw("can't happen")
                        }
-                       cgoCheckArg(st.Fields[0].Typ, p, st.Fields[0].Typ.Kind_&abi.KindDirectIface == 0, top, msg)
+                       cgoCheckArg(st.Fields[0].Typ, p, !st.Fields[0].Typ.IsDirectIface(), top, msg)
                        return
                }
                for _, f := range st.Fields {
@@ -792,5 +792,5 @@ func cgoCheckResult(val any) {
 
        ep := efaceOf(&val)
        t := ep._type
-       cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, false, cgoResultFail)
+       cgoCheckArg(t, ep.data, !t.IsDirectIface(), false, cgoResultFail)
 }
index 50fba3568db19656705834734cb1d4601e751a70..e993e396c14e9fb8cc151a7723ec0ee73a8c8c84 100644 (file)
@@ -327,7 +327,7 @@ func (l *dloggerImpl) p(x any) *dloggerImpl {
                l.w.uvarint(0)
        } else {
                v := efaceOf(&x)
-               switch v._type.Kind_ & abi.KindMask {
+               switch v._type.Kind() {
                case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
                        l.w.uvarint(uint64(uintptr(v.data)))
                default:
index a2611bdfd9c89cdb942c540abdcffb5afd5c5744..f95b14d7808189ef79ad6bd5747023f689a2b636 100644 (file)
@@ -260,7 +260,7 @@ func printanycustomtype(i any) {
        eface := efaceOf(&i)
        typestring := toRType(eface._type).string()
 
-       switch eface._type.Kind_ {
+       switch eface._type.Kind() {
        case abi.String:
                print(typestring, `("`)
                printindented(*(*string)(eface.data))
index 96f6fd9eea46eab627deac6adf1a3dbf0e56b94e..94dc97480420c7d4be3e2f4a002c4b9c8c350c2f 100644 (file)
@@ -33,13 +33,13 @@ func InjectDebugCall(gp *g, fn any, regArgs *abi.RegArgs, stackArgs any, tkill f
        }
 
        f := efaceOf(&fn)
-       if f._type == nil || f._type.Kind_&abi.KindMask != abi.Func {
+       if f._type == nil || f._type.Kind() != abi.Func {
                return nil, plainError("fn must be a function")
        }
        fv := (*funcval)(f.data)
 
        a := efaceOf(&stackArgs)
-       if a._type != nil && a._type.Kind_&abi.KindMask != abi.Pointer {
+       if a._type != nil && a._type.Kind() != abi.Pointer {
                return nil, plainError("args must be a pointer or nil")
        }
        argp := a.data
index 2fc5b4a38a8e856725cb72f0665b7a35f9e51bd5..3af1362ee2553704b5d82dda03981b44537e1c96 100644 (file)
@@ -1773,7 +1773,7 @@ func NewUserArena() *UserArena {
 func (a *UserArena) New(out *any) {
        i := efaceOf(out)
        typ := i._type
-       if typ.Kind_&abi.KindMask != abi.Pointer {
+       if typ.Kind() != abi.Pointer {
                panic("new result of non-ptr type")
        }
        typ = (*ptrtype)(unsafe.Pointer(typ)).Elem
index 72878d072824fcf34d71d9452176a35a1ba48ce7..d9474034c27c82ad41f5e83c2719624a470e0031 100644 (file)
@@ -206,7 +206,7 @@ func dumptype(t *_type) {
                dwritebyte('.')
                dwrite(unsafe.Pointer(unsafe.StringData(name)), uintptr(len(name)))
        }
-       dumpbool(t.Kind_&abi.KindDirectIface == 0 || t.Pointers())
+       dumpbool(!t.IsDirectIface() || t.Pointers())
 }
 
 // dump an object.
index b2557275ece37365f140138e5f21b7cde4500541..9872e5297fb4b7618f6c9e7bf26e8c711a8c0be8 100644 (file)
@@ -947,7 +947,7 @@ func doubleCheckTypePointersOfType(s *mspan, typ *_type, addr, size uintptr) {
        if typ == nil {
                return
        }
-       if typ.Kind_&abi.KindMask == abi.Interface {
+       if typ.Kind() == abi.Interface {
                // Interfaces are unfortunately inconsistently handled
                // when it comes to the type pointer, so it's easy to
                // produce a lot of false positives here.
@@ -1776,7 +1776,7 @@ func pointerMask(ep any) (mask []byte) {
        t := e._type
 
        var et *_type
-       if t.Kind_&abi.KindMask != abi.Pointer {
+       if t.Kind() != abi.Pointer {
                throw("bad argument to getgcmask: expected type to be a pointer to the value type whose mask is being queried")
        }
        et = (*ptrtype)(unsafe.Pointer(t)).Elem
index 2d4a54c9332022903314dd8788be462edd4bf524..bafdb016038830aa0c132a2fc287b2dd5f0f583e 100644 (file)
@@ -251,7 +251,7 @@ func runFinalizers() {
                                        // confusing the write barrier.
                                        *(*[2]uintptr)(frame) = [2]uintptr{}
                                }
-                               switch f.fint.Kind_ & abi.KindMask {
+                               switch f.fint.Kind() {
                                case abi.Pointer:
                                        // direct use of pointer
                                        *(*unsafe.Pointer)(r) = f.arg
@@ -435,7 +435,7 @@ func SetFinalizer(obj any, finalizer any) {
        if etyp == nil {
                throw("runtime.SetFinalizer: first argument is nil")
        }
-       if etyp.Kind_&abi.KindMask != abi.Pointer {
+       if etyp.Kind() != abi.Pointer {
                throw("runtime.SetFinalizer: first argument is " + toRType(etyp).string() + ", not pointer")
        }
        ot := (*ptrtype)(unsafe.Pointer(etyp))
@@ -490,7 +490,7 @@ func SetFinalizer(obj any, finalizer any) {
                return
        }
 
-       if ftyp.Kind_&abi.KindMask != abi.Func {
+       if ftyp.Kind() != abi.Func {
                throw("runtime.SetFinalizer: second argument is " + toRType(ftyp).string() + ", not a function")
        }
        ft := (*functype)(unsafe.Pointer(ftyp))
@@ -505,13 +505,13 @@ func SetFinalizer(obj any, finalizer any) {
        case fint == etyp:
                // ok - same type
                goto okarg
-       case fint.Kind_&abi.KindMask == abi.Pointer:
+       case fint.Kind() == abi.Pointer:
                if (fint.Uncommon() == nil || etyp.Uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).Elem == ot.Elem {
                        // ok - not same type, but both pointers,
                        // one or the other is unnamed, and same element type, so assignable.
                        goto okarg
                }
-       case fint.Kind_&abi.KindMask == abi.Interface:
+       case fint.Kind() == abi.Interface:
                ityp := (*interfacetype)(unsafe.Pointer(fint))
                if len(ityp.Methods) == 0 {
                        // ok - satisfies empty interface
index 543bfdb7a4b801a60f3d026cc5054b5035e22d9f..424dd065efd57766aade1b3eb4b1702f3b768165 100644 (file)
@@ -108,7 +108,7 @@ func pinnerGetPtr(i *any) unsafe.Pointer {
        if etyp == nil {
                panic(errorString("runtime.Pinner: argument is nil"))
        }
-       if kind := etyp.Kind_ & abi.KindMask; kind != abi.Pointer && kind != abi.UnsafePointer {
+       if kind := etyp.Kind(); kind != abi.Pointer && kind != abi.UnsafePointer {
                panic(errorString("runtime.Pinner: argument is not a pointer: " + toRType(etyp).string()))
        }
        if inUserArenaChunk(uintptr(e.data)) {
index 4b6821b1fbbc9b48423503dc28a7a1bdce81c1ff..49cf13cb64673bb78c891ed9cc78a0b9e185e881 100644 (file)
@@ -88,7 +88,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]any, initTasks []*ini
                (*valp)[0] = unsafe.Pointer(t)
 
                name := symName.Name()
-               if t.Kind_&abi.KindMask == abi.Func {
+               if t.Kind() == abi.Func {
                        name = "." + name
                }
                syms[name] = val
index 7e7bca76ac66980a9508efda0651ca307d255918..2cd4e3a9a24f233df679ca4bd4b3e0f5d0acb0f3 100644 (file)
@@ -156,7 +156,7 @@ const raceenabled = true
 // callerpc is a return PC of the function that calls this function,
 // pc is start PC of the function that calls this function.
 func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
-       kind := t.Kind_ & abi.KindMask
+       kind := t.Kind()
        if kind == abi.Array || kind == abi.Struct {
                // for composite objects we have to read every address
                // because a write might happen to any subobject.
@@ -174,7 +174,7 @@ func race_ReadObjectPC(t *abi.Type, addr unsafe.Pointer, callerpc, pc uintptr) {
 }
 
 func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
-       kind := t.Kind_ & abi.KindMask
+       kind := t.Kind()
        if kind == abi.Array || kind == abi.Struct {
                // for composite objects we have to write every address
                // because a write might happen to any subobject.
index 93392896cb9512f10ff05c92c181543f9a0a6bf6..0f74ebbe240eafad603a68fc1b2d7a3fe7b9a27b 100644 (file)
@@ -104,7 +104,7 @@ func (p *abiDesc) assignArg(t *_type) {
                // registers and the stack.
                panic("compileCallback: argument size is larger than uintptr")
        }
-       if k := t.Kind_ & abi.KindMask; GOARCH != "386" && (k == abi.Float32 || k == abi.Float64) {
+       if k := t.Kind(); GOARCH != "386" && (k == abi.Float32 || k == abi.Float64) {
                // In fastcall, floating-point arguments in
                // the first four positions are passed in
                // floating-point registers, which we don't
@@ -175,7 +175,7 @@ func (p *abiDesc) assignArg(t *_type) {
 //
 // Returns whether the assignment succeeded.
 func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
-       switch k := t.Kind_ & abi.KindMask; k {
+       switch k := t.Kind(); k {
        case abi.Bool, abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uintptr, abi.Pointer, abi.UnsafePointer:
                // Assign a register for all these types.
                return p.assignReg(t.Size_, offset)
@@ -270,7 +270,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
                cdecl = false
        }
 
-       if fn._type == nil || (fn._type.Kind_&abi.KindMask) != abi.Func {
+       if fn._type == nil || fn._type.Kind() != abi.Func {
                panic("compileCallback: expected function with one uintptr-sized result")
        }
        ft := (*functype)(unsafe.Pointer(fn._type))
@@ -291,7 +291,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
        if ft.OutSlice()[0].Size_ != goarch.PtrSize {
                panic("compileCallback: expected function with one uintptr-sized result")
        }
-       if k := ft.OutSlice()[0].Kind_ & abi.KindMask; k == abi.Float32 || k == abi.Float64 {
+       if k := ft.OutSlice()[0].Kind(); k == abi.Float32 || k == abi.Float64 {
                // In cdecl and stdcall, float results are returned in
                // ST(0). In fastcall, they're returned in XMM0.
                // Either way, it's not AX.
index c11c866cd870c2f439219ffe67b2e86e0e9405b2..baaaeafc4a3550091384260df19503a787bcdbdb 100644 (file)
@@ -69,7 +69,7 @@ func (t rtype) pkgpath() string {
        if u := t.uncommon(); u != nil {
                return t.nameOff(u.PkgPath).Name()
        }
-       switch t.Kind_ & abi.KindMask {
+       switch t.Kind() {
        case abi.Struct:
                st := (*structtype)(unsafe.Pointer(t.Type))
                return st.PkgPath.Name()
@@ -522,8 +522,8 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
        if t == v {
                return true
        }
-       kind := t.Kind_ & abi.KindMask
-       if kind != v.Kind_&abi.KindMask {
+       kind := t.Kind()
+       if kind != v.Kind() {
                return false
        }
        rt, rv := toRType(t), toRType(v)
diff --git a/src/runtime/typekind.go b/src/runtime/typekind.go
deleted file mode 100644 (file)
index 4920a7c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-import "internal/abi"
-
-// isDirectIface reports whether t is stored directly in an interface value.
-func isDirectIface(t *_type) bool {
-       return t.Kind_&abi.KindDirectIface != 0
-}