diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 0ae00575fc..a4a701c9a2 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -415,14 +415,6 @@ var kinds = []abi.Kind{ types.TUNSAFEPTR: abi.UnsafePointer, } -var elemKinds = []abi.Kind{ - abi.Array, - abi.Chan, - abi.Map, - abi.Pointer, - abi.Slice, -} - var ( memhashvarlen *obj.LSym memequalvarlen *obj.LSym @@ -481,14 +473,6 @@ func dcommontype(c rttype.Cursor, t *types.Type) { tflag |= abi.TFlagGCMaskOnDemand } - kind := kinds[t.Kind()] - if slices.Contains(elemKinds, kind) { - tflag |= abi.TFlagHasElem - if kind == abi.Map { - tflag |= abi.TFlagHasElemSecond - } - } - exported := false p := t.NameString() // If we're writing out type T, @@ -526,6 +510,7 @@ func dcommontype(c rttype.Cursor, t *types.Type) { c.Field("Align_").WriteUint8(uint8(t.Alignment())) c.Field("FieldAlign_").WriteUint8(uint8(t.Alignment())) + kind := kinds[t.Kind()] if types.IsDirectIface(t) { kind |= abi.KindDirectIface } diff --git a/src/internal/abi/type.go b/src/internal/abi/type.go index e6f4627834..4671b0da28 100644 --- a/src/internal/abi/type.go +++ b/src/internal/abi/type.go @@ -5,7 +5,6 @@ package abi import ( - "internal/goarch" "unsafe" ) @@ -126,12 +125,6 @@ const ( // has type **byte instead of *byte. The runtime will store a // pointer to the GC pointer bitmask in *GCData. TFlagGCMaskOnDemand TFlag = 1 << 4 - - // TFlagHasElem signals that the Type has an Elem. - TFlagHasElem TFlag = 1 << 5 - - // TFlagHasElem signals that the Type has an Elem, but at an PtrBytes higher offset. - TFlagHasElemSecond TFlag = 1 << 6 ) // NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime. @@ -383,25 +376,24 @@ func (t *Type) Uncommon() *UncommonType { } } -// Compile time asserts for (*Type).Elem(). -func _() { - const _, _ = unsafe.Offsetof(ChanType{}.Elem) - baseElemOffset, baseElemOffset - unsafe.Offsetof(ChanType{}.Elem) - const _, _ = unsafe.Offsetof(mapType{}.Elem) - baseElemOffset + goarch.PtrSize, baseElemOffset + goarch.PtrSize - unsafe.Offsetof(mapType{}.Elem) - const _, _ = unsafe.Offsetof(PtrType{}.Elem) - baseElemOffset, baseElemOffset - unsafe.Offsetof(PtrType{}.Elem) - const _, _ = unsafe.Offsetof(SliceType{}.Elem) - baseElemOffset, baseElemOffset - unsafe.Offsetof(SliceType{}.Elem) - var _, _, _, _, _ *Type = ArrayType{}.Elem, ChanType{}.Elem, mapType{}.Elem, PtrType{}.Elem, SliceType{}.Elem -} - -const baseElemOffset = unsafe.Offsetof(ArrayType{}.Elem) - // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil. func (t *Type) Elem() *Type { - if t.TFlag&TFlagHasElem != 0 { - // Unfortunately, the mapType does not have the Elem field at the same offset as other - // types do, it is PtrBytes ahead. So we have to calculate the offset based on TFlagHasElemSecond flag. - // Currently we can't really change the definition of mapType to reorder these fields, - // because mapType is referenced with linknames from other modules (non-std). - return *(**Type)(unsafe.Add(unsafe.Pointer(t), baseElemOffset+(goarch.PtrSize*uintptr((t.TFlag&TFlagHasElemSecond)>>6)))) + switch t.Kind() { + case Array: + tt := (*ArrayType)(unsafe.Pointer(t)) + return tt.Elem + case Chan: + tt := (*ChanType)(unsafe.Pointer(t)) + return tt.Elem + case Map: + tt := (*mapType)(unsafe.Pointer(t)) + return tt.Elem + case Pointer: + tt := (*PtrType)(unsafe.Pointer(t)) + return tt.Elem + case Slice: + tt := (*SliceType)(unsafe.Pointer(t)) + return tt.Elem } return nil } diff --git a/src/reflect/map_noswiss.go b/src/reflect/map_noswiss.go index a7cd2cba30..19696a4f4b 100644 --- a/src/reflect/map_noswiss.go +++ b/src/reflect/map_noswiss.go @@ -69,7 +69,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 = abi.TFlagHasElem | abi.TFlagHasElemSecond + mt.TFlag = 0 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/map_swiss.go b/src/reflect/map_swiss.go index c9f01dd941..2eac51e57d 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 = abi.TFlagHasElem | abi.TFlagHasElemSecond + mt.TFlag = 0 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 ce81bd8abb..e5ee7f90d0 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1361,7 +1361,6 @@ func (t *rtype) ptrTo() *abi.Type { pp.Str = resolveReflectName(newName(s, "", false, false)) pp.PtrToThis = 0 - pp.TFlag = abi.TFlagHasElem // For the type structures linked into the binary, the // compiler provides a good hash of the string. @@ -2086,7 +2085,7 @@ func SliceOf(t Type) Type { var islice any = ([]unsafe.Pointer)(nil) prototype := *(**sliceType)(unsafe.Pointer(&islice)) slice := *prototype - slice.TFlag = abi.TFlagHasElem + slice.TFlag = 0 slice.Str = resolveReflectName(newName(s, "", false, false)) slice.Hash = fnv1(typ.Hash, '[') slice.Elem = typ @@ -2472,9 +2471,9 @@ func StructOf(fields []StructField) Type { typ.Str = resolveReflectName(newName(str, "", false, false)) if isRegularMemory(toType(&typ.Type)) { - typ.TFlag = abi.TFlagRegularMemory & abi.TFlagHasElem + typ.TFlag = abi.TFlagRegularMemory } else { - typ.TFlag = abi.TFlagHasElem + typ.TFlag = 0 } typ.Hash = hash typ.Size_ = size @@ -2612,7 +2611,7 @@ func ArrayOf(length int, elem Type) Type { var iarray any = [1]unsafe.Pointer{} prototype := *(**arrayType)(unsafe.Pointer(&iarray)) array := *prototype - array.TFlag = (typ.TFlag & abi.TFlagRegularMemory) | abi.TFlagHasElem + array.TFlag = typ.TFlag & abi.TFlagRegularMemory array.Str = resolveReflectName(newName(s, "", false, false)) array.Hash = fnv1(typ.Hash, '[') for n := uint32(length); n > 0; n >>= 8 { diff --git a/src/reflect/type_test.go b/src/reflect/type_test.go index 7c43d89b46..51abc0776c 100644 --- a/src/reflect/type_test.go +++ b/src/reflect/type_test.go @@ -118,13 +118,6 @@ func BenchmarkTypeForError(b *testing.B) { } } -func BenchmarkSliceTypeElem(b *testing.B) { - slice := reflect.TypeFor[[]int]() - for i := 0; i < b.N; i++ { - sinkType = slice.Elem() - } -} - func TestType_CanSeq(t *testing.T) { tests := []struct { name string