diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 8a2b15a..c3f041e 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -756,7 +756,7 @@
// | 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 243b787..e420ce2 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 @@
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 @@
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 @@
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 893c7940..215ffa9 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -527,67 +527,10 @@
// 0x20 does not make sense.
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 {