Source File
type.go
Belonging Package
reflect
package reflect
import (
)
Align() int
FieldAlign() int
NumMethod() int
Name() string
PkgPath() string
Size() uintptr
String() string
Kind() Kind
Comparable() bool
Bits() int
ChanDir() ChanDir
IsVariadic() bool
Elem() Type
Field(i int) StructField
FieldByIndex(index []int) StructField
FieldByName(name string) (StructField, bool)
FieldByNameFunc(match func(string) bool) (StructField, bool)
Key() Type
Len() int
NumField() int
NumIn() int
NumOut() int
Out(i int) Type
common() *rtype
uncommon() *uncommonType
}
tflagUncommon tflag = 1 << 0
tflagExtraStar tflag = 1 << 1
tflagNamed tflag = 1 << 2
tflagRegularMemory tflag = 1 << 3
)
type rtype struct {
size uintptr
ptrdata uintptr // number of bytes in the type that can contain pointers
hash uint32 // hash of type; avoids computation in hash tables
tflag tflag // extra type information flags
align uint8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type
type structField struct {
name name // name is always non-empty
typ *rtype // type of field
offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
}
func ( *structField) () uintptr {
return .offsetEmbed >> 1
}
func ( *structField) () bool {
return .offsetEmbed&1 != 0
}
type structType struct {
rtype
pkgPath name
fields []structField // sorted by offset
}
type name struct {
bytes *byte
}
func ( name) ( int, string) *byte {
return (*byte)(add(unsafe.Pointer(.bytes), uintptr(), ))
}
func ( name) () bool {
return (*.bytes)&(1<<0) != 0
}
func ( name) () int {
return int(uint16(*.data(1, "name len field"))<<8 | uint16(*.data(2, "name len field")))
}
func ( name) () int {
if *.data(0, "name flag field")&(1<<1) == 0 {
return 0
}
:= 3 + .nameLen()
return int(uint16(*.data(, "name taglen field"))<<8 | uint16(*.data(+1, "name taglen field")))
}
func ( name) () ( string) {
if .bytes == nil {
return
}
:= (*[4]byte)(unsafe.Pointer(.bytes))
:= (*unsafeheader.String)(unsafe.Pointer(&))
.Data = unsafe.Pointer(&[3])
.Len = int([1])<<8 | int([2])
return
}
func ( name) () ( string) {
:= .tagLen()
if == 0 {
return ""
}
:= .nameLen()
:= (*unsafeheader.String)(unsafe.Pointer(&))
.Data = unsafe.Pointer(.data(3++2, "non-empty string"))
.Len =
return
}
func ( name) () string {
if .bytes == nil || *.data(0, "name flag field")&(1<<2) == 0 {
return ""
}
:= 3 + .nameLen()
if := .tagLen(); > 0 {
+= 2 +
}
copy((*[4]byte)(unsafe.Pointer(&))[:], (*[4]byte)(unsafe.Pointer(.data(, "name offset field")))[:])
:= name{(*byte)(resolveTypeOff(unsafe.Pointer(.bytes), ))}
return .name()
}
func (, string, bool) name {
if len() > 1<<16-1 {
panic("reflect.nameFrom: name too long: " + )
}
if len() > 1<<16-1 {
panic("reflect.nameFrom: tag too long: " + )
}
var byte
:= 1 + 2 + len()
if {
|= 1 << 0
}
if len() > 0 {
+= 2 + len()
|= 1 << 1
}
:= make([]byte, )
[0] =
[1] = uint8(len() >> 8)
[2] = uint8(len())
copy([3:], )
if len() > 0 {
:= [3+len():]
[0] = uint8(len() >> 8)
[1] = uint8(len())
copy([2:], )
}
return name{bytes: &[0]}
}
func ( Kind) () string {
if int() < len(kindNames) {
return kindNames[]
}
return "kind" + strconv.Itoa(int())
}
var kindNames = []string{
Invalid: "invalid",
Bool: "bool",
Int: "int",
Int8: "int8",
Int16: "int16",
Int32: "int32",
Int64: "int64",
Uint: "uint",
Uint8: "uint8",
Uint16: "uint16",
Uint32: "uint32",
Uint64: "uint64",
Uintptr: "uintptr",
Float32: "float32",
Float64: "float64",
Complex64: "complex64",
Complex128: "complex128",
Array: "array",
Chan: "chan",
Func: "func",
Interface: "interface",
Map: "map",
Ptr: "ptr",
Slice: "slice",
String: "string",
Struct: "struct",
UnsafePointer: "unsafe.Pointer",
}
func ( *uncommonType) () []method {
if .mcount == 0 {
return nil
}
return (*[1 << 16]method)(add(unsafe.Pointer(), uintptr(.moff), "t.mcount > 0"))[:.mcount:.mcount]
}
func ( *uncommonType) () []method {
if .xcount == 0 {
return nil
}
return (*[1 << 16]method)(add(unsafe.Pointer(), uintptr(.moff), "t.xcount > 0"))[:.xcount:.xcount]
}
func ( unsafe.Pointer) textOff {
return textOff(addReflectOff())
}
type nameOff int32 // offset to a name
type typeOff int32 // offset to an *rtype
type textOff int32 // offset from top of text section
func ( *rtype) ( nameOff) name {
return name{(*byte)(resolveNameOff(unsafe.Pointer(), int32()))}
}
func ( *rtype) ( typeOff) *rtype {
return (*rtype)(resolveTypeOff(unsafe.Pointer(), int32()))
}
func ( *rtype) ( textOff) unsafe.Pointer {
return resolveTextOff(unsafe.Pointer(), int32())
}
func ( *rtype) () *uncommonType {
if .tflag&tflagUncommon == 0 {
return nil
}
switch .Kind() {
case Struct:
return &(*structTypeUncommon)(unsafe.Pointer()).u
case Ptr:
type struct {
ptrType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Func:
type struct {
funcType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Slice:
type struct {
sliceType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Array:
type struct {
arrayType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Chan:
type struct {
chanType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Map:
type struct {
mapType
uncommonType
}
return &(*)(unsafe.Pointer()).
case Interface:
type struct {
interfaceType
uncommonType
}
return &(*)(unsafe.Pointer()).
default:
type struct {
rtype
uncommonType
}
return &(*)(unsafe.Pointer()).
}
}
func ( *rtype) () string {
:= .nameOff(.str).name()
if .tflag&tflagExtraStar != 0 {
return [1:]
}
return
}
func ( *rtype) () uintptr { return .size }
func ( *rtype) () int {
if == nil {
panic("reflect: Bits of nil Type")
}
:= .Kind()
if < Int || > Complex128 {
panic("reflect: Bits of non-arithmetic Type " + .String())
}
return int(.size) * 8
}
func ( *rtype) () int { return int(.align) }
func ( *rtype) () int { return int(.fieldAlign) }
func ( *rtype) () Kind { return Kind(.kind & kindMask) }
func ( *rtype) () bool { return .ptrdata != 0 }
func ( *rtype) () *rtype { return }
func ( *rtype) () []method {
:= .uncommon()
if == nil {
return nil
}
return .exportedMethods()
}
func ( *rtype) () int {
if .Kind() == Interface {
:= (*interfaceType)(unsafe.Pointer())
return .NumMethod()
}
return len(.exportedMethods())
}
func ( *rtype) ( int) ( Method) {
if .Kind() == Interface {
:= (*interfaceType)(unsafe.Pointer())
return .Method()
}
:= .exportedMethods()
if < 0 || >= len() {
panic("reflect: Method index out of range")
}
:= []
:= .nameOff(.name)
.Name = .name()
:= flag(Func)
:= .typeOff(.mtyp)
:= (*funcType)(unsafe.Pointer())
:= make([]Type, 0, 1+len(.in()))
= append(, )
for , := range .in() {
= append(, )
}
:= make([]Type, 0, len(.out()))
for , := range .out() {
= append(, )
}
:= FuncOf(, , .IsVariadic())
.Type =
:= .textOff(.tfn)
:= unsafe.Pointer(&)
.Func = Value{.(*rtype), , }
.Index =
return
}
func ( *rtype) ( string) ( Method, bool) {
if .Kind() == Interface {
:= (*interfaceType)(unsafe.Pointer())
return .MethodByName()
}
:= .uncommon()
if == nil {
return Method{}, false
for , := range .exportedMethods() {
if .nameOff(.name).name() == {
return .Method(), true
}
}
return Method{}, false
}
func ( *rtype) () string {
if .tflag&tflagNamed == 0 {
return ""
}
:= .uncommon()
if == nil {
return ""
}
return .nameOff(.pkgPath).name()
}
func ( *rtype) () bool {
return .tflag&tflagNamed != 0
}
func ( *rtype) () string {
if !.hasName() {
return ""
}
:= .String()
:= len() - 1
for >= 0 && [] != '.' {
--
}
return [+1:]
}
func ( *rtype) () ChanDir {
if .Kind() != Chan {
panic("reflect: ChanDir of non-chan type " + .String())
}
:= (*chanType)(unsafe.Pointer())
return ChanDir(.dir)
}
func ( *rtype) () bool {
if .Kind() != Func {
panic("reflect: IsVariadic of non-func type " + .String())
}
:= (*funcType)(unsafe.Pointer())
return .outCount&(1<<15) != 0
}
func ( *rtype) () Type {
switch .Kind() {
case Array:
:= (*arrayType)(unsafe.Pointer())
return toType(.elem)
case Chan:
:= (*chanType)(unsafe.Pointer())
return toType(.elem)
case Map:
:= (*mapType)(unsafe.Pointer())
return toType(.elem)
case Ptr:
:= (*ptrType)(unsafe.Pointer())
return toType(.elem)
case Slice:
:= (*sliceType)(unsafe.Pointer())
return toType(.elem)
}
panic("reflect: Elem of invalid type " + .String())
}
func ( *rtype) ( int) StructField {
if .Kind() != Struct {
panic("reflect: Field of non-struct type " + .String())
}
:= (*structType)(unsafe.Pointer())
return .Field()
}
func ( *rtype) ( []int) StructField {
if .Kind() != Struct {
panic("reflect: FieldByIndex of non-struct type " + .String())
}
:= (*structType)(unsafe.Pointer())
return .FieldByIndex()
}
func ( *rtype) ( string) (StructField, bool) {
if .Kind() != Struct {
panic("reflect: FieldByName of non-struct type " + .String())
}
:= (*structType)(unsafe.Pointer())
return .FieldByName()
}
func ( *rtype) ( func(string) bool) (StructField, bool) {
if .Kind() != Struct {
panic("reflect: FieldByNameFunc of non-struct type " + .String())
}
:= (*structType)(unsafe.Pointer())
return .FieldByNameFunc()
}
func ( *rtype) ( int) Type {
if .Kind() != Func {
panic("reflect: In of non-func type " + .String())
}
:= (*funcType)(unsafe.Pointer())
return toType(.in()[])
}
func ( *rtype) () Type {
if .Kind() != Map {
panic("reflect: Key of non-map type " + .String())
}
:= (*mapType)(unsafe.Pointer())
return toType(.key)
}
func ( *rtype) () int {
if .Kind() != Array {
panic("reflect: Len of non-array type " + .String())
}
:= (*arrayType)(unsafe.Pointer())
return int(.len)
}
func ( *rtype) () int {
if .Kind() != Struct {
panic("reflect: NumField of non-struct type " + .String())
}
:= (*structType)(unsafe.Pointer())
return len(.fields)
}
func ( *rtype) () int {
if .Kind() != Func {
panic("reflect: NumIn of non-func type " + .String())
}
:= (*funcType)(unsafe.Pointer())
return int(.inCount)
}
func ( *rtype) () int {
if .Kind() != Func {
panic("reflect: NumOut of non-func type " + .String())
}
:= (*funcType)(unsafe.Pointer())
return len(.out())
}
func ( *rtype) ( int) Type {
if .Kind() != Func {
panic("reflect: Out of non-func type " + .String())
}
:= (*funcType)(unsafe.Pointer())
return toType(.out()[])
}
func ( *funcType) () []*rtype {
:= unsafe.Sizeof(*)
if .tflag&tflagUncommon != 0 {
+= unsafe.Sizeof(uncommonType{})
}
if .inCount == 0 {
return nil
}
return (*[1 << 20]*rtype)(add(unsafe.Pointer(), , "t.inCount > 0"))[:.inCount:.inCount]
}
func ( *funcType) () []*rtype {
:= unsafe.Sizeof(*)
if .tflag&tflagUncommon != 0 {
+= unsafe.Sizeof(uncommonType{})
}
:= .outCount & (1<<15 - 1)
if == 0 {
return nil
}
return (*[1 << 20]*rtype)(add(unsafe.Pointer(), , "outCount > 0"))[.inCount : .inCount+ : .inCount+]
}
func ( *interfaceType) () int { return len(.methods) }
:= 0
for < len() && [] == ' ' {
++
}
= [:]
if == "" {
break
}
func ( *structType) ( int) ( StructField) {
if < 0 || >= len(.fields) {
panic("reflect: Field index out of bounds")
}
:= &.fields[]
.Type = toType(.typ)
.Name = .name.name()
.Anonymous = .embedded()
if !.name.isExported() {
.PkgPath = .pkgPath.name()
}
if := .name.tag(); != "" {
.Tag = StructTag()
}
.Offset = .offset()
type fieldScan struct {
typ *structType
index []int
}
var map[*structType]int
:= map[*structType]bool{}
for len() > 0 {
, = , [:0]
:=
= nil
for , := range {
:= .typ
if || == nil || .Kind() != Struct {
continue
}
:= (*structType)(unsafe.Pointer())
if [] > 0 {
[] = 2 // exact multiple doesn't matter
continue
}
if == nil {
= map[*structType]int{}
}
[] = 1
if [] > 1 {
[] = 2 // exact multiple doesn't matter
}
var []int
= append(, .index...)
= append(, )
= append(, fieldScan{, })
}
}
if {
break
}
}
return
}
:= "*" + .String()
for , := range typesByString() {
:= (*ptrType)(unsafe.Pointer())
if .elem != {
continue
}
, := ptrMap.LoadOrStore(, )
return &.(*ptrType).rtype
}
func ( uint32, ...byte) uint32 {
for , := range {
= *16777619 ^ uint32()
}
return
}
func ( *rtype) ( Type) bool {
if == nil {
panic("reflect: nil type passed to Type.Implements")
}
if .Kind() != Interface {
panic("reflect: non-interface type passed to Type.Implements")
}
return implements(.(*rtype), )
}
func ( *rtype) ( Type) bool {
if == nil {
panic("reflect: nil type passed to Type.AssignableTo")
}
:= .(*rtype)
return directlyAssignable(, ) || implements(, )
}
func ( *rtype) ( Type) bool {
if == nil {
panic("reflect: nil type passed to Type.ConvertibleTo")
}
:= .(*rtype)
return convertOp(, ) != nil
}
func ( *rtype) () bool {
return .equal != nil
}
if .Kind() == Interface {
:= (*interfaceType)(unsafe.Pointer())
:= 0
for := 0; < len(.methods); ++ {
:= &.methods[]
:= .nameOff(.name)
:= &.methods[]
:= .nameOff(.name)
if .name() == .name() && .typeOff(.typ) == .typeOff(.typ) {
if !.isExported() {
:= .pkgPath()
if == "" {
= .pkgPath.name()
}
:= .pkgPath()
if == "" {
= .pkgPath.name()
}
if != {
continue
}
}
if ++; >= len(.methods) {
return true
}
}
}
return false
}
:= .uncommon()
if == nil {
return false
}
:= 0
:= .methods()
for := 0; < int(.mcount); ++ {
:= &.methods[]
:= .nameOff(.name)
:= []
:= .nameOff(.name)
if .name() == .name() && .typeOff(.mtyp) == .typeOff(.typ) {
if !.isExported() {
:= .pkgPath()
if == "" {
= .pkgPath.name()
}
:= .pkgPath()
if == "" {
= .nameOff(.pkgPath).name()
}
if != {
continue
}
}
if ++; >= len(.methods) {
return true
}
}
}
return false
}
if == {
return true
}
return haveIdenticalUnderlyingType(, , true)
}
func (, Type, bool) bool {
if {
return ==
}
if .Name() != .Name() || .Kind() != .Kind() {
return false
}
return haveIdenticalUnderlyingType(.common(), .common(), false)
}
func (, *rtype, bool) bool {
if == {
return true
}
:= .Kind()
if != .Kind() {
return false
}
if Bool <= && <= Complex128 || == String || == UnsafePointer {
return true
}
switch {
case Array:
return .Len() == .Len() && haveIdenticalType(.Elem(), .Elem(), )
case Chan:
return .ChanDir() == .ChanDir() && haveIdenticalType(.Elem(), .Elem(), )
case Func:
:= (*funcType)(unsafe.Pointer())
:= (*funcType)(unsafe.Pointer())
if .outCount != .outCount || .inCount != .inCount {
return false
}
for := 0; < .NumIn(); ++ {
if !haveIdenticalType(.In(), .In(), ) {
return false
}
}
for := 0; < .NumOut(); ++ {
if !haveIdenticalType(.Out(), .Out(), ) {
return false
}
}
return true
case Interface:
:= (*interfaceType)(unsafe.Pointer())
:= (*interfaceType)(unsafe.Pointer())
if len(.methods) == 0 && len(.methods) == 0 {
return true
return false
case Map:
return haveIdenticalType(.Key(), .Key(), ) && haveIdenticalType(.Elem(), .Elem(), )
case Ptr, Slice:
return haveIdenticalType(.Elem(), .Elem(), )
case 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 !haveIdenticalType(.typ, .typ, ) {
return false
}
if && .name.tag() != .name.tag() {
return false
}
if .offsetEmbed != .offsetEmbed {
return false
}
}
return true
}
return false
}
, := 0, len()
for < {
var lookupCache sync.Map // map[cacheKey]*rtype
var funcLookupCache struct {
sync.Mutex // Guards stores (but not loads) on m.
= "chan (" + + ")"
} else {
= "chan " +
}
}
for , := range typesByString() {
:= (*chanType)(unsafe.Pointer())
if .elem == && .dir == uintptr() {
, := lookupCache.LoadOrStore(, )
return .(Type)
}
}
:= cacheKey{Map, , , 0}
if , := lookupCache.Load(); {
return .(Type)
}
:= "map[" + .String() + "]" + .String()
for , := range typesByString() {
:= (*mapType)(unsafe.Pointer())
if .key == && .elem == {
, := lookupCache.LoadOrStore(, )
return .(Type)
}
}
var interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
:= **(**mapType)(unsafe.Pointer(&))
.str = resolveReflectName(newName(, "", false))
.tflag = 0
.hash = fnv1(.hash, 'm', byte(.hash>>24), byte(.hash>>16), byte(.hash>>8), byte(.hash))
.key =
.elem =
.bucket = bucketOf(, )
.hasher = func( unsafe.Pointer, uintptr) uintptr {
return typehash(, , )
}
.flags = 0
if .size > maxKeySize {
.keysize = uint8(ptrSize)
.flags |= 1 // indirect key
} else {
.keysize = uint8(.size)
}
if .size > maxValSize {
.valuesize = uint8(ptrSize)
.flags |= 2 // indirect value
} else {
.valuesize = uint8(.size)
}
.bucketsize = uint16(.bucket.size)
if isReflexive() {
.flags |= 4
}
if needKeyUpdate() {
.flags |= 8
}
if hashMightPanic() {
.flags |= 16
}
.ptrToThis = 0
, := lookupCache.LoadOrStore(, &.rtype)
return .(Type)
}
type funcTypeFixed4 struct {
funcType
args [4]*rtype
}
type funcTypeFixed8 struct {
funcType
args [8]*rtype
}
type funcTypeFixed16 struct {
funcType
args [16]*rtype
}
type funcTypeFixed32 struct {
funcType
args [32]*rtype
}
type funcTypeFixed64 struct {
funcType
args [64]*rtype
}
type funcTypeFixed128 struct {
funcType
args [128]*rtype
}
var interface{} = (func())(nil)
:= *(**funcType)(unsafe.Pointer(&))
:= len() + len()
var *funcType
var []*rtype
switch {
case <= 4:
:= new(funcTypeFixed4)
= .args[:0:len(.args)]
= &.funcType
case <= 8:
:= new(funcTypeFixed8)
= .args[:0:len(.args)]
= &.funcType
case <= 16:
:= new(funcTypeFixed16)
= .args[:0:len(.args)]
= &.funcType
case <= 32:
:= new(funcTypeFixed32)
= .args[:0:len(.args)]
= &.funcType
case <= 64:
:= new(funcTypeFixed64)
= .args[:0:len(.args)]
= &.funcType
case <= 128:
:= new(funcTypeFixed128)
= .args[:0:len(.args)]
= &.funcType
default:
panic("reflect.FuncOf: too many arguments")
}
* = *
var uint32
for , := range {
:= .(*rtype)
= append(, )
= fnv1(, byte(.hash>>24), byte(.hash>>16), byte(.hash>>8), byte(.hash))
}
if {
= fnv1(, 'v')
}
= fnv1(, '.')
for , := range {
:= .(*rtype)
= append(, )
= fnv1(, byte(.hash>>24), byte(.hash>>16), byte(.hash>>8), byte(.hash))
}
if len() > 50 {
panic("reflect.FuncOf does not support more than 50 arguments")
}
.tflag = 0
.hash =
.inCount = uint16(len())
.outCount = uint16(len())
if {
.outCount |= 1 << 15
}
if , := funcLookupCache.m.Load(); {
for , := range .([]*rtype) {
if haveIdenticalUnderlyingType(&.rtype, , true) {
return
}
}
}
funcLookupCache.Lock()
defer funcLookupCache.Unlock()
if , := funcLookupCache.m.Load(); {
for , := range .([]*rtype) {
if haveIdenticalUnderlyingType(&.rtype, , true) {
return
}
}
}
:= func( *rtype) Type {
var []*rtype
if , := funcLookupCache.m.Load(); {
= .([]*rtype)
}
funcLookupCache.m.Store(, append(, ))
return
}
:= funcStr()
for , := range typesByString() {
if haveIdenticalUnderlyingType(&.rtype, , true) {
return ()
}
}
func ( *funcType) string {
:= make([]byte, 0, 64)
= append(, "func("...)
for , := range .in() {
if > 0 {
= append(, ", "...)
}
if .IsVariadic() && == int(.inCount)-1 {
= append(, "..."...)
= append(, (*sliceType)(unsafe.Pointer()).elem.String()...)
} else {
= append(, .String()...)
}
}
= append(, ')')
:= .out()
if len() == 1 {
= append(, ' ')
} else if len() > 1 {
= append(, " ("...)
}
for , := range {
if > 0 {
= append(, ", "...)
}
= append(, .String()...)
}
if len() > 1 {
= append(, ')')
}
return string()
}
func ( *rtype) bool {
switch .Kind() {
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer:
return true
case Float32, Float64, Complex64, Complex128, Interface:
return false
case Array:
:= (*arrayType)(unsafe.Pointer())
return (.elem)
case Struct:
:= (*structType)(unsafe.Pointer())
for , := range .fields {
if !(.typ) {
return false
}
}
return true
const (
bucketSize uintptr = 8
maxKeySize uintptr = 128
maxValSize uintptr = 128
)
func (, *rtype) *rtype {
if .size > maxKeySize {
= PtrTo().(*rtype)
}
if .size > maxValSize {
= PtrTo().(*rtype)
}
var *byte
var uintptr
var uintptr
:= bucketSize*(1+.size+.size) + + ptrSize
if &uintptr(.align-1) != 0 || &uintptr(.align-1) != 0 {
panic("reflect: bad size computation in MapOf")
}
if .ptrdata != 0 || .ptrdata != 0 {
:= (bucketSize*(1+.size+.size) + ptrSize) / ptrSize
:= make([]byte, (+7)/8)
:= bucketSize / ptrSize
if .ptrdata != 0 {
emitGCMask(, , , bucketSize)
}
+= bucketSize * .size / ptrSize
if .ptrdata != 0 {
emitGCMask(, , , bucketSize)
}
+= bucketSize * .size / ptrSize
+= / ptrSize
:=
[/8] |= 1 << ( % 8)
= &[0]
= ( + 1) * ptrSize
if != {
panic("reflect: bad layout computation in MapOf")
}
}
:= &rtype{
align: ptrSize,
size: ,
kind: uint8(Struct),
ptrdata: ,
gcdata: ,
}
if > 0 {
.align = 8
}
:= "bucket(" + .String() + "," + .String() + ")"
.str = resolveReflectName(newName(, "", false))
return
}
func ( *rtype) (, uintptr) []byte {
return (*[1 << 30]byte)(unsafe.Pointer(.gcdata))[::]
}
:= "[]" + .String()
for , := range typesByString() {
:= (*sliceType)(unsafe.Pointer())
if .elem == {
, := lookupCache.LoadOrStore(, )
return .(Type)
}
}
var structLookupCache struct {
sync.Mutex // Guards stores (but not loads) on m.
m sync.Map
}
type structTypeUncommon struct {
structType
u uncommonType
}
func ( []StructField) Type {
var (
= fnv1(0, []byte("struct {")...)
uintptr
uint8
= true
[]method
= make([]structField, len())
= make([]byte, 0, 64)
= map[string]struct{}{} // fields' names
= false // records whether a struct-field type has a GCProg
)
:= uintptr(0)
= append(, "struct {"...)
:= ""
for , := range {
if .Name == "" {
panic("reflect.StructOf: field " + strconv.Itoa() + " has no name")
}
if !isValidFieldName(.Name) {
panic("reflect.StructOf: field " + strconv.Itoa() + " has invalid name")
}
if .Type == nil {
panic("reflect.StructOf: field " + strconv.Itoa() + " has no type")
}
, := runtimeStructField()
:= .typ
if .kind&kindGCProg != 0 {
= true
}
if != "" {
if == "" {
=
} else if != {
panic("reflect.Struct: fields with different PkgPath " + + " and " + )
}
}
panic("reflect: embedded interface with unexported method(s) not implemented")
}
var (
= .typeOff(.typ)
=
=
Value
Value
)
if .kind&kindDirectIface != 0 {
= MakeFunc(, func( []Value) []Value {
var []Value
var = [0]
if len() > 1 {
= [1:]
}
return .Field().Method().Call()
})
= MakeFunc(, func( []Value) []Value {
var []Value
var = [0]
if len() > 1 {
= [1:]
}
return .Field().Method().Call()
})
} else {
= MakeFunc(, func( []Value) []Value {
var []Value
var = [0]
if len() > 1 {
= [1:]
}
return .Field().Method().Call()
})
= MakeFunc(, func( []Value) []Value {
var []Value
var = Indirect([0])
if len() > 1 {
= [1:]
}
return .Field().Method().Call()
})
}
= append(, method{
name: resolveReflectName(.nameOff(.name)),
mtyp: resolveReflectType(),
ifn: resolveReflectText(unsafe.Pointer(&)),
tfn: resolveReflectText(unsafe.Pointer(&)),
})
}
case Ptr:
:= (*ptrType)(unsafe.Pointer())
if := .uncommon(); != nil {
panic("reflect: embedded interface with unexported method(s) not implemented")
}
= append(, method{
name: resolveReflectName(),
mtyp: resolveReflectType(.typeOff(.mtyp)),
ifn: resolveReflectText(.textOff(.ifn)),
tfn: resolveReflectText(.textOff(.tfn)),
})
}
}
if := .elem.uncommon(); != nil {
for , := range .methods() {
:= .nameOff(.name)
panic("reflect: embedded interface with unexported method(s) not implemented")
}
= append(, method{
name: resolveReflectName(),
mtyp: resolveReflectType(.elem.typeOff(.mtyp)),
ifn: resolveReflectText(.elem.textOff(.ifn)),
tfn: resolveReflectText(.elem.textOff(.tfn)),
})
}
}
default:
if := .uncommon(); != nil {
panic("reflect: embedded interface with unexported method(s) not implemented")
}
= append(, method{
name: resolveReflectName(),
mtyp: resolveReflectType(.typeOff(.mtyp)),
ifn: resolveReflectText(.textOff(.ifn)),
tfn: resolveReflectText(.textOff(.tfn)),
})
}
}
}
}
if , := []; {
panic("reflect.StructOf: duplicate field " + )
}
[] = struct{}{}
= fnv1(, byte(.hash>>24), byte(.hash>>16), byte(.hash>>8), byte(.hash))
= append(, (" " + .String())...)
if .name.tagLen() > 0 {
= fnv1(, []byte(.name.tag())...)
= append(, (" " + strconv.Quote(.name.tag()))...)
}
if < len()-1 {
= append(, ';')
}
= && (.equal != nil)
:= align(, uintptr(.align))
if .align > {
= .align
}
= + .size
.offsetEmbed |= << 1
if .size == 0 {
=
}
[] =
}
++
}
var *structType
var *uncommonType
if len() == 0 {
:= new(structTypeUncommon)
= &.structType
= &.u
:= New(([]StructField{
{Name: "S", Type: TypeOf(structType{})},
{Name: "U", Type: TypeOf(uncommonType{})},
{Name: "M", Type: ArrayOf(len(), TypeOf([0]))},
}))
= (*structType)(unsafe.Pointer(.Elem().Field(0).UnsafeAddr()))
= (*uncommonType)(unsafe.Pointer(.Elem().Field(1).UnsafeAddr()))
copy(.Elem().Field(2).Slice(0, len()).Interface().([]method), )
if , := structLookupCache.m.Load(); {
for , := range .([]Type) {
:= .common()
if haveIdenticalUnderlyingType(&.rtype, , true) {
return
}
}
}
structLookupCache.Lock()
defer structLookupCache.Unlock()
if , := structLookupCache.m.Load(); {
for , := range .([]Type) {
:= .common()
if haveIdenticalUnderlyingType(&.rtype, , true) {
return
}
}
}
:= func( Type) Type {
var []Type
if , := structLookupCache.m.Load(); {
= .([]Type)
}
structLookupCache.m.Store(, append(, ))
return
}
for , := range typesByString() {
return ()
}
}
.str = resolveReflectName(newName(, "", false))
.tflag = 0 // TODO: set tflagRegularMemory
.hash =
.size =
.ptrdata = typeptrdata(.common())
.align =
.fieldAlign =
.ptrToThis = 0
if len() > 0 {
.tflag |= tflagUncommon
}
if {
:= 0
for , := range {
if .typ.pointers() {
=
}
}
:= []byte{0, 0, 0, 0} // will be length of prog
var uintptr
for , := range {
break
}
continue
if .offset() > {
:= (.offset() - ) / ptrSize
= append(, 0x01, 0x00) // emit a 0 bit
if > 1 {
= append(, 0x81) // repeat previous bit
= appendVarint(, -1) // n-1 times
}
= .offset()
}
= appendGCProg(, .typ)
+= .typ.ptrdata
}
= append(, 0)
*(*uint32)(unsafe.Pointer(&[0])) = uint32(len() - 4)
.kind |= kindGCProg
.gcdata = &[0]
} else {
.kind &^= kindGCProg
:= new(bitVector)
addTypeBits(, 0, .common())
if len(.data) > 0 {
.gcdata = &.data[0]
}
}
.equal = nil
if {
.equal = func(, unsafe.Pointer) bool {
for , := range .fields {
:= add(, .offset(), "&x.field safe")
:= add(, .offset(), "&x.field safe")
if !.typ.equal(, ) {
return false
}
}
return true
}
}
switch {
.kind |= kindDirectIface
default:
.kind &^= kindDirectIface
}
return (&.rtype)
}
func ( StructField) (structField, string) {
if .Anonymous && .PkgPath != "" {
panic("reflect.StructOf: field \"" + .Name + "\" is anonymous but has PkgPath set")
}
:= .PkgPath == ""
:= .Name[0]
if 'a' <= && <= 'z' || == '_' {
panic("reflect.StructOf: field \"" + .Name + "\" is unexported but missing PkgPath")
}
}
:= uintptr(0)
if .Anonymous {
|= 1
}
resolveReflectType(.Type.common()) // install in runtime
:= structField{
name: newName(.Name, string(.Tag), ),
typ: .Type.common(),
offsetEmbed: ,
}
return , .PkgPath
}
const maxPtrmaskBytes = 2048
:= "[" + strconv.Itoa() + "]" + .String()
for , := range typesByString() {
:= (*arrayType)(unsafe.Pointer())
if .elem == {
, := lookupCache.LoadOrStore(, )
return .(Type)
}
}
var interface{} = [1]unsafe.Pointer{}
:= *(**arrayType)(unsafe.Pointer(&))
:= *
.tflag = .tflag & tflagRegularMemory
.str = resolveReflectName(newName(, "", false))
.hash = fnv1(.hash, '[')
for := uint32(); > 0; >>= 8 {
.hash = fnv1(.hash, byte())
}
.hash = fnv1(.hash, ']')
.elem =
.ptrToThis = 0
if .size > 0 {
:= ^uintptr(0) / .size
if uintptr() > {
panic("reflect.ArrayOf: array size would exceed virtual address space")
}
}
.size = .size * uintptr()
if > 0 && .ptrdata != 0 {
.ptrdata = .size*uintptr(-1) + .ptrdata
}
.align = .align
.fieldAlign = .fieldAlign
.len = uintptr()
.slice = SliceOf().(*rtype)
switch {
:= []byte{0, 0, 0, 0} // will be length of prog
= append(, 0x01, 0x00)
if +1 < {
= append(, 0x81)
= appendVarint(, --1)
}
if < 0x80 {
= append(, byte(|0x80))
} else {
= append(, 0x80)
= appendVarint(, )
}
= appendVarint(, uintptr()-1)
= append(, 0)
*(*uint32)(unsafe.Pointer(&[0])) = uint32(len() - 4)
.kind |= kindGCProg
.gcdata = &[0]
.ptrdata = .size // overestimate but ok; must match program
}
:= .common()
:= .Size()
.equal = nil
if := .equal; != nil {
.equal = func(, unsafe.Pointer) bool {
for := 0; < ; ++ {
:= arrayAt(, , , "i < count")
:= arrayAt(, , , "i < count")
if !(, ) {
return false
}
}
return true
}
}
switch {
.kind |= kindDirectIface
default:
.kind &^= kindDirectIface
}
, := lookupCache.LoadOrStore(, &.rtype)
return .(Type)
}
func ( []byte, uintptr) []byte {
for ; >= 0x80; >>= 7 {
= append(, byte(|0x80))
}
= append(, byte())
return
}
func ( *rtype) Type {
if == nil {
return nil
}
return
}
type layoutKey struct {
ftyp *funcType // function signature
rcvr *rtype // receiver type, or nil if none
}
type layoutType struct {
t *rtype
argSize uintptr // size of arguments
retOffset uintptr // offset of return values.
stack *bitVector
framePool *sync.Pool
}
var layoutCache sync.Map // map[layoutKey]layoutType
func ( *funcType, *rtype) ( *rtype, , uintptr, *bitVector, *sync.Pool) {
if .Kind() != Func {
panic("reflect: funcLayout of non-func type " + .String())
}
if != nil && .Kind() == Interface {
panic("reflect: funcLayout with interface receiver " + .String())
}
:= layoutKey{, }
if , := layoutCache.Load(); {
:= .(layoutType)
return .t, .argSize, .retOffset, .stack, .framePool
}
= &sync.Pool{New: func() interface{} {
return unsafe_New()
}}
, := layoutCache.LoadOrStore(, layoutType{
t: ,
argSize: ,
retOffset: ,
stack: ,
framePool: ,
})
:= .(layoutType)
return .t, .argSize, .retOffset, .stack, .framePool
}
func ( *rtype) bool {
return .kind&kindDirectIface == 0
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |