package runtime
import (
)
type nameOff = abi.NameOff
type typeOff = abi.TypeOff
type textOff = abi.TextOff
type _type = abi.Type
type rtype struct {
*abi.Type
}
func ( rtype) () string {
:= .nameOff(.Str).Name()
if .TFlag&abi.TFlagExtraStar != 0 {
return [1:]
}
return
}
func ( rtype) () *uncommontype {
return .Uncommon()
}
func ( rtype) () string {
if .TFlag&abi.TFlagNamed == 0 {
return ""
}
:= .string()
:= len() - 1
:= 0
for >= 0 && ([] != '.' || != 0) {
switch [] {
case ']':
++
case '[':
--
}
--
}
return [+1:]
}
func ( rtype) () string {
if := .uncommon(); != nil {
return .nameOff(.PkgPath).Name()
}
switch .Kind_ & abi.KindMask {
case abi.Struct:
:= (*structtype)(unsafe.Pointer(.Type))
return .PkgPath.Name()
case abi.Interface:
:= (*interfacetype)(unsafe.Pointer(.Type))
return .PkgPath.Name()
}
return ""
}
func ( *_type) *byte {
if .TFlag&abi.TFlagGCMaskOnDemand != 0 {
return getGCMaskOnDemand()
}
return .GCData
}
var inProgress byte
func ( *_type) *byte {
:= unsafe.Pointer(.GCData)
if GOOS == "aix" {
= add(, firstmoduledata.data-aixStaticDataBase)
}
for {
:= (*byte)(atomic.Loadp())
switch {
default:
return
case &inProgress:
osyield()
continue
case nil:
if !atomic.Casp1((*unsafe.Pointer)(), nil, unsafe.Pointer(&inProgress)) {
continue
}
:= goarch.PtrSize * divRoundUp(.PtrBytes/goarch.PtrSize, 8*goarch.PtrSize)
= (*byte)(persistentalloc(, goarch.PtrSize, &memstats.other_sys))
systemstack(func() {
buildGCMask(, bitCursor{ptr: , n: 0})
})
atomic.StorepNoWB(, unsafe.Pointer())
return
}
}
}
type bitCursor struct {
ptr *byte
n uintptr
}
func ( bitCursor) ( *byte, uintptr) {
:= addb(.ptr, .n/8)
:= .n % 8
:= uintptr(*) & (1<< - 1)
for > 8 {
|= uintptr(*) <<
+= 8
= addb(, 1)
-= 8
* = byte()
>>= 8
-= 8
= addb(, 1)
}
|= (uintptr(*) & (1<< - 1)) <<
+=
if > 8 {
* = byte()
>>= 8
-= 8
= addb(, 1)
}
* &^= 1<< - 1
* |= byte()
}
func ( bitCursor) ( uintptr) bitCursor {
return bitCursor{ptr: .ptr, n: .n + }
}
func ( *_type, bitCursor) {
:
if .PtrBytes == 0 {
throw("pointerless type")
}
if .TFlag&abi.TFlagGCMaskOnDemand == 0 {
.write(.GCData, .PtrBytes/goarch.PtrSize)
return
}
switch .Kind() {
case abi.Array:
:= .ArrayType()
if .Len == 1 {
= .Elem
goto
}
:= .Elem
for := uintptr(0); < .Len; ++ {
(, )
= .offset(.Size_ / goarch.PtrSize)
}
case abi.Struct:
:= .StructType()
var abi.StructField
for , := range .Fields {
:= .Typ
if !.Pointers() {
continue
}
if .Size_ > .Size_/2 {
=
continue
}
(, .offset(.Offset/goarch.PtrSize))
}
if .Typ != nil {
= .Typ
= .offset(.Offset / goarch.PtrSize)
goto
}
default:
throw("unexpected kind")
}
}
var reflectOffs struct {
lock mutex
next int32
m map[int32]unsafe.Pointer
minv map[unsafe.Pointer]int32
}
func () {
lock(&reflectOffs.lock)
if raceenabled {
raceacquire(unsafe.Pointer(&reflectOffs.lock))
}
}
func () {
if raceenabled {
racerelease(unsafe.Pointer(&reflectOffs.lock))
}
unlock(&reflectOffs.lock)
}
func ( unsafe.Pointer, nameOff) name {
if == 0 {
return name{}
}
:= uintptr()
for := &firstmoduledata; != nil; = .next {
if >= .types && < .etypes {
:= .types + uintptr()
if > .etypes {
println("runtime: nameOff", hex(), "out of range", hex(.types), "-", hex(.etypes))
throw("runtime: name offset out of range")
}
return name{Bytes: (*byte)(unsafe.Pointer())}
}
}
reflectOffsLock()
, := reflectOffs.m[int32()]
reflectOffsUnlock()
if ! {
println("runtime: nameOff", hex(), "base", hex(), "not in ranges:")
for := &firstmoduledata; != nil; = .next {
println("\ttypes", hex(.types), "etypes", hex(.etypes))
}
throw("runtime: name offset base pointer out of range")
}
return name{Bytes: (*byte)()}
}
func ( rtype) ( nameOff) name {
return resolveNameOff(unsafe.Pointer(.Type), )
}
func ( unsafe.Pointer, typeOff) *_type {
if == 0 || == -1 {
return nil
}
:= uintptr()
var *moduledata
for := &firstmoduledata; != nil; = .next {
if >= .types && < .etypes {
=
break
}
}
if == nil {
reflectOffsLock()
:= reflectOffs.m[int32()]
reflectOffsUnlock()
if == nil {
println("runtime: typeOff", hex(), "base", hex(), "not in ranges:")
for := &firstmoduledata; != nil; = .next {
println("\ttypes", hex(.types), "etypes", hex(.etypes))
}
throw("runtime: type offset base pointer out of range")
}
return (*_type)()
}
if := .typemap[]; != nil {
return
}
:= .types + uintptr()
if > .etypes {
println("runtime: typeOff", hex(), "out of range", hex(.types), "-", hex(.etypes))
throw("runtime: type offset out of range")
}
return (*_type)(unsafe.Pointer())
}
func ( rtype) ( typeOff) *_type {
return resolveTypeOff(unsafe.Pointer(.Type), )
}
func ( rtype) ( textOff) unsafe.Pointer {
if == -1 {
return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod))
}
:= uintptr(unsafe.Pointer(.Type))
var *moduledata
for := &firstmoduledata; != nil; = .next {
if >= .types && < .etypes {
=
break
}
}
if == nil {
reflectOffsLock()
:= reflectOffs.m[int32()]
reflectOffsUnlock()
if == nil {
println("runtime: textOff", hex(), "base", hex(), "not in ranges:")
for := &firstmoduledata; != nil; = .next {
println("\ttypes", hex(.types), "etypes", hex(.etypes))
}
throw("runtime: text offset base pointer out of range")
}
return
}
:= .textAddr(uint32())
return unsafe.Pointer()
}
type uncommontype = abi.UncommonType
type interfacetype = abi.InterfaceType
type arraytype = abi.ArrayType
type chantype = abi.ChanType
type slicetype = abi.SliceType
type functype = abi.FuncType
type ptrtype = abi.PtrType
type name = abi.Name
type structtype = abi.StructType
func ( name) string {
if .Bytes == nil || *.Data(0)&(1<<2) == 0 {
return ""
}
, := .ReadVarint(1)
:= 1 + +
if *.Data(0)&(1<<1) != 0 {
, := .ReadVarint()
+= +
}
var nameOff
copy((*[4]byte)(unsafe.Pointer(&))[:], (*[4]byte)(unsafe.Pointer(.Data()))[:])
:= resolveNameOff(unsafe.Pointer(.Bytes), )
return .Name()
}
func () {
if firstmoduledata.next == nil {
return
}
:= make(map[uint32][]*_type, len(firstmoduledata.typelinks))
:= activeModules()
:= [0]
for , := range [1:] {
:
for , := range .typelinks {
var *_type
if .typemap == nil {
= (*_type)(unsafe.Pointer(.types + uintptr()))
} else {
= .typemap[typeOff()]
}
:= [.Hash]
for , := range {
if == {
continue
}
}
[.Hash] = append(, )
}
if .typemap == nil {
:= make(map[typeOff]*_type, len(.typelinks))
pinnedTypemaps = append(pinnedTypemaps, )
.typemap =
for , := range .typelinks {
:= (*_type)(unsafe.Pointer(.types + uintptr()))
for , := range [.Hash] {
:= map[_typePair]struct{}{}
if typesEqual(, , ) {
=
break
}
}
.typemap[typeOff()] =
}
}
=
}
}
type _typePair struct {
t1 *_type
t2 *_type
}
func ( *abi.Type) rtype {
return rtype{}
}
func (, *_type, map[_typePair]struct{}) bool {
:= _typePair{, }
if , := []; {
return true
}
[] = struct{}{}
if == {
return true
}
:= .Kind_ & abi.KindMask
if != .Kind_&abi.KindMask {
return false
}
, := toRType(), toRType()
if .string() != .string() {
return false
}
:= .Uncommon()
:= .Uncommon()
if != nil || != nil {
if == nil || == nil {
return false
}
:= .nameOff(.PkgPath).Name()
:= .nameOff(.PkgPath).Name()
if != {
return false
}
}
if abi.Bool <= && <= abi.Complex128 {
return true
}
switch {
case abi.String, abi.UnsafePointer:
return true
case abi.Array:
:= (*arraytype)(unsafe.Pointer())
:= (*arraytype)(unsafe.Pointer())
return (.Elem, .Elem, ) && .Len == .Len
case abi.Chan:
:= (*chantype)(unsafe.Pointer())
:= (*chantype)(unsafe.Pointer())
return .Dir == .Dir && (.Elem, .Elem, )
case abi.Func:
:= (*functype)(unsafe.Pointer())
:= (*functype)(unsafe.Pointer())
if .OutCount != .OutCount || .InCount != .InCount {
return false
}
, := .InSlice(), .InSlice()
for := 0; < len(); ++ {
if !([], [], ) {
return false
}
}
, := .OutSlice(), .OutSlice()
for := 0; < len(); ++ {
if !([], [], ) {
return false
}
}
return true
case abi.Interface:
:= (*interfacetype)(unsafe.Pointer())
:= (*interfacetype)(unsafe.Pointer())
if .PkgPath.Name() != .PkgPath.Name() {
return false
}
if len(.Methods) != len(.Methods) {
return false
}
for := range .Methods {
:= &.Methods[]
:= &.Methods[]
:= resolveNameOff(unsafe.Pointer(), .Name)
:= resolveNameOff(unsafe.Pointer(), .Name)
if .Name() != .Name() {
return false
}
if pkgPath() != pkgPath() {
return false
}
:= resolveTypeOff(unsafe.Pointer(), .Typ)
:= resolveTypeOff(unsafe.Pointer(), .Typ)
if !(, , ) {
return false
}
}
return true
case abi.Map:
if goexperiment.SwissMap {
:= (*abi.SwissMapType)(unsafe.Pointer())
:= (*abi.SwissMapType)(unsafe.Pointer())
return (.Key, .Key, ) && (.Elem, .Elem, )
}
:= (*abi.OldMapType)(unsafe.Pointer())
:= (*abi.OldMapType)(unsafe.Pointer())
return (.Key, .Key, ) && (.Elem, .Elem, )
case abi.Pointer:
:= (*ptrtype)(unsafe.Pointer())
:= (*ptrtype)(unsafe.Pointer())
return (.Elem, .Elem, )
case abi.Slice:
:= (*slicetype)(unsafe.Pointer())
:= (*slicetype)(unsafe.Pointer())
return (.Elem, .Elem, )
case abi.Struct:
:= (*structtype)(unsafe.Pointer())
:= (*structtype)(unsafe.Pointer())
if len(.Fields) != len(.Fields) {
return false
}
if .PkgPath.Name() != .PkgPath.Name() {
return false
}
for := range .Fields {
:= &.Fields[]
:= &.Fields[]
if .Name.Name() != .Name.Name() {
return false
}
if !(.Typ, .Typ, ) {
return false
}
if .Name.Tag() != .Name.Tag() {
return false
}
if .Offset != .Offset {
return false
}
if .Name.IsEmbedded() != .Name.IsEmbedded() {
return false
}
}
return true
default:
println("runtime: impossible type kind", )
throw("runtime: impossible type kind")
return false
}
}