From: Ian Lance Taylor Date: Wed, 3 Dec 2025 05:13:19 +0000 (-0800) Subject: internal/abi, runtime: put type descriptor sizes in internal/abi X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d440b8b48560d29995d299973e6c79bd11fb90e9;p=gostls13.git internal/abi, runtime: put type descriptor sizes in internal/abi Change-Id: I4ecfda9f85b00a228e8cf51d7ff4457ef7f83ce5 Reviewed-on: https://go-review.googlesource.com/c/go/+/726160 Reviewed-by: Keith Randall Reviewed-by: Dmitri Shuralyov Reviewed-by: Keith Randall Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8a2b15ab24..c3f041ec57 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -756,7 +756,7 @@ func writeType(t *types.Type) *obj.LSym { // | method list, if any | dextratype // +--------------------------------+ - E - // runtime.moduleTypelinks is aware of this type layout, + // internal/abi.Type.DescriptorSize is aware of this type layout, // and must be changed if the layout change. // UncommonType section is included if we have a name or a method. diff --git a/src/internal/abi/type.go b/src/internal/abi/type.go index 243b787cfc..689394daba 100644 --- a/src/internal/abi/type.go +++ b/src/internal/abi/type.go @@ -5,6 +5,7 @@ package abi import ( + "internal/goarch" "unsafe" ) @@ -412,6 +413,22 @@ func (t *Type) MapType() *MapType { return (*MapType)(unsafe.Pointer(t)) } +// PointerType returns t cast to a *PtrType, or nil if its tag does not match. +func (t *Type) PointerType() *PtrType { + if t.Kind() != Pointer { + return nil + } + return (*PtrType)(unsafe.Pointer(t)) +} + +// SliceType returns t cast to a *SliceType, or nil if its tag does not match. +func (t *Type) SliceType() *SliceType { + if t.Kind() != Slice { + return nil + } + return (*SliceType)(unsafe.Pointer(t)) +} + // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match. func (t *Type) ArrayType() *ArrayType { if t.Kind() != Array { @@ -420,6 +437,14 @@ func (t *Type) ArrayType() *ArrayType { return (*ArrayType)(unsafe.Pointer(t)) } +// ChanType returns t cast to a *ChanType, or nil if its tag does not match. +func (t *Type) ChanType() *ChanType { + if t.Kind() != Chan { + return nil + } + return (*ChanType)(unsafe.Pointer(t)) +} + // FuncType returns t cast to a *FuncType, or nil if its tag does not match. func (t *Type) FuncType() *FuncType { if t.Kind() != Func { @@ -712,6 +737,105 @@ func NewName(n, tag string, exported, embedded bool) Name { return Name{Bytes: &b[0]} } +// DescriptorSize returns the contiguous size taken in memory by the +// type descriptor. This is the size of the Type struct, +// plus other fields used by some type kinds, plus the UncommonType +// struct if present, plus other optional information. +// This is just the size of the bytes that appear contiguously in memory. +// It does not include the size of things like type strings +// and field names that appear elsewhere. +// +// This code must match the data structures build by +// cmd/compile/internal/reflectdata/reflect.go:writeType. +func (t *Type) DescriptorSize() int { + var baseSize, addSize int + switch t.Kind_ { + case Array: + baseSize, addSize = t.ArrayType().descriptorSizes() + case Chan: + baseSize, addSize = t.ChanType().descriptorSizes() + case Func: + baseSize, addSize = t.FuncType().descriptorSizes() + case Interface: + baseSize, addSize = t.InterfaceType().descriptorSizes() + case Map: + baseSize, addSize = t.MapType().descriptorSizes() + case Pointer: + baseSize, addSize = t.PointerType().descriptorSizes() + case Slice: + baseSize, addSize = t.SliceType().descriptorSizes() + case Struct: + baseSize, addSize = t.StructType().descriptorSizes() + case Bool, + Int, Int8, Int16, Int32, Int64, + Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, + Float32, Float64, Complex64, Complex128, + String, UnsafePointer: + + baseSize = int(unsafe.Sizeof(*t)) + addSize = 0 + + default: + panic("DescriptorSize: invalid type descriptor") + } + + // For clarity, we add the sizes together in the order + // they appear in memory. + + ret := baseSize + + mcount := 0 + ut := t.Uncommon() + if ut != nil { + ret += int(unsafe.Sizeof(*ut)) + mcount = int(ut.Mcount) + } + + ret += addSize + + ret += mcount * int(unsafe.Sizeof(Method{})) + + return ret +} + +func (at *ArrayType) descriptorSizes() (base, add int) { + return int(unsafe.Sizeof(*at)), 0 +} + +func (ct *ChanType) descriptorSizes() (base, add int) { + return int(unsafe.Sizeof(*ct)), 0 +} + +func (ft *FuncType) descriptorSizes() (base, add int) { + base = int(unsafe.Sizeof(*ft)) + add = (ft.NumIn() + ft.NumOut()) * goarch.PtrSize + return base, add +} + +func (it *InterfaceType) descriptorSizes() (base, add int) { + base = int(unsafe.Sizeof(*it)) + add = len(it.Methods) * int(unsafe.Sizeof(Imethod{})) + return base, add +} + +func (mt *MapType) descriptorSizes() (base, add int) { + return int(unsafe.Sizeof(*mt)), 0 +} + +func (pt *PtrType) descriptorSizes() (base, add int) { + return int(unsafe.Sizeof(*pt)), 0 +} + +func (st *SliceType) descriptorSizes() (base, add int) { + return int(unsafe.Sizeof(*st)), 0 +} + +func (st *StructType) descriptorSizes() (base, add int) { + base = int(unsafe.Sizeof(*st)) + add = len(st.Fields) * int(unsafe.Sizeof(StructField{})) + return base, add +} + const ( TraceArgsLimit = 10 // print no more than 10 args/components TraceArgsMaxDepth = 5 // no more than 5 layers of nesting diff --git a/src/runtime/type.go b/src/runtime/type.go index 82ac5120bb..a8205c2404 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -540,67 +540,10 @@ func moduleTypelinks(md *moduledata) []*_type { td = alignUp(td, 0x20) } - // This code must match the data structures built by - // cmd/compile/internal/reflectdata/reflect.go:writeType. - typ := (*_type)(unsafe.Pointer(td)) - ret = append(ret, typ) - var typSize, add uintptr - switch typ.Kind_ { - case abi.Array: - typSize = unsafe.Sizeof(abi.ArrayType{}) - case abi.Chan: - typSize = unsafe.Sizeof(abi.ChanType{}) - case abi.Func: - typSize = unsafe.Sizeof(abi.FuncType{}) - ft := (*abi.FuncType)(unsafe.Pointer(typ)) - add = uintptr(ft.NumIn()+ft.NumOut()) * goarch.PtrSize - case abi.Interface: - typSize = unsafe.Sizeof(abi.InterfaceType{}) - it := (*abi.InterfaceType)(unsafe.Pointer(typ)) - add = uintptr(len(it.Methods)) * unsafe.Sizeof(abi.Imethod{}) - case abi.Map: - typSize = unsafe.Sizeof(abi.MapType{}) - case abi.Pointer: - typSize = unsafe.Sizeof(abi.PtrType{}) - case abi.Slice: - typSize = unsafe.Sizeof(abi.SliceType{}) - case abi.Struct: - typSize = unsafe.Sizeof(abi.StructType{}) - st := (*abi.StructType)(unsafe.Pointer(typ)) - add = uintptr(len(st.Fields)) * unsafe.Sizeof(abi.StructField{}) - - case abi.Bool, - abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Int64, - abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uint64, abi.Uintptr, - abi.Float32, abi.Float64, - abi.Complex64, abi.Complex128, - abi.String, - abi.UnsafePointer: - - typSize = unsafe.Sizeof(_type{}) - - default: - println("type descriptor at", hex(td), "is kind", typ.Kind_) - throw("invalid type descriptor") - } - - td += typSize - - mcount := uintptr(0) - if typ.TFlag&abi.TFlagUncommon != 0 { - ut := (*abi.UncommonType)(unsafe.Pointer(td)) - mcount = uintptr(ut.Mcount) - td += unsafe.Sizeof(abi.UncommonType{}) - } - - td += add - - if mcount > 0 { - td += mcount * unsafe.Sizeof(abi.Method{}) - } + td += uintptr(typ.DescriptorSize()) } if moduleToTypelinks == nil {