github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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{nil, typ, &inter.typ, 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{concrete: typ, asserted: &inter.typ, 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 panic(&TypeAssertionError{iface, have, want, ""}) 249 } 250 251 // panicdottypeI is called when doing an i.(T) conversion and the conversion fails. 252 // Same args as panicdottypeE, but "have" is the dynamic itab we have. 253 func panicdottypeI(have *itab, want, iface *_type) { 254 var t *_type 255 if have != nil { 256 t = have._type 257 } 258 panicdottypeE(t, want, iface) 259 } 260 261 // panicnildottype is called when doing a i.(T) conversion and the interface i is nil. 262 // want = the static type we're trying to convert to. 263 func panicnildottype(want *_type) { 264 panic(&TypeAssertionError{nil, nil, want, ""}) 265 // TODO: Add the static type we're converting from as well. 266 // It might generate a better error message. 267 // Just to match other nil conversion errors, we don't for now. 268 } 269 270 // The conv and assert functions below do very similar things. 271 // The convXXX functions are guaranteed by the compiler to succeed. 272 // The assertXXX functions may fail (either panicking or returning false, 273 // depending on whether they are 1-result or 2-result). 274 // The convXXX functions succeed on a nil input, whereas the assertXXX 275 // functions fail on a nil input. 276 277 func convT2E(t *_type, elem unsafe.Pointer) (e eface) { 278 if raceenabled { 279 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E)) 280 } 281 if msanenabled { 282 msanread(elem, t.size) 283 } 284 x := mallocgc(t.size, t, true) 285 // TODO: We allocate a zeroed object only to overwrite it with actual data. 286 // Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice. 287 typedmemmove(t, x, elem) 288 e._type = t 289 e.data = x 290 return 291 } 292 293 func convT2E16(t *_type, val uint16) (e eface) { 294 var x unsafe.Pointer 295 if val == 0 { 296 x = unsafe.Pointer(&zeroVal[0]) 297 } else { 298 x = mallocgc(2, t, false) 299 *(*uint16)(x) = val 300 } 301 e._type = t 302 e.data = x 303 return 304 } 305 306 func convT2E32(t *_type, val uint32) (e eface) { 307 var x unsafe.Pointer 308 if val == 0 { 309 x = unsafe.Pointer(&zeroVal[0]) 310 } else { 311 x = mallocgc(4, t, false) 312 *(*uint32)(x) = val 313 } 314 e._type = t 315 e.data = x 316 return 317 } 318 319 func convT2E64(t *_type, val uint64) (e eface) { 320 var x unsafe.Pointer 321 if val == 0 { 322 x = unsafe.Pointer(&zeroVal[0]) 323 } else { 324 x = mallocgc(8, t, false) 325 *(*uint64)(x) = val 326 } 327 e._type = t 328 e.data = x 329 return 330 } 331 332 func convT2Estring(t *_type, val string) (e eface) { 333 var x unsafe.Pointer 334 if val == "" { 335 x = unsafe.Pointer(&zeroVal[0]) 336 } else { 337 x = mallocgc(unsafe.Sizeof(val), t, true) 338 *(*string)(x) = val 339 } 340 e._type = t 341 e.data = x 342 return 343 } 344 345 func convT2Eslice(t *_type, val []byte) (e eface) { 346 // Note: this must work for any element type, not just byte. 347 var x unsafe.Pointer 348 if (*slice)(unsafe.Pointer(&val)).array == nil { 349 x = unsafe.Pointer(&zeroVal[0]) 350 } else { 351 x = mallocgc(unsafe.Sizeof(val), t, true) 352 *(*[]byte)(x) = val 353 } 354 e._type = t 355 e.data = x 356 return 357 } 358 359 func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { 360 if raceenabled { 361 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Enoptr)) 362 } 363 if msanenabled { 364 msanread(elem, t.size) 365 } 366 x := mallocgc(t.size, t, false) 367 memmove(x, elem, t.size) 368 e._type = t 369 e.data = x 370 return 371 } 372 373 func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { 374 t := tab._type 375 if raceenabled { 376 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I)) 377 } 378 if msanenabled { 379 msanread(elem, t.size) 380 } 381 x := mallocgc(t.size, t, true) 382 typedmemmove(t, x, elem) 383 i.tab = tab 384 i.data = x 385 return 386 } 387 388 func convT2I16(tab *itab, val uint16) (i iface) { 389 t := tab._type 390 var x unsafe.Pointer 391 if val == 0 { 392 x = unsafe.Pointer(&zeroVal[0]) 393 } else { 394 x = mallocgc(2, t, false) 395 *(*uint16)(x) = val 396 } 397 i.tab = tab 398 i.data = x 399 return 400 } 401 402 func convT2I32(tab *itab, val uint32) (i iface) { 403 t := tab._type 404 var x unsafe.Pointer 405 if val == 0 { 406 x = unsafe.Pointer(&zeroVal[0]) 407 } else { 408 x = mallocgc(4, t, false) 409 *(*uint32)(x) = val 410 } 411 i.tab = tab 412 i.data = x 413 return 414 } 415 416 func convT2I64(tab *itab, val uint64) (i iface) { 417 t := tab._type 418 var x unsafe.Pointer 419 if val == 0 { 420 x = unsafe.Pointer(&zeroVal[0]) 421 } else { 422 x = mallocgc(8, t, false) 423 *(*uint64)(x) = val 424 } 425 i.tab = tab 426 i.data = x 427 return 428 } 429 430 func convT2Istring(tab *itab, val string) (i iface) { 431 t := tab._type 432 var x unsafe.Pointer 433 if val == "" { 434 x = unsafe.Pointer(&zeroVal[0]) 435 } else { 436 x = mallocgc(unsafe.Sizeof(val), t, true) 437 *(*string)(x) = val 438 } 439 i.tab = tab 440 i.data = x 441 return 442 } 443 444 func convT2Islice(tab *itab, val []byte) (i iface) { 445 // Note: this must work for any element type, not just byte. 446 t := tab._type 447 var x unsafe.Pointer 448 if (*slice)(unsafe.Pointer(&val)).array == nil { 449 x = unsafe.Pointer(&zeroVal[0]) 450 } else { 451 x = mallocgc(unsafe.Sizeof(val), t, true) 452 *(*[]byte)(x) = val 453 } 454 i.tab = tab 455 i.data = x 456 return 457 } 458 459 func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) { 460 t := tab._type 461 if raceenabled { 462 raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Inoptr)) 463 } 464 if msanenabled { 465 msanread(elem, t.size) 466 } 467 x := mallocgc(t.size, t, false) 468 memmove(x, elem, t.size) 469 i.tab = tab 470 i.data = x 471 return 472 } 473 474 func convI2I(inter *interfacetype, i iface) (r iface) { 475 tab := i.tab 476 if tab == nil { 477 return 478 } 479 if tab.inter == inter { 480 r.tab = tab 481 r.data = i.data 482 return 483 } 484 r.tab = getitab(inter, tab._type, false) 485 r.data = i.data 486 return 487 } 488 489 func assertI2I(inter *interfacetype, i iface) (r iface) { 490 tab := i.tab 491 if tab == nil { 492 // explicit conversions require non-nil interface value. 493 panic(&TypeAssertionError{nil, nil, &inter.typ, ""}) 494 } 495 if tab.inter == inter { 496 r.tab = tab 497 r.data = i.data 498 return 499 } 500 r.tab = getitab(inter, tab._type, false) 501 r.data = i.data 502 return 503 } 504 505 func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) { 506 tab := i.tab 507 if tab == nil { 508 return 509 } 510 if tab.inter != inter { 511 tab = getitab(inter, tab._type, true) 512 if tab == nil { 513 return 514 } 515 } 516 r.tab = tab 517 r.data = i.data 518 b = true 519 return 520 } 521 522 func assertE2I(inter *interfacetype, e eface) (r iface) { 523 t := e._type 524 if t == nil { 525 // explicit conversions require non-nil interface value. 526 panic(&TypeAssertionError{nil, nil, &inter.typ, ""}) 527 } 528 r.tab = getitab(inter, t, false) 529 r.data = e.data 530 return 531 } 532 533 func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) { 534 t := e._type 535 if t == nil { 536 return 537 } 538 tab := getitab(inter, t, true) 539 if tab == nil { 540 return 541 } 542 r.tab = tab 543 r.data = e.data 544 b = true 545 return 546 } 547 548 //go:linkname reflect_ifaceE2I reflect.ifaceE2I 549 func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) { 550 *dst = assertE2I(inter, e) 551 } 552 553 func iterate_itabs(fn func(*itab)) { 554 // Note: only runs during stop the world or with itabLock held, 555 // so no other locks/atomics needed. 556 t := itabTable 557 for i := uintptr(0); i < t.size; i++ { 558 m := *(**itab)(add(unsafe.Pointer(&t.entries), i*sys.PtrSize)) 559 if m != nil { 560 fn(m) 561 } 562 } 563 } 564 565 // staticbytes is used to avoid convT2E for byte-sized values. 566 var staticbytes = [...]byte{ 567 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 568 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 569 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 570 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 571 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 572 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 573 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 574 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 575 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 576 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 577 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 578 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 579 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 580 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 581 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 582 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 583 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 584 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 585 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 586 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 587 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 588 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 589 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 590 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 591 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 592 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 593 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 594 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 595 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 596 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 597 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 598 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 599 }