github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/type.go (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 // Runtime type representation. 6 7 package runtime 8 9 import ( 10 "internal/abi" 11 "unsafe" 12 ) 13 14 // tflag is documented in reflect/type.go. 15 // 16 // tflag values must be kept in sync with copies in: 17 // 18 // cmd/compile/internal/reflectdata/reflect.go 19 // cmd/link/internal/ld/decodesym.go 20 // reflect/type.go 21 // internal/reflectlite/type.go 22 type tflag uint8 23 24 const ( 25 tflagUncommon tflag = 1 << 0 26 tflagExtraStar tflag = 1 << 1 27 tflagNamed tflag = 1 << 2 28 tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes 29 ) 30 31 // Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize, 32 // ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and 33 // ../reflect/type.go:/^type.rtype. 34 // ../internal/reflectlite/type.go:/^type.rtype. 35 type _type struct { 36 size uintptr 37 ptrdata uintptr // size of memory prefix holding all pointers 38 hash uint32 39 tflag tflag 40 align uint8 41 fieldAlign uint8 42 kind uint8 43 // function for comparing objects of this type 44 // (ptr to object A, ptr to object B) -> ==? 45 equal func(unsafe.Pointer, unsafe.Pointer) bool 46 // gcdata stores the GC type data for the garbage collector. 47 // If the KindGCProg bit is set in kind, gcdata is a GC program. 48 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 49 gcdata *byte 50 str nameOff 51 ptrToThis typeOff 52 } 53 54 func (t *_type) string() string { 55 s := t.nameOff(t.str).name() 56 if t.tflag&tflagExtraStar != 0 { 57 return s[1:] 58 } 59 return s 60 } 61 62 func (t *_type) uncommon() *uncommontype { 63 if t.tflag&tflagUncommon == 0 { 64 return nil 65 } 66 switch t.kind & kindMask { 67 case kindStruct: 68 type u struct { 69 structtype 70 u uncommontype 71 } 72 return &(*u)(unsafe.Pointer(t)).u 73 case kindPtr: 74 type u struct { 75 ptrtype 76 u uncommontype 77 } 78 return &(*u)(unsafe.Pointer(t)).u 79 case kindFunc: 80 type u struct { 81 functype 82 u uncommontype 83 } 84 return &(*u)(unsafe.Pointer(t)).u 85 case kindSlice: 86 type u struct { 87 slicetype 88 u uncommontype 89 } 90 return &(*u)(unsafe.Pointer(t)).u 91 case kindArray: 92 type u struct { 93 arraytype 94 u uncommontype 95 } 96 return &(*u)(unsafe.Pointer(t)).u 97 case kindChan: 98 type u struct { 99 chantype 100 u uncommontype 101 } 102 return &(*u)(unsafe.Pointer(t)).u 103 case kindMap: 104 type u struct { 105 maptype 106 u uncommontype 107 } 108 return &(*u)(unsafe.Pointer(t)).u 109 case kindInterface: 110 type u struct { 111 interfacetype 112 u uncommontype 113 } 114 return &(*u)(unsafe.Pointer(t)).u 115 default: 116 type u struct { 117 _type 118 u uncommontype 119 } 120 return &(*u)(unsafe.Pointer(t)).u 121 } 122 } 123 124 func (t *_type) name() string { 125 if t.tflag&tflagNamed == 0 { 126 return "" 127 } 128 s := t.string() 129 i := len(s) - 1 130 sqBrackets := 0 131 for i >= 0 && (s[i] != '.' || sqBrackets != 0) { 132 switch s[i] { 133 case ']': 134 sqBrackets++ 135 case '[': 136 sqBrackets-- 137 } 138 i-- 139 } 140 return s[i+1:] 141 } 142 143 // pkgpath returns the path of the package where t was defined, if 144 // available. This is not the same as the reflect package's PkgPath 145 // method, in that it returns the package path for struct and interface 146 // types, not just named types. 147 func (t *_type) pkgpath() string { 148 if u := t.uncommon(); u != nil { 149 return t.nameOff(u.pkgpath).name() 150 } 151 switch t.kind & kindMask { 152 case kindStruct: 153 st := (*structtype)(unsafe.Pointer(t)) 154 return st.pkgPath.name() 155 case kindInterface: 156 it := (*interfacetype)(unsafe.Pointer(t)) 157 return it.pkgpath.name() 158 } 159 return "" 160 } 161 162 // reflectOffs holds type offsets defined at run time by the reflect package. 163 // 164 // When a type is defined at run time, its *rtype data lives on the heap. 165 // There are a wide range of possible addresses the heap may use, that 166 // may not be representable as a 32-bit offset. Moreover the GC may 167 // one day start moving heap memory, in which case there is no stable 168 // offset that can be defined. 169 // 170 // To provide stable offsets, we add pin *rtype objects in a global map 171 // and treat the offset as an identifier. We use negative offsets that 172 // do not overlap with any compile-time module offsets. 173 // 174 // Entries are created by reflect.addReflectOff. 175 var reflectOffs struct { 176 lock mutex 177 next int32 178 m map[int32]unsafe.Pointer 179 minv map[unsafe.Pointer]int32 180 } 181 182 func reflectOffsLock() { 183 lock(&reflectOffs.lock) 184 if raceenabled { 185 raceacquire(unsafe.Pointer(&reflectOffs.lock)) 186 } 187 } 188 189 func reflectOffsUnlock() { 190 if raceenabled { 191 racerelease(unsafe.Pointer(&reflectOffs.lock)) 192 } 193 unlock(&reflectOffs.lock) 194 } 195 196 func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name { 197 if off == 0 { 198 return name{} 199 } 200 base := uintptr(ptrInModule) 201 for md := &firstmoduledata; md != nil; md = md.next { 202 if base >= md.types && base < md.etypes { 203 res := md.types + uintptr(off) 204 if res > md.etypes { 205 println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes)) 206 throw("runtime: name offset out of range") 207 } 208 return name{(*byte)(unsafe.Pointer(res))} 209 } 210 } 211 212 // No module found. see if it is a run time name. 213 reflectOffsLock() 214 res, found := reflectOffs.m[int32(off)] 215 reflectOffsUnlock() 216 if !found { 217 println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:") 218 for next := &firstmoduledata; next != nil; next = next.next { 219 println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) 220 } 221 throw("runtime: name offset base pointer out of range") 222 } 223 return name{(*byte)(res)} 224 } 225 226 func (t *_type) nameOff(off nameOff) name { 227 return resolveNameOff(unsafe.Pointer(t), off) 228 } 229 230 func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type { 231 if off == 0 || off == -1 { 232 // -1 is the sentinel value for unreachable code. 233 // See cmd/link/internal/ld/data.go:relocsym. 234 return nil 235 } 236 base := uintptr(ptrInModule) 237 var md *moduledata 238 for next := &firstmoduledata; next != nil; next = next.next { 239 if base >= next.types && base < next.etypes { 240 md = next 241 break 242 } 243 } 244 if md == nil { 245 reflectOffsLock() 246 res := reflectOffs.m[int32(off)] 247 reflectOffsUnlock() 248 if res == nil { 249 println("runtime: typeOff", hex(off), "base", hex(base), "not in ranges:") 250 for next := &firstmoduledata; next != nil; next = next.next { 251 println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) 252 } 253 throw("runtime: type offset base pointer out of range") 254 } 255 return (*_type)(res) 256 } 257 if t := md.typemap[off]; t != nil { 258 return t 259 } 260 res := md.types + uintptr(off) 261 if res > md.etypes { 262 println("runtime: typeOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes)) 263 throw("runtime: type offset out of range") 264 } 265 return (*_type)(unsafe.Pointer(res)) 266 } 267 268 func (t *_type) typeOff(off typeOff) *_type { 269 return resolveTypeOff(unsafe.Pointer(t), off) 270 } 271 272 func (t *_type) textOff(off textOff) unsafe.Pointer { 273 if off == -1 { 274 // -1 is the sentinel value for unreachable code. 275 // See cmd/link/internal/ld/data.go:relocsym. 276 return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod)) 277 } 278 base := uintptr(unsafe.Pointer(t)) 279 var md *moduledata 280 for next := &firstmoduledata; next != nil; next = next.next { 281 if base >= next.types && base < next.etypes { 282 md = next 283 break 284 } 285 } 286 if md == nil { 287 reflectOffsLock() 288 res := reflectOffs.m[int32(off)] 289 reflectOffsUnlock() 290 if res == nil { 291 println("runtime: textOff", hex(off), "base", hex(base), "not in ranges:") 292 for next := &firstmoduledata; next != nil; next = next.next { 293 println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) 294 } 295 throw("runtime: text offset base pointer out of range") 296 } 297 return res 298 } 299 res := md.textAddr(uint32(off)) 300 return unsafe.Pointer(res) 301 } 302 303 func (t *functype) in() []*_type { 304 // See funcType in reflect/type.go for details on data layout. 305 uadd := uintptr(unsafe.Sizeof(functype{})) 306 if t.typ.tflag&tflagUncommon != 0 { 307 uadd += unsafe.Sizeof(uncommontype{}) 308 } 309 return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[:t.inCount] 310 } 311 312 func (t *functype) out() []*_type { 313 // See funcType in reflect/type.go for details on data layout. 314 uadd := uintptr(unsafe.Sizeof(functype{})) 315 if t.typ.tflag&tflagUncommon != 0 { 316 uadd += unsafe.Sizeof(uncommontype{}) 317 } 318 outCount := t.outCount & (1<<15 - 1) 319 return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount] 320 } 321 322 func (t *functype) dotdotdot() bool { 323 return t.outCount&(1<<15) != 0 324 } 325 326 type nameOff int32 327 type typeOff int32 328 type textOff int32 329 330 type method struct { 331 name nameOff 332 mtyp typeOff 333 ifn textOff 334 tfn textOff 335 } 336 337 type uncommontype struct { 338 pkgpath nameOff 339 mcount uint16 // number of methods 340 xcount uint16 // number of exported methods 341 moff uint32 // offset from this uncommontype to [mcount]method 342 _ uint32 // unused 343 } 344 345 type imethod struct { 346 name nameOff 347 ityp typeOff 348 } 349 350 type interfacetype struct { 351 typ _type 352 pkgpath name 353 mhdr []imethod 354 } 355 356 type maptype struct { 357 typ _type 358 key *_type 359 elem *_type 360 bucket *_type // internal type representing a hash bucket 361 // function for hashing keys (ptr to key, seed) -> hash 362 hasher func(unsafe.Pointer, uintptr) uintptr 363 keysize uint8 // size of key slot 364 elemsize uint8 // size of elem slot 365 bucketsize uint16 // size of bucket 366 flags uint32 367 } 368 369 // Note: flag values must match those used in the TMAP case 370 // in ../cmd/compile/internal/reflectdata/reflect.go:writeType. 371 func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself 372 return mt.flags&1 != 0 373 } 374 func (mt *maptype) indirectelem() bool { // store ptr to elem instead of elem itself 375 return mt.flags&2 != 0 376 } 377 func (mt *maptype) reflexivekey() bool { // true if k==k for all keys 378 return mt.flags&4 != 0 379 } 380 func (mt *maptype) needkeyupdate() bool { // true if we need to update key on an overwrite 381 return mt.flags&8 != 0 382 } 383 func (mt *maptype) hashMightPanic() bool { // true if hash function might panic 384 return mt.flags&16 != 0 385 } 386 387 type arraytype struct { 388 typ _type 389 elem *_type 390 slice *_type 391 len uintptr 392 } 393 394 type chantype struct { 395 typ _type 396 elem *_type 397 dir uintptr 398 } 399 400 type slicetype struct { 401 typ _type 402 elem *_type 403 } 404 405 type functype struct { 406 typ _type 407 inCount uint16 408 outCount uint16 409 } 410 411 type ptrtype struct { 412 typ _type 413 elem *_type 414 } 415 416 type structfield struct { 417 name name 418 typ *_type 419 offset uintptr 420 } 421 422 type structtype struct { 423 typ _type 424 pkgPath name 425 fields []structfield 426 } 427 428 // name is an encoded type name with optional extra data. 429 // See reflect/type.go for details. 430 type name struct { 431 bytes *byte 432 } 433 434 func (n name) data(off int) *byte { 435 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off))) 436 } 437 438 func (n name) isExported() bool { 439 return (*n.bytes)&(1<<0) != 0 440 } 441 442 func (n name) isEmbedded() bool { 443 return (*n.bytes)&(1<<3) != 0 444 } 445 446 func (n name) readvarint(off int) (int, int) { 447 v := 0 448 for i := 0; ; i++ { 449 x := *n.data(off + i) 450 v += int(x&0x7f) << (7 * i) 451 if x&0x80 == 0 { 452 return i + 1, v 453 } 454 } 455 } 456 457 func (n name) name() string { 458 if n.bytes == nil { 459 return "" 460 } 461 i, l := n.readvarint(1) 462 if l == 0 { 463 return "" 464 } 465 return unsafe.String(n.data(1+i), l) 466 } 467 468 func (n name) tag() string { 469 if *n.data(0)&(1<<1) == 0 { 470 return "" 471 } 472 i, l := n.readvarint(1) 473 i2, l2 := n.readvarint(1 + i + l) 474 return unsafe.String(n.data(1+i+l+i2), l2) 475 } 476 477 func (n name) pkgPath() string { 478 if n.bytes == nil || *n.data(0)&(1<<2) == 0 { 479 return "" 480 } 481 i, l := n.readvarint(1) 482 off := 1 + i + l 483 if *n.data(0)&(1<<1) != 0 { 484 i2, l2 := n.readvarint(off) 485 off += i2 + l2 486 } 487 var nameOff nameOff 488 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:]) 489 pkgPathName := resolveNameOff(unsafe.Pointer(n.bytes), nameOff) 490 return pkgPathName.name() 491 } 492 493 func (n name) isBlank() bool { 494 if n.bytes == nil { 495 return false 496 } 497 _, l := n.readvarint(1) 498 return l == 1 && *n.data(2) == '_' 499 } 500 501 // typelinksinit scans the types from extra modules and builds the 502 // moduledata typemap used to de-duplicate type pointers. 503 func typelinksinit() { 504 if firstmoduledata.next == nil { 505 return 506 } 507 typehash := make(map[uint32][]*_type, len(firstmoduledata.typelinks)) 508 509 modules := activeModules() 510 prev := modules[0] 511 for _, md := range modules[1:] { 512 // Collect types from the previous module into typehash. 513 collect: 514 for _, tl := range prev.typelinks { 515 var t *_type 516 if prev.typemap == nil { 517 t = (*_type)(unsafe.Pointer(prev.types + uintptr(tl))) 518 } else { 519 t = prev.typemap[typeOff(tl)] 520 } 521 // Add to typehash if not seen before. 522 tlist := typehash[t.hash] 523 for _, tcur := range tlist { 524 if tcur == t { 525 continue collect 526 } 527 } 528 typehash[t.hash] = append(tlist, t) 529 } 530 531 if md.typemap == nil { 532 // If any of this module's typelinks match a type from a 533 // prior module, prefer that prior type by adding the offset 534 // to this module's typemap. 535 tm := make(map[typeOff]*_type, len(md.typelinks)) 536 pinnedTypemaps = append(pinnedTypemaps, tm) 537 md.typemap = tm 538 for _, tl := range md.typelinks { 539 t := (*_type)(unsafe.Pointer(md.types + uintptr(tl))) 540 for _, candidate := range typehash[t.hash] { 541 seen := map[_typePair]struct{}{} 542 if typesEqual(t, candidate, seen) { 543 t = candidate 544 break 545 } 546 } 547 md.typemap[typeOff(tl)] = t 548 } 549 } 550 551 prev = md 552 } 553 } 554 555 type _typePair struct { 556 t1 *_type 557 t2 *_type 558 } 559 560 // typesEqual reports whether two types are equal. 561 // 562 // Everywhere in the runtime and reflect packages, it is assumed that 563 // there is exactly one *_type per Go type, so that pointer equality 564 // can be used to test if types are equal. There is one place that 565 // breaks this assumption: buildmode=shared. In this case a type can 566 // appear as two different pieces of memory. This is hidden from the 567 // runtime and reflect package by the per-module typemap built in 568 // typelinksinit. It uses typesEqual to map types from later modules 569 // back into earlier ones. 570 // 571 // Only typelinksinit needs this function. 572 func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool { 573 tp := _typePair{t, v} 574 if _, ok := seen[tp]; ok { 575 return true 576 } 577 578 // mark these types as seen, and thus equivalent which prevents an infinite loop if 579 // the two types are identical, but recursively defined and loaded from 580 // different modules 581 seen[tp] = struct{}{} 582 583 if t == v { 584 return true 585 } 586 kind := t.kind & kindMask 587 if kind != v.kind&kindMask { 588 return false 589 } 590 if t.string() != v.string() { 591 return false 592 } 593 ut := t.uncommon() 594 uv := v.uncommon() 595 if ut != nil || uv != nil { 596 if ut == nil || uv == nil { 597 return false 598 } 599 pkgpatht := t.nameOff(ut.pkgpath).name() 600 pkgpathv := v.nameOff(uv.pkgpath).name() 601 if pkgpatht != pkgpathv { 602 return false 603 } 604 } 605 if kindBool <= kind && kind <= kindComplex128 { 606 return true 607 } 608 switch kind { 609 case kindString, kindUnsafePointer: 610 return true 611 case kindArray: 612 at := (*arraytype)(unsafe.Pointer(t)) 613 av := (*arraytype)(unsafe.Pointer(v)) 614 return typesEqual(at.elem, av.elem, seen) && at.len == av.len 615 case kindChan: 616 ct := (*chantype)(unsafe.Pointer(t)) 617 cv := (*chantype)(unsafe.Pointer(v)) 618 return ct.dir == cv.dir && typesEqual(ct.elem, cv.elem, seen) 619 case kindFunc: 620 ft := (*functype)(unsafe.Pointer(t)) 621 fv := (*functype)(unsafe.Pointer(v)) 622 if ft.outCount != fv.outCount || ft.inCount != fv.inCount { 623 return false 624 } 625 tin, vin := ft.in(), fv.in() 626 for i := 0; i < len(tin); i++ { 627 if !typesEqual(tin[i], vin[i], seen) { 628 return false 629 } 630 } 631 tout, vout := ft.out(), fv.out() 632 for i := 0; i < len(tout); i++ { 633 if !typesEqual(tout[i], vout[i], seen) { 634 return false 635 } 636 } 637 return true 638 case kindInterface: 639 it := (*interfacetype)(unsafe.Pointer(t)) 640 iv := (*interfacetype)(unsafe.Pointer(v)) 641 if it.pkgpath.name() != iv.pkgpath.name() { 642 return false 643 } 644 if len(it.mhdr) != len(iv.mhdr) { 645 return false 646 } 647 for i := range it.mhdr { 648 tm := &it.mhdr[i] 649 vm := &iv.mhdr[i] 650 // Note the mhdr array can be relocated from 651 // another module. See #17724. 652 tname := resolveNameOff(unsafe.Pointer(tm), tm.name) 653 vname := resolveNameOff(unsafe.Pointer(vm), vm.name) 654 if tname.name() != vname.name() { 655 return false 656 } 657 if tname.pkgPath() != vname.pkgPath() { 658 return false 659 } 660 tityp := resolveTypeOff(unsafe.Pointer(tm), tm.ityp) 661 vityp := resolveTypeOff(unsafe.Pointer(vm), vm.ityp) 662 if !typesEqual(tityp, vityp, seen) { 663 return false 664 } 665 } 666 return true 667 case kindMap: 668 mt := (*maptype)(unsafe.Pointer(t)) 669 mv := (*maptype)(unsafe.Pointer(v)) 670 return typesEqual(mt.key, mv.key, seen) && typesEqual(mt.elem, mv.elem, seen) 671 case kindPtr: 672 pt := (*ptrtype)(unsafe.Pointer(t)) 673 pv := (*ptrtype)(unsafe.Pointer(v)) 674 return typesEqual(pt.elem, pv.elem, seen) 675 case kindSlice: 676 st := (*slicetype)(unsafe.Pointer(t)) 677 sv := (*slicetype)(unsafe.Pointer(v)) 678 return typesEqual(st.elem, sv.elem, seen) 679 case kindStruct: 680 st := (*structtype)(unsafe.Pointer(t)) 681 sv := (*structtype)(unsafe.Pointer(v)) 682 if len(st.fields) != len(sv.fields) { 683 return false 684 } 685 if st.pkgPath.name() != sv.pkgPath.name() { 686 return false 687 } 688 for i := range st.fields { 689 tf := &st.fields[i] 690 vf := &sv.fields[i] 691 if tf.name.name() != vf.name.name() { 692 return false 693 } 694 if !typesEqual(tf.typ, vf.typ, seen) { 695 return false 696 } 697 if tf.name.tag() != vf.name.tag() { 698 return false 699 } 700 if tf.offset != vf.offset { 701 return false 702 } 703 if tf.name.isEmbedded() != vf.name.isEmbedded() { 704 return false 705 } 706 } 707 return true 708 default: 709 println("runtime: impossible type kind", kind) 710 throw("runtime: impossible type kind") 711 return false 712 } 713 }