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