Source file
src/runtime/iface.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "runtime/internal/atomic"
11 "unsafe"
12 )
13
14 const itabInitSize = 512
15
16 var (
17 itabLock mutex
18 itabTable = &itabTableInit
19 itabTableInit = itabTableType{size: itabInitSize}
20 )
21
22
23 type itabTableType struct {
24 size uintptr
25 count uintptr
26 entries [itabInitSize]*itab
27 }
28
29 func itabHashFunc(inter *interfacetype, typ *_type) uintptr {
30
31 return uintptr(inter.typ.hash ^ typ.hash)
32 }
33
34 func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
35 if len(inter.mhdr) == 0 {
36 throw("internal error - misuse of itab")
37 }
38
39
40 if typ.tflag&tflagUncommon == 0 {
41 if canfail {
42 return nil
43 }
44 name := inter.typ.nameOff(inter.mhdr[0].name)
45 panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
46 }
47
48 var m *itab
49
50
51
52
53
54 t := (*itabTableType)(atomic.Loadp(unsafe.Pointer(&itabTable)))
55 if m = t.find(inter, typ); m != nil {
56 goto finish
57 }
58
59
60 lock(&itabLock)
61 if m = itabTable.find(inter, typ); m != nil {
62 unlock(&itabLock)
63 goto finish
64 }
65
66
67 m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*goarch.PtrSize, 0, &memstats.other_sys))
68 m.inter = inter
69 m._type = typ
70
71
72
73
74
75 m.hash = 0
76 m.init()
77 itabAdd(m)
78 unlock(&itabLock)
79 finish:
80 if m.fun[0] != 0 {
81 return m
82 }
83 if canfail {
84 return nil
85 }
86
87
88
89
90
91
92 panic(&TypeAssertionError{concrete: typ, asserted: &inter.typ, missingMethod: m.init()})
93 }
94
95
96
97 func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab {
98
99
100
101 mask := t.size - 1
102 h := itabHashFunc(inter, typ) & mask
103 for i := uintptr(1); ; i++ {
104 p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
105
106
107
108 m := (*itab)(atomic.Loadp(unsafe.Pointer(p)))
109 if m == nil {
110 return nil
111 }
112 if m.inter == inter && m._type == typ {
113 return m
114 }
115 h += i
116 h &= mask
117 }
118 }
119
120
121
122 func itabAdd(m *itab) {
123
124
125
126
127 if getg().m.mallocing != 0 {
128 throw("malloc deadlock")
129 }
130
131 t := itabTable
132 if t.count >= 3*(t.size/4) {
133
134
135
136
137 t2 := (*itabTableType)(mallocgc((2+2*t.size)*goarch.PtrSize, nil, true))
138 t2.size = t.size * 2
139
140
141
142
143
144 iterate_itabs(t2.add)
145 if t2.count != t.count {
146 throw("mismatched count during itab table copy")
147 }
148
149 atomicstorep(unsafe.Pointer(&itabTable), unsafe.Pointer(t2))
150
151 t = itabTable
152
153 }
154 t.add(m)
155 }
156
157
158
159 func (t *itabTableType) add(m *itab) {
160
161
162 mask := t.size - 1
163 h := itabHashFunc(m.inter, m._type) & mask
164 for i := uintptr(1); ; i++ {
165 p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize))
166 m2 := *p
167 if m2 == m {
168
169
170
171
172 return
173 }
174 if m2 == nil {
175
176
177
178
179 atomic.StorepNoWB(unsafe.Pointer(p), unsafe.Pointer(m))
180 t.count++
181 return
182 }
183 h += i
184 h &= mask
185 }
186 }
187
188
189
190
191
192 func (m *itab) init() string {
193 inter := m.inter
194 typ := m._type
195 x := typ.uncommon()
196
197
198
199
200
201 ni := len(inter.mhdr)
202 nt := int(x.mcount)
203 xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt]
204 j := 0
205 methods := (*[1 << 16]unsafe.Pointer)(unsafe.Pointer(&m.fun[0]))[:ni:ni]
206 var fun0 unsafe.Pointer
207 imethods:
208 for k := 0; k < ni; k++ {
209 i := &inter.mhdr[k]
210 itype := inter.typ.typeOff(i.ityp)
211 name := inter.typ.nameOff(i.name)
212 iname := name.name()
213 ipkg := name.pkgPath()
214 if ipkg == "" {
215 ipkg = inter.pkgpath.name()
216 }
217 for ; j < nt; j++ {
218 t := &xmhdr[j]
219 tname := typ.nameOff(t.name)
220 if typ.typeOff(t.mtyp) == itype && tname.name() == iname {
221 pkgPath := tname.pkgPath()
222 if pkgPath == "" {
223 pkgPath = typ.nameOff(x.pkgpath).name()
224 }
225 if tname.isExported() || pkgPath == ipkg {
226 if m != nil {
227 ifn := typ.textOff(t.ifn)
228 if k == 0 {
229 fun0 = ifn
230 } else {
231 methods[k] = ifn
232 }
233 }
234 continue imethods
235 }
236 }
237 }
238
239 m.fun[0] = 0
240 return iname
241 }
242 m.fun[0] = uintptr(fun0)
243 return ""
244 }
245
246 func itabsinit() {
247 lockInit(&itabLock, lockRankItab)
248 lock(&itabLock)
249 for _, md := range activeModules() {
250 for _, i := range md.itablinks {
251 itabAdd(i)
252 }
253 }
254 unlock(&itabLock)
255 }
256
257
258
259
260
261 func panicdottypeE(have, want, iface *_type) {
262 panic(&TypeAssertionError{iface, have, want, ""})
263 }
264
265
266
267 func panicdottypeI(have *itab, want, iface *_type) {
268 var t *_type
269 if have != nil {
270 t = have._type
271 }
272 panicdottypeE(t, want, iface)
273 }
274
275
276
277 func panicnildottype(want *_type) {
278 panic(&TypeAssertionError{nil, nil, want, ""})
279
280
281
282 }
283
284
285
286
287
288
289
290 type (
291 uint16InterfacePtr uint16
292 uint32InterfacePtr uint32
293 uint64InterfacePtr uint64
294 stringInterfacePtr string
295 sliceInterfacePtr []byte
296 )
297
298 var (
299 uint16Eface any = uint16InterfacePtr(0)
300 uint32Eface any = uint32InterfacePtr(0)
301 uint64Eface any = uint64InterfacePtr(0)
302 stringEface any = stringInterfacePtr("")
303 sliceEface any = sliceInterfacePtr(nil)
304
305 uint16Type *_type = efaceOf(&uint16Eface)._type
306 uint32Type *_type = efaceOf(&uint32Eface)._type
307 uint64Type *_type = efaceOf(&uint64Eface)._type
308 stringType *_type = efaceOf(&stringEface)._type
309 sliceType *_type = efaceOf(&sliceEface)._type
310 )
311
312
313
314
315
316
317
318
319
320
321 func convT(t *_type, v unsafe.Pointer) unsafe.Pointer {
322 if raceenabled {
323 raceReadObjectPC(t, v, getcallerpc(), abi.FuncPCABIInternal(convT))
324 }
325 if msanenabled {
326 msanread(v, t.size)
327 }
328 if asanenabled {
329 asanread(v, t.size)
330 }
331 x := mallocgc(t.size, t, true)
332 typedmemmove(t, x, v)
333 return x
334 }
335 func convTnoptr(t *_type, v unsafe.Pointer) unsafe.Pointer {
336
337 if raceenabled {
338 raceReadObjectPC(t, v, getcallerpc(), abi.FuncPCABIInternal(convTnoptr))
339 }
340 if msanenabled {
341 msanread(v, t.size)
342 }
343 if asanenabled {
344 asanread(v, t.size)
345 }
346
347 x := mallocgc(t.size, t, false)
348 memmove(x, v, t.size)
349 return x
350 }
351
352 func convT16(val uint16) (x unsafe.Pointer) {
353 if val < uint16(len(staticuint64s)) {
354 x = unsafe.Pointer(&staticuint64s[val])
355 if goarch.BigEndian {
356 x = add(x, 6)
357 }
358 } else {
359 x = mallocgc(2, uint16Type, false)
360 *(*uint16)(x) = val
361 }
362 return
363 }
364
365 func convT32(val uint32) (x unsafe.Pointer) {
366 if val < uint32(len(staticuint64s)) {
367 x = unsafe.Pointer(&staticuint64s[val])
368 if goarch.BigEndian {
369 x = add(x, 4)
370 }
371 } else {
372 x = mallocgc(4, uint32Type, false)
373 *(*uint32)(x) = val
374 }
375 return
376 }
377
378 func convT64(val uint64) (x unsafe.Pointer) {
379 if val < uint64(len(staticuint64s)) {
380 x = unsafe.Pointer(&staticuint64s[val])
381 } else {
382 x = mallocgc(8, uint64Type, false)
383 *(*uint64)(x) = val
384 }
385 return
386 }
387
388 func convTstring(val string) (x unsafe.Pointer) {
389 if val == "" {
390 x = unsafe.Pointer(&zeroVal[0])
391 } else {
392 x = mallocgc(unsafe.Sizeof(val), stringType, true)
393 *(*string)(x) = val
394 }
395 return
396 }
397
398 func convTslice(val []byte) (x unsafe.Pointer) {
399
400 if (*slice)(unsafe.Pointer(&val)).array == nil {
401 x = unsafe.Pointer(&zeroVal[0])
402 } else {
403 x = mallocgc(unsafe.Sizeof(val), sliceType, true)
404 *(*[]byte)(x) = val
405 }
406 return
407 }
408
409
410
411 func convI2I(dst *interfacetype, src *itab) *itab {
412 if src == nil {
413 return nil
414 }
415 if src.inter == dst {
416 return src
417 }
418 return getitab(dst, src._type, false)
419 }
420
421 func assertI2I(inter *interfacetype, tab *itab) *itab {
422 if tab == nil {
423
424 panic(&TypeAssertionError{nil, nil, &inter.typ, ""})
425 }
426 if tab.inter == inter {
427 return tab
428 }
429 return getitab(inter, tab._type, false)
430 }
431
432 func assertI2I2(inter *interfacetype, i iface) (r iface) {
433 tab := i.tab
434 if tab == nil {
435 return
436 }
437 if tab.inter != inter {
438 tab = getitab(inter, tab._type, true)
439 if tab == nil {
440 return
441 }
442 }
443 r.tab = tab
444 r.data = i.data
445 return
446 }
447
448 func assertE2I(inter *interfacetype, t *_type) *itab {
449 if t == nil {
450
451 panic(&TypeAssertionError{nil, nil, &inter.typ, ""})
452 }
453 return getitab(inter, t, false)
454 }
455
456 func assertE2I2(inter *interfacetype, e eface) (r iface) {
457 t := e._type
458 if t == nil {
459 return
460 }
461 tab := getitab(inter, t, true)
462 if tab == nil {
463 return
464 }
465 r.tab = tab
466 r.data = e.data
467 return
468 }
469
470
471 func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
472 *dst = iface{assertE2I(inter, e._type), e.data}
473 }
474
475
476 func reflectlite_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
477 *dst = iface{assertE2I(inter, e._type), e.data}
478 }
479
480 func iterate_itabs(fn func(*itab)) {
481
482
483 t := itabTable
484 for i := uintptr(0); i < t.size; i++ {
485 m := *(**itab)(add(unsafe.Pointer(&t.entries), i*goarch.PtrSize))
486 if m != nil {
487 fn(m)
488 }
489 }
490 }
491
492
493 var staticuint64s = [...]uint64{
494 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
495 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
496 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
497 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
498 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
499 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
500 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
501 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
502 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
503 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
504 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
505 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
506 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
507 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
508 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
509 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
510 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
511 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
512 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
513 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
514 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
515 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
516 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
517 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
518 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
519 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
520 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
521 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
522 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
523 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
524 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
525 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
526 }
527
528
529
530
531 func unreachableMethod() {
532 throw("unreachable method called. linker bug?")
533 }
534
View as plain text