github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/iface.c (about) 1 // Copyright 2009 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 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "type.h" 8 #include "typekind.h" 9 #include "malloc.h" 10 #include "../../cmd/ld/textflag.h" 11 12 void 13 runtime·printiface(Iface i) 14 { 15 runtime·printf("(%p,%p)", i.tab, i.data); 16 } 17 18 void 19 runtime·printeface(Eface e) 20 { 21 runtime·printf("(%p,%p)", e.type, e.data); 22 } 23 24 static Itab* hash[1009]; 25 static Lock ifacelock; 26 27 static Itab* 28 itab(InterfaceType *inter, Type *type, int32 canfail) 29 { 30 int32 locked; 31 int32 ni; 32 Method *t, *et; 33 IMethod *i, *ei; 34 uint32 h; 35 String *iname, *ipkgPath; 36 Itab *m; 37 UncommonType *x; 38 Type *itype; 39 Eface err; 40 41 if(inter->mhdr.len == 0) 42 runtime·throw("internal error - misuse of itab"); 43 44 locked = 0; 45 46 // easy case 47 x = type->x; 48 if(x == nil) { 49 if(canfail) 50 return nil; 51 iname = inter->m[0].name; 52 goto throw; 53 } 54 55 // compiler has provided some good hash codes for us. 56 h = inter->hash; 57 h += 17 * type->hash; 58 // TODO(rsc): h += 23 * x->mhash ? 59 h %= nelem(hash); 60 61 // look twice - once without lock, once with. 62 // common case will be no lock contention. 63 for(locked=0; locked<2; locked++) { 64 if(locked) 65 runtime·lock(&ifacelock); 66 for(m=runtime·atomicloadp(&hash[h]); m!=nil; m=m->link) { 67 if(m->inter == inter && m->type == type) { 68 if(m->bad) { 69 m = nil; 70 if(!canfail) { 71 // this can only happen if the conversion 72 // was already done once using the , ok form 73 // and we have a cached negative result. 74 // the cached result doesn't record which 75 // interface function was missing, so jump 76 // down to the interface check, which will 77 // do more work but give a better error. 78 goto search; 79 } 80 } 81 if(locked) 82 runtime·unlock(&ifacelock); 83 return m; 84 } 85 } 86 } 87 88 ni = inter->mhdr.len; 89 m = runtime·persistentalloc(sizeof(*m) + ni*sizeof m->fun[0], 0, &mstats.other_sys); 90 m->inter = inter; 91 m->type = type; 92 93 search: 94 // both inter and type have method sorted by name, 95 // and interface names are unique, 96 // so can iterate over both in lock step; 97 // the loop is O(ni+nt) not O(ni*nt). 98 i = inter->m; 99 ei = i + inter->mhdr.len; 100 t = x->m; 101 et = t + x->mhdr.len; 102 for(; i < ei; i++) { 103 itype = i->type; 104 iname = i->name; 105 ipkgPath = i->pkgPath; 106 for(;; t++) { 107 if(t >= et) { 108 if(!canfail) { 109 throw: 110 // didn't find method 111 runtime·newTypeAssertionError( 112 nil, type->string, inter->string, 113 iname, &err); 114 if(locked) 115 runtime·unlock(&ifacelock); 116 runtime·panic(err); 117 return nil; // not reached 118 } 119 m->bad = 1; 120 goto out; 121 } 122 if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath) 123 break; 124 } 125 if(m) 126 m->fun[i - inter->m] = t->ifn; 127 } 128 129 out: 130 if(!locked) 131 runtime·panicstring("invalid itab locking"); 132 m->link = hash[h]; 133 runtime·atomicstorep(&hash[h], m); 134 runtime·unlock(&ifacelock); 135 if(m->bad) 136 return nil; 137 return m; 138 } 139 140 static void 141 copyin(Type *t, void *src, void **dst) 142 { 143 uintptr size; 144 void *p; 145 Alg *alg; 146 147 size = t->size; 148 alg = t->alg; 149 150 if(size <= sizeof(*dst)) 151 alg->copy(size, dst, src); 152 else { 153 p = runtime·mal(size); 154 alg->copy(size, p, src); 155 *dst = p; 156 } 157 } 158 159 static void 160 copyout(Type *t, void **src, void *dst) 161 { 162 uintptr size; 163 Alg *alg; 164 165 size = t->size; 166 alg = t->alg; 167 168 if(size <= sizeof(*src)) 169 alg->copy(size, dst, src); 170 else 171 alg->copy(size, dst, *src); 172 } 173 174 #pragma textflag NOSPLIT 175 void 176 runtime·typ2Itab(Type *t, InterfaceType *inter, Itab **cache, Itab *ret) 177 { 178 Itab *tab; 179 180 tab = itab(inter, t, 0); 181 runtime·atomicstorep(cache, tab); 182 ret = tab; 183 FLUSH(&ret); 184 } 185 186 // func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any) 187 #pragma textflag NOSPLIT 188 void 189 runtime·convT2I(Type *t, InterfaceType *inter, Itab **cache, ...) 190 { 191 byte *elem; 192 Iface *ret; 193 Itab *tab; 194 int32 wid; 195 196 elem = (byte*)(&cache+1); 197 wid = t->size; 198 ret = (Iface*)(elem + ROUND(wid, Structrnd)); 199 tab = runtime·atomicloadp(cache); 200 if(!tab) { 201 tab = itab(inter, t, 0); 202 runtime·atomicstorep(cache, tab); 203 } 204 ret->tab = tab; 205 copyin(t, elem, &ret->data); 206 } 207 208 // func convT2E(typ *byte, elem any) (ret any) 209 #pragma textflag NOSPLIT 210 void 211 runtime·convT2E(Type *t, ...) 212 { 213 byte *elem; 214 Eface *ret; 215 int32 wid; 216 217 elem = (byte*)(&t+1); 218 wid = t->size; 219 ret = (Eface*)(elem + ROUND(wid, Structrnd)); 220 ret->type = t; 221 copyin(t, elem, &ret->data); 222 } 223 224 static void assertI2Tret(Type *t, Iface i, byte *ret); 225 226 // func ifaceI2T(typ *byte, iface any) (ret any) 227 #pragma textflag NOSPLIT 228 void 229 runtime·assertI2T(Type *t, Iface i, ...) 230 { 231 byte *ret; 232 233 ret = (byte*)(&i+1); 234 assertI2Tret(t, i, ret); 235 } 236 237 static void 238 assertI2Tret(Type *t, Iface i, byte *ret) 239 { 240 Itab *tab; 241 Eface err; 242 243 tab = i.tab; 244 if(tab == nil) { 245 runtime·newTypeAssertionError( 246 nil, nil, t->string, 247 nil, &err); 248 runtime·panic(err); 249 } 250 if(tab->type != t) { 251 runtime·newTypeAssertionError( 252 tab->inter->string, tab->type->string, t->string, 253 nil, &err); 254 runtime·panic(err); 255 } 256 copyout(t, &i.data, ret); 257 } 258 259 // func ifaceI2T2(typ *byte, iface any) (ret any, ok bool) 260 #pragma textflag NOSPLIT 261 void 262 runtime·assertI2T2(Type *t, Iface i, ...) 263 { 264 byte *ret; 265 bool *ok; 266 int32 wid; 267 268 ret = (byte*)(&i+1); 269 wid = t->size; 270 ok = (bool*)(ret + wid); 271 272 if(i.tab == nil || i.tab->type != t) { 273 *ok = false; 274 runtime·memclr(ret, wid); 275 return; 276 } 277 278 *ok = true; 279 copyout(t, &i.data, ret); 280 } 281 282 void 283 runtime·assertI2TOK(Type *t, Iface i, bool ok) 284 { 285 ok = i.tab!=nil && i.tab->type==t; 286 FLUSH(&ok); 287 } 288 289 static void assertE2Tret(Type *t, Eface e, byte *ret); 290 291 // func ifaceE2T(typ *byte, iface any) (ret any) 292 #pragma textflag NOSPLIT 293 void 294 runtime·assertE2T(Type *t, Eface e, ...) 295 { 296 byte *ret; 297 298 ret = (byte*)(&e+1); 299 assertE2Tret(t, e, ret); 300 } 301 302 static void 303 assertE2Tret(Type *t, Eface e, byte *ret) 304 { 305 Eface err; 306 307 if(e.type == nil) { 308 runtime·newTypeAssertionError( 309 nil, nil, t->string, 310 nil, &err); 311 runtime·panic(err); 312 } 313 if(e.type != t) { 314 runtime·newTypeAssertionError( 315 nil, e.type->string, t->string, 316 nil, &err); 317 runtime·panic(err); 318 } 319 copyout(t, &e.data, ret); 320 } 321 322 // func ifaceE2T2(sigt *byte, iface any) (ret any, ok bool); 323 #pragma textflag NOSPLIT 324 void 325 runtime·assertE2T2(Type *t, Eface e, ...) 326 { 327 byte *ret; 328 bool *ok; 329 int32 wid; 330 331 ret = (byte*)(&e+1); 332 wid = t->size; 333 ok = (bool*)(ret + wid); 334 335 if(t != e.type) { 336 *ok = false; 337 runtime·memclr(ret, wid); 338 return; 339 } 340 341 *ok = true; 342 copyout(t, &e.data, ret); 343 } 344 345 void 346 runtime·assertE2TOK(Type *t, Eface e, bool ok) 347 { 348 ok = t==e.type; 349 FLUSH(&ok); 350 } 351 352 // func convI2E(elem any) (ret any) 353 void 354 runtime·convI2E(Iface i, Eface ret) 355 { 356 Itab *tab; 357 358 ret.data = i.data; 359 if((tab = i.tab) == nil) 360 ret.type = nil; 361 else 362 ret.type = tab->type; 363 FLUSH(&ret); 364 } 365 366 // func ifaceI2E(typ *byte, iface any) (ret any) 367 void 368 runtime·assertI2E(InterfaceType* inter, Iface i, Eface ret) 369 { 370 Itab *tab; 371 Eface err; 372 373 tab = i.tab; 374 if(tab == nil) { 375 // explicit conversions require non-nil interface value. 376 runtime·newTypeAssertionError( 377 nil, nil, inter->string, 378 nil, &err); 379 runtime·panic(err); 380 } 381 ret.data = i.data; 382 ret.type = tab->type; 383 FLUSH(&ret); 384 } 385 386 // func ifaceI2E2(typ *byte, iface any) (ret any, ok bool) 387 void 388 runtime·assertI2E2(InterfaceType* inter, Iface i, Eface ret, bool ok) 389 { 390 Itab *tab; 391 392 USED(inter); 393 tab = i.tab; 394 if(tab == nil) { 395 ret.type = nil; 396 ok = 0; 397 } else { 398 ret.type = tab->type; 399 ok = 1; 400 } 401 ret.data = i.data; 402 FLUSH(&ret); 403 FLUSH(&ok); 404 } 405 406 // func convI2I(typ *byte, elem any) (ret any) 407 void 408 runtime·convI2I(InterfaceType* inter, Iface i, Iface ret) 409 { 410 Itab *tab; 411 412 ret.data = i.data; 413 if((tab = i.tab) == nil) 414 ret.tab = nil; 415 else if(tab->inter == inter) 416 ret.tab = tab; 417 else 418 ret.tab = itab(inter, tab->type, 0); 419 FLUSH(&ret); 420 } 421 422 void 423 runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret) 424 { 425 Itab *tab; 426 Eface err; 427 428 tab = i.tab; 429 if(tab == nil) { 430 // explicit conversions require non-nil interface value. 431 runtime·newTypeAssertionError( 432 nil, nil, inter->string, 433 nil, &err); 434 runtime·panic(err); 435 } 436 ret->data = i.data; 437 ret->tab = itab(inter, tab->type, 0); 438 } 439 440 // func ifaceI2I(sigi *byte, iface any) (ret any) 441 void 442 runtime·assertI2I(InterfaceType* inter, Iface i, Iface ret) 443 { 444 runtime·ifaceI2I(inter, i, &ret); 445 } 446 447 // func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool) 448 void 449 runtime·assertI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok) 450 { 451 Itab *tab; 452 453 tab = i.tab; 454 if(tab != nil && (tab->inter == inter || (tab = itab(inter, tab->type, 1)) != nil)) { 455 ret.data = i.data; 456 ret.tab = tab; 457 ok = 1; 458 } else { 459 ret.data = 0; 460 ret.tab = 0; 461 ok = 0; 462 } 463 FLUSH(&ret); 464 FLUSH(&ok); 465 } 466 467 void 468 runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret) 469 { 470 Type *t; 471 Eface err; 472 473 t = e.type; 474 if(t == nil) { 475 // explicit conversions require non-nil interface value. 476 runtime·newTypeAssertionError( 477 nil, nil, inter->string, 478 nil, &err); 479 runtime·panic(err); 480 } 481 ret->data = e.data; 482 ret->tab = itab(inter, t, 0); 483 } 484 485 bool 486 runtime·ifaceE2I2(InterfaceType *inter, Eface e, Iface *ret) 487 { 488 ret->tab = itab(inter, e.type, 1); 489 if(ret->tab == nil) 490 return false; 491 ret->data = e.data; 492 return true; 493 } 494 495 // For reflect 496 // func ifaceE2I(t *InterfaceType, e interface{}, dst *Iface) 497 void 498 reflect·ifaceE2I(InterfaceType *inter, Eface e, Iface *dst) 499 { 500 runtime·ifaceE2I(inter, e, dst); 501 } 502 503 // func ifaceE2I(sigi *byte, iface any) (ret any) 504 void 505 runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret) 506 { 507 runtime·ifaceE2I(inter, e, &ret); 508 } 509 510 // ifaceE2I2(sigi *byte, iface any) (ret any, ok bool) 511 void 512 runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok) 513 { 514 if(e.type == nil) { 515 ok = 0; 516 ret.data = nil; 517 ret.tab = nil; 518 } else if((ret.tab = itab(inter, e.type, 1)) == nil) { 519 ok = 0; 520 ret.data = nil; 521 } else { 522 ok = 1; 523 ret.data = e.data; 524 } 525 FLUSH(&ret); 526 FLUSH(&ok); 527 } 528 529 // func ifaceE2E(typ *byte, iface any) (ret any) 530 void 531 runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret) 532 { 533 Type *t; 534 Eface err; 535 536 t = e.type; 537 if(t == nil) { 538 // explicit conversions require non-nil interface value. 539 runtime·newTypeAssertionError( 540 nil, nil, inter->string, 541 nil, &err); 542 runtime·panic(err); 543 } 544 ret = e; 545 FLUSH(&ret); 546 } 547 548 // func ifaceE2E2(iface any) (ret any, ok bool) 549 void 550 runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok) 551 { 552 USED(inter); 553 ret = e; 554 ok = e.type != nil; 555 FLUSH(&ret); 556 FLUSH(&ok); 557 } 558 559 static uintptr 560 ifacehash1(void *data, Type *t, uintptr h) 561 { 562 Alg *alg; 563 uintptr size; 564 Eface err; 565 566 if(t == nil) 567 return 0; 568 569 alg = t->alg; 570 size = t->size; 571 if(alg->hash == runtime·nohash) { 572 // calling nohash will panic too, 573 // but we can print a better error. 574 runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err); 575 runtime·panic(err); 576 } 577 if(size <= sizeof(data)) 578 alg->hash(&h, size, &data); 579 else 580 alg->hash(&h, size, data); 581 return h; 582 } 583 584 uintptr 585 runtime·ifacehash(Iface a, uintptr h) 586 { 587 if(a.tab == nil) 588 return h; 589 return ifacehash1(a.data, a.tab->type, h); 590 } 591 592 uintptr 593 runtime·efacehash(Eface a, uintptr h) 594 { 595 return ifacehash1(a.data, a.type, h); 596 } 597 598 static bool 599 ifaceeq1(void *data1, void *data2, Type *t) 600 { 601 uintptr size; 602 Alg *alg; 603 Eface err; 604 bool eq; 605 606 alg = t->alg; 607 size = t->size; 608 609 if(alg->equal == runtime·noequal) { 610 // calling noequal will panic too, 611 // but we can print a better error. 612 runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err); 613 runtime·panic(err); 614 } 615 616 eq = 0; 617 if(size <= sizeof(data1)) 618 alg->equal(&eq, size, &data1, &data2); 619 else 620 alg->equal(&eq, size, data1, data2); 621 return eq; 622 } 623 624 bool 625 runtime·ifaceeq_c(Iface i1, Iface i2) 626 { 627 if(i1.tab != i2.tab) 628 return false; 629 if(i1.tab == nil) 630 return true; 631 return ifaceeq1(i1.data, i2.data, i1.tab->type); 632 } 633 634 bool 635 runtime·efaceeq_c(Eface e1, Eface e2) 636 { 637 if(e1.type != e2.type) 638 return false; 639 if(e1.type == nil) 640 return true; 641 return ifaceeq1(e1.data, e2.data, e1.type); 642 } 643 644 // ifaceeq(i1 any, i2 any) (ret bool); 645 void 646 runtime·ifaceeq(Iface i1, Iface i2, bool ret) 647 { 648 ret = runtime·ifaceeq_c(i1, i2); 649 FLUSH(&ret); 650 } 651 652 // efaceeq(i1 any, i2 any) (ret bool) 653 void 654 runtime·efaceeq(Eface e1, Eface e2, bool ret) 655 { 656 ret = runtime·efaceeq_c(e1, e2); 657 FLUSH(&ret); 658 } 659 660 // ifacethash(i1 any) (ret uint32); 661 void 662 runtime·ifacethash(Iface i1, uint32 ret) 663 { 664 Itab *tab; 665 666 ret = 0; 667 tab = i1.tab; 668 if(tab != nil) 669 ret = tab->type->hash; 670 FLUSH(&ret); 671 } 672 673 // efacethash(e1 any) (ret uint32) 674 void 675 runtime·efacethash(Eface e1, uint32 ret) 676 { 677 Type *t; 678 679 ret = 0; 680 t = e1.type; 681 if(t != nil) 682 ret = t->hash; 683 FLUSH(&ret); 684 } 685 686 void 687 reflect·unsafe_Typeof(Eface e, Eface ret) 688 { 689 if(e.type == nil) { 690 ret.type = nil; 691 ret.data = nil; 692 } else { 693 ret = *(Eface*)(e.type); 694 } 695 FLUSH(&ret); 696 } 697 698 void 699 reflect·unsafe_New(Type *t, void *ret) 700 { 701 ret = runtime·cnew(t); 702 FLUSH(&ret); 703 } 704 705 void 706 reflect·unsafe_NewArray(Type *t, intgo n, void *ret) 707 { 708 ret = runtime·cnewarray(t, n); 709 FLUSH(&ret); 710 } 711 712 void 713 reflect·typelinks(Slice ret) 714 { 715 extern Type *typelink[], *etypelink[]; 716 static int32 first = 1; 717 ret.array = (byte*)typelink; 718 ret.len = etypelink - typelink; 719 ret.cap = ret.len; 720 FLUSH(&ret); 721 }