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