]> Cypherpunks repositories - gostls13.git/commitdiff
internal/abi, runtime: put type descriptor sizes in internal/abi
authorIan Lance Taylor <iant@golang.org>
Wed, 3 Dec 2025 05:13:19 +0000 (21:13 -0800)
committerGopher Robot <gobot@golang.org>
Sat, 7 Feb 2026 23:09:43 +0000 (15:09 -0800)
Change-Id: I4ecfda9f85b00a228e8cf51d7ff4457ef7f83ce5
Reviewed-on: https://go-review.googlesource.com/c/go/+/726160
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/reflectdata/reflect.go
src/internal/abi/type.go
src/runtime/type.go

index 8a2b15ab24c94ee876fd9cfb6ebe097fbbf7b68e..c3f041ec572910f5b2052ea0e6c07fc17c09b9ad 100644 (file)
@@ -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.
index 243b787cfcee9497bc38c7d9ef0a3ee1e0862ef7..689394daba4b6ba8c02a58e4b849d58fdd182463 100644 (file)
@@ -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
index 82ac5120bb6632f09f066a1feb311b5132516b11..a8205c2404ec35708a80a5b63789e28c8de905c6 100644 (file)
@@ -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 {