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