mirrored from git://gcc.gnu.org/git/gcc.git
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
type.go
213 lines (185 loc) · 5.06 KB
/
type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Runtime type representation.
package runtime
import (
"runtime/internal/atomic"
"runtime/internal/sys"
"unsafe"
)
type _type struct {
size uintptr
ptrdata uintptr
hash uint32
kind uint8
align int8
fieldAlign uint8
_ uint8
hashfn func(unsafe.Pointer, uintptr) uintptr
equalfn func(unsafe.Pointer, unsafe.Pointer) bool
gcdata *byte
_string *string
*uncommontype
ptrToThis *_type
}
func (t *_type) string() string {
return *t._string
}
// pkgpath returns the path of the package where t was defined, if
// available. This is not the same as the reflect package's PkgPath
// method, in that it returns the package path for struct and interface
// types, not just named types.
func (t *_type) pkgpath() string {
if u := t.uncommontype; u != nil {
if u.pkgPath == nil {
return ""
}
return *u.pkgPath
}
return ""
}
type method struct {
name *string
pkgPath *string
mtyp *_type
typ *_type
tfn unsafe.Pointer
}
type uncommontype struct {
name *string
pkgPath *string
methods []method
}
type imethod struct {
name *string
pkgPath *string
typ *_type
}
type interfacetype struct {
typ _type
methods []imethod
}
type maptype struct {
typ _type
key *_type
elem *_type
bucket *_type // internal type representing a hash bucket
keysize uint8 // size of key slot
valuesize uint8 // size of value slot
bucketsize uint16 // size of bucket
flags uint32
}
// Note: flag values must match those used in the TMAP case
// in ../cmd/compile/internal/gc/reflect.go:dtypesym.
func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
return mt.flags&1 != 0
}
func (mt *maptype) indirectvalue() bool { // store ptr to value instead of value itself
return mt.flags&2 != 0
}
func (mt *maptype) reflexivekey() bool { // true if k==k for all keys
return mt.flags&4 != 0
}
func (mt *maptype) needkeyupdate() bool { // true if we need to update key on an overwrite
return mt.flags&8 != 0
}
func (mt *maptype) hashMightPanic() bool { // true if hash function might panic
return mt.flags&16 != 0
}
type arraytype struct {
typ _type
elem *_type
slice *_type
len uintptr
}
type chantype struct {
typ _type
elem *_type
dir uintptr
}
type slicetype struct {
typ _type
elem *_type
}
type functype struct {
typ _type
dotdotdot bool
in []*_type
out []*_type
}
type ptrtype struct {
typ _type
elem *_type
}
type structfield struct {
name *string // nil for embedded fields
pkgPath *string // nil for exported Names; otherwise import path
typ *_type // type of field
tag *string // nil if no tag
offsetAnon uintptr // byte offset of field<<1 | isAnonymous
}
func (f *structfield) offset() uintptr {
return f.offsetAnon >> 1
}
func (f *structfield) anon() bool {
return f.offsetAnon&1 != 0
}
type structtype struct {
typ _type
fields []structfield
}
// typeDescriptorList holds a list of type descriptors generated
// by the compiler. This is used for the compiler to register
// type descriptors to the runtime.
// The layout is known to the compiler.
//go:notinheap
type typeDescriptorList struct {
count int
types [1]uintptr // variable length
}
// typelist holds all type descriptors generated by the comiler.
// This is for the reflect package to deduplicate type descriptors
// when it creates a type that is also a compiler-generated type.
var typelist struct {
initialized uint32
lists []*typeDescriptorList // one element per package
types map[string]uintptr // map from a type's string to *_type, lazily populated
// TODO: use a sorted array instead?
}
var typelistLock mutex
// The compiler generates a call of this function in the main
// package's init function, to register compiler-generated
// type descriptors.
// p points to a list of *typeDescriptorList, n is the length
// of the list.
//go:linkname registerTypeDescriptors
func registerTypeDescriptors(n int, p unsafe.Pointer) {
*(*slice)(unsafe.Pointer(&typelist.lists)) = slice{p, n, n}
}
// The reflect package uses this function to look up a compiler-
// generated type descriptor.
//go:linkname reflect_lookupType reflect.lookupType
func reflect_lookupType(s string) *_type {
// Lazy initialization. We don't need to do this if we never create
// types through reflection.
if atomic.Load(&typelist.initialized) == 0 {
lock(&typelistLock)
if atomic.Load(&typelist.initialized) == 0 {
n := 0
for _, list := range typelist.lists {
n += list.count
}
typelist.types = make(map[string]uintptr, n)
for _, list := range typelist.lists {
for i := 0; i < list.count; i++ {
typ := *(**_type)(add(unsafe.Pointer(&list.types), uintptr(i)*sys.PtrSize))
typelist.types[typ.string()] = uintptr(unsafe.Pointer(typ))
}
}
atomic.Store(&typelist.initialized, 1)
}
unlock(&typelistLock)
}
return (*_type)(unsafe.Pointer(typelist.types[s]))
}