From f7d167fe710501f687fad006125f4ec60be42c35 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 14 Jun 2025 17:06:20 -0700 Subject: [PATCH] internal/abi: move direct/indirect flag from Kind to TFlag 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 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- .../compile/internal/reflectdata/reflect.go | 6 ++-- src/cmd/compile/internal/test/inl_test.go | 2 +- src/cmd/link/internal/ld/decodesym.go | 2 +- src/internal/abi/type.go | 28 +++++++++---------- src/internal/reflectlite/export_test.go | 2 +- src/internal/reflectlite/value.go | 6 ++-- src/internal/runtime/maps/map.go | 2 +- src/reflect/abi.go | 2 +- src/reflect/badlinkname.go | 2 +- src/reflect/export_noswiss_test.go | 3 +- src/reflect/map_swiss.go | 2 +- src/reflect/type.go | 20 ++++++------- src/reflect/value.go | 26 ++++++++--------- src/runtime/alg.go | 10 +++---- src/runtime/arena.go | 10 +++---- src/runtime/cgocall.go | 22 +++++++-------- src/runtime/debuglog.go | 2 +- src/runtime/error.go | 2 +- src/runtime/export_debug_test.go | 4 +-- src/runtime/export_test.go | 2 +- src/runtime/heapdump.go | 2 +- src/runtime/mbitmap.go | 4 +-- src/runtime/mfinal.go | 10 +++---- src/runtime/pinner.go | 2 +- src/runtime/plugin.go | 2 +- src/runtime/race.go | 4 +-- src/runtime/syscall_windows.go | 8 +++--- src/runtime/type.go | 6 ++-- src/runtime/typekind.go | 12 -------- 29 files changed, 95 insertions(+), 110 deletions(-) delete mode 100644 src/runtime/typekind.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index fb60569670..62cef16816 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -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) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 091933e1e7..ace95f78a6 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -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": { diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index 4d38ec1a77..248205539d 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -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 diff --git a/src/internal/abi/type.go b/src/internal/abi/type.go index 786fb9cd66..29e17cf6a2 100644 --- a/src/internal/abi/type.go +++ b/src/internal/abi/type.go @@ -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 { diff --git a/src/internal/reflectlite/export_test.go b/src/internal/reflectlite/export_test.go index 0ad3d97c15..93762a8387 100644 --- a/src/internal/reflectlite/export_test.go +++ b/src/internal/reflectlite/export_test.go @@ -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} diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 7b231d554f..a92df613f5 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -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} diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go index 78fed6a5b7..017942cfad 100644 --- a/src/internal/runtime/maps/map.go +++ b/src/internal/runtime/maps/map.go @@ -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) diff --git a/src/reflect/abi.go b/src/reflect/abi.go index b67d821743..bcd0a95f1b 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -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 { diff --git a/src/reflect/badlinkname.go b/src/reflect/badlinkname.go index eb701bff03..8a9bea6721 100644 --- a/src/reflect/badlinkname.go +++ b/src/reflect/badlinkname.go @@ -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 diff --git a/src/reflect/export_noswiss_test.go b/src/reflect/export_noswiss_test.go index 34e5e92055..286ba6300d 100644 --- a/src/reflect/export_noswiss_test.go +++ b/src/reflect/export_noswiss_test.go @@ -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)) diff --git a/src/reflect/map_swiss.go b/src/reflect/map_swiss.go index 2eac51e57d..2f31d6689f 100644 --- a/src/reflect/map_swiss.go +++ b/src/reflect/map_swiss.go @@ -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 diff --git a/src/reflect/type.go b/src/reflect/type.go index 0004cab985..cec8662c01 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -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) { diff --git a/src/reflect/value.go b/src/reflect/value.go index ffdf789648..6f65ef81dc 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -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)") } diff --git a/src/runtime/alg.go b/src/runtime/alg.go index df32bc7941..b956f9d05a 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -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 } diff --git a/src/runtime/arena.go b/src/runtime/arena.go index 0aa3876aaa..52a2a99d6c 100644 --- a/src/runtime/arena.go +++ b/src/runtime/arena.go @@ -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 diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 5bb6f58bc2..18e1dc8baf 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -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) } diff --git a/src/runtime/debuglog.go b/src/runtime/debuglog.go index 50fba3568d..e993e396c1 100644 --- a/src/runtime/debuglog.go +++ b/src/runtime/debuglog.go @@ -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: diff --git a/src/runtime/error.go b/src/runtime/error.go index a2611bdfd9..f95b14d780 100644 --- a/src/runtime/error.go +++ b/src/runtime/error.go @@ -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)) diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index 96f6fd9eea..94dc974804 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -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 diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 2fc5b4a38a..3af1362ee2 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -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 diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 72878d0728..d9474034c2 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -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. diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index b2557275ec..9872e5297f 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -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 diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go index 2d4a54c933..bafdb01603 100644 --- a/src/runtime/mfinal.go +++ b/src/runtime/mfinal.go @@ -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 diff --git a/src/runtime/pinner.go b/src/runtime/pinner.go index 543bfdb7a4..424dd065ef 100644 --- a/src/runtime/pinner.go +++ b/src/runtime/pinner.go @@ -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)) { diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go index 4b6821b1fb..49cf13cb64 100644 --- a/src/runtime/plugin.go +++ b/src/runtime/plugin.go @@ -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 diff --git a/src/runtime/race.go b/src/runtime/race.go index 7e7bca76ac..2cd4e3a9a2 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -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. diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 93392896cb..0f74ebbe24 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -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. diff --git a/src/runtime/type.go b/src/runtime/type.go index c11c866cd8..baaaeafc4a 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -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 index 4920a7cf14..0000000000 --- a/src/runtime/typekind.go +++ /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 -} -- 2.51.0