github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/iface.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 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 // lock for accessing itab table 17 itabTable = &itabTableInit // pointer to current table 18 itabTableInit = itabTableType{size: itabInitSize} // starter table 19 ) 20 21 //Note: change the formula in the mallocgc call in itabAdd if you change these fields. 22 type itabTableType struct { 23 size uintptr // length of entries array. Always a power of 2. 24 count uintptr // current number of filled entries. 25 entries [itabInitSize]*itab // really [size] large 26 } 27 28 func itabHashFunc(inter *interfacetype, typ *_type) uintptr { 29 // compiler has provided some good hash codes for us. 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 // easy case 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{"", typ.string(), inter.typ.string(), name.name()}) 45 } 46 47 var m *itab 48 49 // First, look in the existing table to see if we can find the itab we need. 50 // This is by far the most common case, so do it without locks. 51 // Use atomic to ensure we see any previous writes done by the thread 52 // that updates the itabTable field (with atomic.Storep in itabAdd). 53 t := (*itabTableType)(atomic.Loadp(unsafe.Pointer(&itabTable))) 54 if m = t.find(inter, typ); m != nil { 55 goto finish 56 } 57 58 // Not found. Grab the lock and try again. 59 lock(&itabLock) 60 if m = itabTable.find(inter, typ); m != nil { 61 unlock(&itabLock) 62 goto finish 63 } 64 65 // Entry doesn't exist yet. Make a new entry & add it. 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 // this can only happen if the conversion 80 // was already done once using the , ok form 81 // and we have a cached negative result. 82 // The cached result doesn't record which 83 // interface function was missing, so initialize 84 // the itab again to get the missing function name. 85 panic(&TypeAssertionError{concreteString: typ.string(), assertedString: inter.typ.string(), missingMethod: m.init()}) 86 } 87 88 // find finds the given interface/type pair in t. 89 // Returns nil if the given interface/type pair isn't present. 90 func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab { 91 // Implemented using quadratic probing. 92 // Probe sequence is h(i) = h0 + i*(i+1)/2 mod 2^k. 93 // We're guaranteed to hit all table entries using this probe sequence. 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 // Use atomic read here so if we see m != nil, we also see 99 // the initializations of the fields of m. 100 // m := *p 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 // itabAdd adds the given itab to the itab hash table. 114 // itabLock must be held. 115 func itabAdd(m *itab) { 116 // Bugs can lead to calling this while mallocing is set, 117 // typically because this is called while panicing. 118 // Crash reliably, rather than only when we need to grow 119 // the hash table. 120 if getg().m.mallocing != 0 { 121 throw("malloc deadlock") 122 } 123 124 t := itabTable 125 if t.count >= 3*(t.size/4) { // 75% load factor 126 // Grow hash table. 127 // t2 = new(itabTableType) + some additional entries 128 // We lie and tell malloc we want pointer-free memory because 129 // all the pointed-to values are not in the heap. 130 t2 := (*itabTableType)(mallocgc((2+2*t.size)*sys.PtrSize, nil, true)) 131 t2.size = t.size * 2 132 133 // Copy over entries. 134 // Note: while copying, other threads may look for an itab and 135 // fail to find it. That's ok, they will then try to get the itab lock 136 // and as a consequence wait until this copying is complete. 137 iterate_itabs(t2.add) 138 if t2.count != t.count { 139 throw("mismatched count during itab table copy") 140 } 141 // Publish new hash table. Use an atomic write: see comment in getitab. 142 atomicstorep(unsafe.Pointer(&itabTable), unsafe.Pointer(t2)) 143 // Adopt the new table as our own. 144 t = itabTable 145 // Note: the old table can be GC'ed here. 146 } 147 t.add(m) 148 } 149 150 // add adds the given itab to itab table t. 151 // itabLock must be held. 152 func (t *itabTableType) add(m *itab) { 153 // See comment in find about the probe sequence. 154 // Insert new itab in the first empty spot in the probe sequence. 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 // A given itab may be used in more than one module 162 // and thanks to the way global symbol resolution works, the 163 // pointed-to itab may already have been inserted into the 164 // global 'hash'. 165 return 166 } 167 if m2 == nil { 168 // Use atomic write here so if a reader sees m, it also 169 // sees the correctly initialized fields of m. 170 // NoWB is ok because m is not in heap memory. 171 // *p = m 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 // init fills in the m.fun array with all the code pointers for 182 // the m.inter/m._type pair. If the type does not implement the interface, 183 // it sets m.fun[0] to 0 and returns the name of an interface function that is missing. 184 // It is ok to call this multiple times on the same m, even concurrently. 185 func (m *itab) init() string { 186 inter := m.inter 187 typ := m._type 188 x := typ.uncommon() 189 190 // both inter and typ have method sorted by name, 191 // and interface names are unique, 192 // so can iterate over both in lock step; 193 // the loop is O(ni+nt) not O(ni*nt). 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 imethods: 199 for k := 0; k < ni; k++ { 200 i := &inter.mhdr[k] 201 itype := inter.typ.typeOff(i.ityp) 202 name := inter.typ.nameOff(i.name) 203 iname := name.name() 204 ipkg := name.pkgPath() 205 if ipkg == "" { 206 ipkg = inter.pkgpath.name() 207 } 208 for ; j < nt; j++ { 209 t := &xmhdr[j] 210 tname := typ.nameOff(t.name) 211 if typ.typeOff(t.mtyp) == itype && tname.name() == iname { 212 pkgPath := tname.pkgPath() 213 if pkgPath == "" { 214 pkgPath = typ.nameOff(x.pkgpath).name() 215 } 216 if tname.isExported() || pkgPath == ipkg { 217 if m != nil { 218 ifn := typ.textOff(t.ifn) 219 *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn 220 } 221 continue imethods 222 } 223 } 224 } 225 // didn't find method 226 m.fun[0] = 0 227 return iname 228 } 229 m.hash = typ.hash 230 return "" 231 } 232 233 func itabsinit() { 234 lock(&itabLock) 235 for _, md := range activeModules() { 236 for _, i := range md.itablinks { 237 itabAdd(i) 238 } 239 } 240 unlock(&itabLock) 241 } 242 243 // panicdottypeE is called when doing an e.(T) conversion and the conversion fails. 244 // have = the dynamic type we have. 245 // want = the static type we're trying to convert to. 246 // iface = the static type we're converting from. 247 func panicdottypeE(have, want, iface *_type) { 248 haveString := "" 249 if have != nil { 250 haveString = have.string() 251 } 252 panic(&TypeAssertionError{iface.string(), haveString, want.string(), ""}) 253 } 254 255 // panicdottypeI is called when doing an i.(T) conversion and the conversion fails. 256 // Same args as panicdottypeE, but "have" is the dynamic itab we have. 257 func panicdottypeI(have *itab, want, iface *_type) { 258 var t *_type 259 if have != nil { 260 t = have._type 261 } 262 panicdottypeE(t, want, iface) 263 } 264 265 // panicnildottype is called when doing a i.(T) conversion and the interface i is nil. 266 // want = the static type we're trying to convert to. 267 func panicnildottype(want *_type) { 268 panic(&TypeAssertionError{"", "", want.string(), ""}) 269 // TODO: Add the static type we're converting from as well. 270 // It might generate a better error message. 271 // Just to match other nil conversion errors, we don't for now. 272 } 273 274 // The conv and assert functions below do very similar things. 275 // The convXXX functions are guaranteed by the compiler to succeed. 276 // The assertXXX functions may fail (either panicking or returning false, 277 // depending on whether they are 1-result or 2-result). 278 // The convXXX functions succeed on a nil input, whereas the assertXXX 279 // functions fail on a nil input. 280 281 func convT2E(t *_type, elem unsafe.Pointer) (e eface) { 282 if raceenabled { 283 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E)) 284 } 285 if msanenabled { 286 msanread(elem, t.size) 287 } 288 x := mallocgc(t.size, t, true) 289 // TODO: We allocate a zeroed object only to overwrite it with actual data. 290 // Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice. 291 typedmemmove(t, x, elem) 292 e._type = t 293 e.data = x 294 return 295 } 296 297 func convT2E16(t *_type, elem unsafe.Pointer) (e eface) { 298 if raceenabled { 299 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E16)) 300 } 301 if msanenabled { 302 msanread(elem, t.size) 303 } 304 var x unsafe.Pointer 305 if *(*uint16)(elem) == 0 { 306 x = unsafe.Pointer(&zeroVal[0]) 307 } else { 308 x = mallocgc(2, t, false) 309 *(*uint16)(x) = *(*uint16)(elem) 310 } 311 e._type = t 312 e.data = x 313 return 314 } 315 316 func convT2E32(t *_type, elem unsafe.Pointer) (e eface) { 317 if raceenabled { 318 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E32)) 319 } 320 if msanenabled { 321 msanread(elem, t.size) 322 } 323 var x unsafe.Pointer 324 if *(*uint32)(elem) == 0 { 325 x = unsafe.Pointer(&zeroVal[0]) 326 } else { 327 x = mallocgc(4, t, false) 328 *(*uint32)(x) = *(*uint32)(elem) 329 } 330 e._type = t 331 e.data = x 332 return 333 } 334 335 func convT2E64(t *_type, elem unsafe.Pointer) (e eface) { 336 if raceenabled { 337 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E64)) 338 } 339 if msanenabled { 340 msanread(elem, t.size) 341 } 342 var x unsafe.Pointer 343 if *(*uint64)(elem) == 0 { 344 x = unsafe.Pointer(&zeroVal[0]) 345 } else { 346 x = mallocgc(8, t, false) 347 *(*uint64)(x) = *(*uint64)(elem) 348 } 349 e._type = t 350 e.data = x 351 return 352 } 353 354 func convT2Estring(t *_type, elem unsafe.Pointer) (e eface) { 355 if raceenabled { 356 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Estring)) 357 } 358 if msanenabled { 359 msanread(elem, t.size) 360 } 361 var x unsafe.Pointer 362 if *(*string)(elem) == "" { 363 x = unsafe.Pointer(&zeroVal[0]) 364 } else { 365 x = mallocgc(t.size, t, true) 366 *(*string)(x) = *(*string)(elem) 367 } 368 e._type = t 369 e.data = x 370 return 371 } 372 373 func convT2Eslice(t *_type, elem unsafe.Pointer) (e eface) { 374 if raceenabled { 375 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Eslice)) 376 } 377 if msanenabled { 378 msanread(elem, t.size) 379 } 380 var x unsafe.Pointer 381 if v := *(*slice)(elem); uintptr(v.array) == 0 { 382 x = unsafe.Pointer(&zeroVal[0]) 383 } else { 384 x = mallocgc(t.size, t, true) 385 *(*slice)(x) = *(*slice)(elem) 386 } 387 e._type = t 388 e.data = x 389 return 390 } 391 392 func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { 393 if raceenabled { 394 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Enoptr)) 395 } 396 if msanenabled { 397 msanread(elem, t.size) 398 } 399 x := mallocgc(t.size, t, false) 400 memmove(x, elem, t.size) 401 e._type = t 402 e.data = x 403 return 404 } 405 406 func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { 407 t := tab._type 408 if raceenabled { 409 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I)) 410 } 411 if msanenabled { 412 msanread(elem, t.size) 413 } 414 x := mallocgc(t.size, t, true) 415 typedmemmove(t, x, elem) 416 i.tab = tab 417 i.data = x 418 return 419 } 420 421 func convT2I16(tab *itab, elem unsafe.Pointer) (i iface) { 422 t := tab._type 423 if raceenabled { 424 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I16)) 425 } 426 if msanenabled { 427 msanread(elem, t.size) 428 } 429 var x unsafe.Pointer 430 if *(*uint16)(elem) == 0 { 431 x = unsafe.Pointer(&zeroVal[0]) 432 } else { 433 x = mallocgc(2, t, false) 434 *(*uint16)(x) = *(*uint16)(elem) 435 } 436 i.tab = tab 437 i.data = x 438 return 439 } 440 441 func convT2I32(tab *itab, elem unsafe.Pointer) (i iface) { 442 t := tab._type 443 if raceenabled { 444 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I32)) 445 } 446 if msanenabled { 447 msanread(elem, t.size) 448 } 449 var x unsafe.Pointer 450 if *(*uint32)(elem) == 0 { 451 x = unsafe.Pointer(&zeroVal[0]) 452 } else { 453 x = mallocgc(4, t, false) 454 *(*uint32)(x) = *(*uint32)(elem) 455 } 456 i.tab = tab 457 i.data = x 458 return 459 } 460 461 func convT2I64(tab *itab, elem unsafe.Pointer) (i iface) { 462 t := tab._type 463 if raceenabled { 464 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I64)) 465 } 466 if msanenabled { 467 msanread(elem, t.size) 468 } 469 var x unsafe.Pointer 470 if *(*uint64)(elem) == 0 { 471 x = unsafe.Pointer(&zeroVal[0]) 472 } else { 473 x = mallocgc(8, t, false) 474 *(*uint64)(x) = *(*uint64)(elem) 475 } 476 i.tab = tab 477 i.data = x 478 return 479 } 480 481 func convT2Istring(tab *itab, elem unsafe.Pointer) (i iface) { 482 t := tab._type 483 if raceenabled { 484 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Istring)) 485 } 486 if msanenabled { 487 msanread(elem, t.size) 488 } 489 var x unsafe.Pointer 490 if *(*string)(elem) == "" { 491 x = unsafe.Pointer(&zeroVal[0]) 492 } else { 493 x = mallocgc(t.size, t, true) 494 *(*string)(x) = *(*string)(elem) 495 } 496 i.tab = tab 497 i.data = x 498 return 499 } 500 501 func convT2Islice(tab *itab, elem unsafe.Pointer) (i iface) { 502 t := tab._type 503 if raceenabled { 504 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Islice)) 505 } 506 if msanenabled { 507 msanread(elem, t.size) 508 } 509 var x unsafe.Pointer 510 if v := *(*slice)(elem); uintptr(v.array) == 0 { 511 x = unsafe.Pointer(&zeroVal[0]) 512 } else { 513 x = mallocgc(t.size, t, true) 514 *(*slice)(x) = *(*slice)(elem) 515 } 516 i.tab = tab 517 i.data = x 518 return 519 } 520 521 func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) { 522 t := tab._type 523 if raceenabled { 524 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Inoptr)) 525 } 526 if msanenabled { 527 msanread(elem, t.size) 528 } 529 x := mallocgc(t.size, t, false) 530 memmove(x, elem, t.size) 531 i.tab = tab 532 i.data = x 533 return 534 } 535 536 func convI2I(inter *interfacetype, i iface) (r iface) { 537 tab := i.tab 538 if tab == nil { 539 return 540 } 541 if tab.inter == inter { 542 r.tab = tab 543 r.data = i.data 544 return 545 } 546 r.tab = getitab(inter, tab._type, false) 547 r.data = i.data 548 return 549 } 550 551 func assertI2I(inter *interfacetype, i iface) (r iface) { 552 tab := i.tab 553 if tab == nil { 554 // explicit conversions require non-nil interface value. 555 panic(&TypeAssertionError{"", "", inter.typ.string(), ""}) 556 } 557 if tab.inter == inter { 558 r.tab = tab 559 r.data = i.data 560 return 561 } 562 r.tab = getitab(inter, tab._type, false) 563 r.data = i.data 564 return 565 } 566 567 func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) { 568 tab := i.tab 569 if tab == nil { 570 return 571 } 572 if tab.inter != inter { 573 tab = getitab(inter, tab._type, true) 574 if tab == nil { 575 return 576 } 577 } 578 r.tab = tab 579 r.data = i.data 580 b = true 581 return 582 } 583 584 func assertE2I(inter *interfacetype, e eface) (r iface) { 585 t := e._type 586 if t == nil { 587 // explicit conversions require non-nil interface value. 588 panic(&TypeAssertionError{"", "", inter.typ.string(), ""}) 589 } 590 r.tab = getitab(inter, t, false) 591 r.data = e.data 592 return 593 } 594 595 func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) { 596 t := e._type 597 if t == nil { 598 return 599 } 600 tab := getitab(inter, t, true) 601 if tab == nil { 602 return 603 } 604 r.tab = tab 605 r.data = e.data 606 b = true 607 return 608 } 609 610 //go:linkname reflect_ifaceE2I reflect.ifaceE2I 611 func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) { 612 *dst = assertE2I(inter, e) 613 } 614 615 func iterate_itabs(fn func(*itab)) { 616 // Note: only runs during stop the world or with itabLock held, 617 // so no other locks/atomics needed. 618 t := itabTable 619 for i := uintptr(0); i < t.size; i++ { 620 m := *(**itab)(add(unsafe.Pointer(&t.entries), i*sys.PtrSize)) 621 if m != nil { 622 fn(m) 623 } 624 } 625 } 626 627 // staticbytes is used to avoid convT2E for byte-sized values. 628 var staticbytes = [...]byte{ 629 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 630 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 631 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 632 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 633 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 634 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 635 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 636 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 637 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 638 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 639 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 640 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 641 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 642 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 643 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 644 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 645 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 646 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 647 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 648 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 649 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 650 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 651 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 652 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 653 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 654 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 655 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 656 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 657 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 658 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 659 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 660 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 661 }