github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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 ( 14 hashSize = 1009 15 ) 16 17 var ( 18 ifaceLock mutex // lock for accessing hash 19 hash [hashSize]*itab 20 ) 21 22 func itabhash(inter *interfacetype, typ *_type) uint32 { 23 // compiler has provided some good hash codes for us. 24 h := inter.typ.hash 25 h += 17 * typ.hash 26 // TODO(rsc): h += 23 * x.mhash ? 27 return h % hashSize 28 } 29 30 func getitab(inter *interfacetype, typ *_type, canfail bool) *itab { 31 if len(inter.mhdr) == 0 { 32 throw("internal error - misuse of itab") 33 } 34 35 // easy case 36 if typ.tflag&tflagUncommon == 0 { 37 if canfail { 38 return nil 39 } 40 name := inter.typ.nameOff(inter.mhdr[0].name) 41 panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), name.name()}) 42 } 43 44 h := itabhash(inter, typ) 45 46 // look twice - once without lock, once with. 47 // common case will be no lock contention. 48 var m *itab 49 var locked int 50 for locked = 0; locked < 2; locked++ { 51 if locked != 0 { 52 lock(&ifaceLock) 53 } 54 for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link { 55 if m.inter == inter && m._type == typ { 56 if m.bad { 57 if !canfail { 58 // this can only happen if the conversion 59 // was already done once using the , ok form 60 // and we have a cached negative result. 61 // the cached result doesn't record which 62 // interface function was missing, so try 63 // adding the itab again, which will throw an error. 64 additab(m, locked != 0, false) 65 } 66 m = nil 67 } 68 if locked != 0 { 69 unlock(&ifaceLock) 70 } 71 return m 72 } 73 } 74 } 75 76 m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys)) 77 m.inter = inter 78 m._type = typ 79 additab(m, true, canfail) 80 unlock(&ifaceLock) 81 if m.bad { 82 return nil 83 } 84 return m 85 } 86 87 func additab(m *itab, locked, canfail bool) { 88 inter := m.inter 89 typ := m._type 90 x := typ.uncommon() 91 92 // both inter and typ have method sorted by name, 93 // and interface names are unique, 94 // so can iterate over both in lock step; 95 // the loop is O(ni+nt) not O(ni*nt). 96 ni := len(inter.mhdr) 97 nt := int(x.mcount) 98 xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt] 99 j := 0 100 for k := 0; k < ni; k++ { 101 i := &inter.mhdr[k] 102 itype := inter.typ.typeOff(i.ityp) 103 name := inter.typ.nameOff(i.name) 104 iname := name.name() 105 ipkg := name.pkgPath() 106 if ipkg == "" { 107 ipkg = inter.pkgpath.name() 108 } 109 for ; j < nt; j++ { 110 t := &xmhdr[j] 111 tname := typ.nameOff(t.name) 112 if typ.typeOff(t.mtyp) == itype && tname.name() == iname { 113 pkgPath := tname.pkgPath() 114 if pkgPath == "" { 115 pkgPath = typ.nameOff(x.pkgpath).name() 116 } 117 if tname.isExported() || pkgPath == ipkg { 118 if m != nil { 119 ifn := typ.textOff(t.ifn) 120 *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn 121 } 122 goto nextimethod 123 } 124 } 125 } 126 // didn't find method 127 if !canfail { 128 if locked { 129 unlock(&ifaceLock) 130 } 131 panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), iname}) 132 } 133 m.bad = true 134 break 135 nextimethod: 136 } 137 if !locked { 138 throw("invalid itab locking") 139 } 140 h := itabhash(inter, typ) 141 m.link = hash[h] 142 m.inhash = true 143 atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m)) 144 } 145 146 func itabsinit() { 147 lock(&ifaceLock) 148 for _, md := range activeModules() { 149 for _, i := range md.itablinks { 150 // itablinks is a slice of pointers to the itabs used in this 151 // module. A given itab may be used in more than one module 152 // and thanks to the way global symbol resolution works, the 153 // pointed-to itab may already have been inserted into the 154 // global 'hash'. 155 if !i.inhash { 156 additab(i, true, false) 157 } 158 } 159 } 160 unlock(&ifaceLock) 161 } 162 163 // panicdottypeE is called when doing an e.(T) conversion and the conversion fails. 164 // have = the dynamic type we have. 165 // want = the static type we're trying to convert to. 166 // iface = the static type we're converting from. 167 func panicdottypeE(have, want, iface *_type) { 168 haveString := "" 169 if have != nil { 170 haveString = have.string() 171 } 172 panic(&TypeAssertionError{iface.string(), haveString, want.string(), ""}) 173 } 174 175 // panicdottypeI is called when doing an i.(T) conversion and the conversion fails. 176 // Same args as panicdottypeE, but "have" is the dynamic itab we have. 177 func panicdottypeI(have *itab, want, iface *_type) { 178 var t *_type 179 if have != nil { 180 t = have._type 181 } 182 panicdottypeE(t, want, iface) 183 } 184 185 // panicnildottype is called when doing a i.(T) conversion and the interface i is nil. 186 // want = the static type we're trying to convert to. 187 func panicnildottype(want *_type) { 188 panic(&TypeAssertionError{"", "", want.string(), ""}) 189 // TODO: Add the static type we're converting from as well. 190 // It might generate a better error message. 191 // Just to match other nil conversion errors, we don't for now. 192 } 193 194 // The conv and assert functions below do very similar things. 195 // The convXXX functions are guaranteed by the compiler to succeed. 196 // The assertXXX functions may fail (either panicking or returning false, 197 // depending on whether they are 1-result or 2-result). 198 // The convXXX functions succeed on a nil input, whereas the assertXXX 199 // functions fail on a nil input. 200 201 func convT2E(t *_type, elem unsafe.Pointer) (e eface) { 202 if raceenabled { 203 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E)) 204 } 205 if msanenabled { 206 msanread(elem, t.size) 207 } 208 x := mallocgc(t.size, t, true) 209 // TODO: We allocate a zeroed object only to overwrite it with actual data. 210 // Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice. 211 typedmemmove(t, x, elem) 212 e._type = t 213 e.data = x 214 return 215 } 216 217 func convT2E16(t *_type, elem unsafe.Pointer) (e eface) { 218 if raceenabled { 219 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E16)) 220 } 221 if msanenabled { 222 msanread(elem, t.size) 223 } 224 var x unsafe.Pointer 225 if *(*uint16)(elem) == 0 { 226 x = unsafe.Pointer(&zeroVal[0]) 227 } else { 228 x = mallocgc(2, t, false) 229 *(*uint16)(x) = *(*uint16)(elem) 230 } 231 e._type = t 232 e.data = x 233 return 234 } 235 236 func convT2E32(t *_type, elem unsafe.Pointer) (e eface) { 237 if raceenabled { 238 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E32)) 239 } 240 if msanenabled { 241 msanread(elem, t.size) 242 } 243 var x unsafe.Pointer 244 if *(*uint32)(elem) == 0 { 245 x = unsafe.Pointer(&zeroVal[0]) 246 } else { 247 x = mallocgc(4, t, false) 248 *(*uint32)(x) = *(*uint32)(elem) 249 } 250 e._type = t 251 e.data = x 252 return 253 } 254 255 func convT2E64(t *_type, elem unsafe.Pointer) (e eface) { 256 if raceenabled { 257 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E64)) 258 } 259 if msanenabled { 260 msanread(elem, t.size) 261 } 262 var x unsafe.Pointer 263 if *(*uint64)(elem) == 0 { 264 x = unsafe.Pointer(&zeroVal[0]) 265 } else { 266 x = mallocgc(8, t, false) 267 *(*uint64)(x) = *(*uint64)(elem) 268 } 269 e._type = t 270 e.data = x 271 return 272 } 273 274 func convT2Estring(t *_type, elem unsafe.Pointer) (e eface) { 275 if raceenabled { 276 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Estring)) 277 } 278 if msanenabled { 279 msanread(elem, t.size) 280 } 281 var x unsafe.Pointer 282 if *(*string)(elem) == "" { 283 x = unsafe.Pointer(&zeroVal[0]) 284 } else { 285 x = mallocgc(t.size, t, true) 286 *(*string)(x) = *(*string)(elem) 287 } 288 e._type = t 289 e.data = x 290 return 291 } 292 293 func convT2Eslice(t *_type, elem unsafe.Pointer) (e eface) { 294 if raceenabled { 295 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Eslice)) 296 } 297 if msanenabled { 298 msanread(elem, t.size) 299 } 300 var x unsafe.Pointer 301 if v := *(*slice)(elem); uintptr(v.array) == 0 { 302 x = unsafe.Pointer(&zeroVal[0]) 303 } else { 304 x = mallocgc(t.size, t, true) 305 *(*slice)(x) = *(*slice)(elem) 306 } 307 e._type = t 308 e.data = x 309 return 310 } 311 312 func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { 313 if raceenabled { 314 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Enoptr)) 315 } 316 if msanenabled { 317 msanread(elem, t.size) 318 } 319 x := mallocgc(t.size, t, false) 320 memmove(x, elem, t.size) 321 e._type = t 322 e.data = x 323 return 324 } 325 326 func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { 327 t := tab._type 328 if raceenabled { 329 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I)) 330 } 331 if msanenabled { 332 msanread(elem, t.size) 333 } 334 x := mallocgc(t.size, t, true) 335 typedmemmove(t, x, elem) 336 i.tab = tab 337 i.data = x 338 return 339 } 340 341 func convT2I16(tab *itab, elem unsafe.Pointer) (i iface) { 342 t := tab._type 343 if raceenabled { 344 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I16)) 345 } 346 if msanenabled { 347 msanread(elem, t.size) 348 } 349 var x unsafe.Pointer 350 if *(*uint16)(elem) == 0 { 351 x = unsafe.Pointer(&zeroVal[0]) 352 } else { 353 x = mallocgc(2, t, false) 354 *(*uint16)(x) = *(*uint16)(elem) 355 } 356 i.tab = tab 357 i.data = x 358 return 359 } 360 361 func convT2I32(tab *itab, elem unsafe.Pointer) (i iface) { 362 t := tab._type 363 if raceenabled { 364 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I32)) 365 } 366 if msanenabled { 367 msanread(elem, t.size) 368 } 369 var x unsafe.Pointer 370 if *(*uint32)(elem) == 0 { 371 x = unsafe.Pointer(&zeroVal[0]) 372 } else { 373 x = mallocgc(4, t, false) 374 *(*uint32)(x) = *(*uint32)(elem) 375 } 376 i.tab = tab 377 i.data = x 378 return 379 } 380 381 func convT2I64(tab *itab, elem unsafe.Pointer) (i iface) { 382 t := tab._type 383 if raceenabled { 384 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I64)) 385 } 386 if msanenabled { 387 msanread(elem, t.size) 388 } 389 var x unsafe.Pointer 390 if *(*uint64)(elem) == 0 { 391 x = unsafe.Pointer(&zeroVal[0]) 392 } else { 393 x = mallocgc(8, t, false) 394 *(*uint64)(x) = *(*uint64)(elem) 395 } 396 i.tab = tab 397 i.data = x 398 return 399 } 400 401 func convT2Istring(tab *itab, elem unsafe.Pointer) (i iface) { 402 t := tab._type 403 if raceenabled { 404 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Istring)) 405 } 406 if msanenabled { 407 msanread(elem, t.size) 408 } 409 var x unsafe.Pointer 410 if *(*string)(elem) == "" { 411 x = unsafe.Pointer(&zeroVal[0]) 412 } else { 413 x = mallocgc(t.size, t, true) 414 *(*string)(x) = *(*string)(elem) 415 } 416 i.tab = tab 417 i.data = x 418 return 419 } 420 421 func convT2Islice(tab *itab, elem unsafe.Pointer) (i iface) { 422 t := tab._type 423 if raceenabled { 424 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Islice)) 425 } 426 if msanenabled { 427 msanread(elem, t.size) 428 } 429 var x unsafe.Pointer 430 if v := *(*slice)(elem); uintptr(v.array) == 0 { 431 x = unsafe.Pointer(&zeroVal[0]) 432 } else { 433 x = mallocgc(t.size, t, true) 434 *(*slice)(x) = *(*slice)(elem) 435 } 436 i.tab = tab 437 i.data = x 438 return 439 } 440 441 func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) { 442 t := tab._type 443 if raceenabled { 444 raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Inoptr)) 445 } 446 if msanenabled { 447 msanread(elem, t.size) 448 } 449 x := mallocgc(t.size, t, false) 450 memmove(x, elem, t.size) 451 i.tab = tab 452 i.data = x 453 return 454 } 455 456 func convI2I(inter *interfacetype, i iface) (r iface) { 457 tab := i.tab 458 if tab == nil { 459 return 460 } 461 if tab.inter == inter { 462 r.tab = tab 463 r.data = i.data 464 return 465 } 466 r.tab = getitab(inter, tab._type, false) 467 r.data = i.data 468 return 469 } 470 471 func assertI2I(inter *interfacetype, i iface) (r iface) { 472 tab := i.tab 473 if tab == nil { 474 // explicit conversions require non-nil interface value. 475 panic(&TypeAssertionError{"", "", inter.typ.string(), ""}) 476 } 477 if tab.inter == inter { 478 r.tab = tab 479 r.data = i.data 480 return 481 } 482 r.tab = getitab(inter, tab._type, false) 483 r.data = i.data 484 return 485 } 486 487 func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) { 488 tab := i.tab 489 if tab == nil { 490 return 491 } 492 if tab.inter != inter { 493 tab = getitab(inter, tab._type, true) 494 if tab == nil { 495 return 496 } 497 } 498 r.tab = tab 499 r.data = i.data 500 b = true 501 return 502 } 503 504 func assertE2I(inter *interfacetype, e eface) (r iface) { 505 t := e._type 506 if t == nil { 507 // explicit conversions require non-nil interface value. 508 panic(&TypeAssertionError{"", "", inter.typ.string(), ""}) 509 } 510 r.tab = getitab(inter, t, false) 511 r.data = e.data 512 return 513 } 514 515 func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) { 516 t := e._type 517 if t == nil { 518 return 519 } 520 tab := getitab(inter, t, true) 521 if tab == nil { 522 return 523 } 524 r.tab = tab 525 r.data = e.data 526 b = true 527 return 528 } 529 530 //go:linkname reflect_ifaceE2I reflect.ifaceE2I 531 func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) { 532 *dst = assertE2I(inter, e) 533 } 534 535 func iterate_itabs(fn func(*itab)) { 536 for _, h := range &hash { 537 for ; h != nil; h = h.link { 538 fn(h) 539 } 540 } 541 } 542 543 // staticbytes is used to avoid convT2E for byte-sized values. 544 var staticbytes = [...]byte{ 545 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 546 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 547 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 548 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 549 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 550 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 551 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 552 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 553 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 554 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 555 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 556 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 557 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 558 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 559 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 560 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 561 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 562 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 563 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 564 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 565 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 566 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 567 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 568 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 569 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 570 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 571 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 572 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 573 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 574 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 575 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 576 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 577 }