Source file
src/reflect/type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package reflect
17
18 import (
19 "internal/abi"
20 "internal/goarch"
21 "strconv"
22 "sync"
23 "unicode"
24 "unicode/utf8"
25 "unsafe"
26 )
27
28
29
30
31
32
33
34
35
36
37
38
39 type Type interface {
40
41
42
43
44 Align() int
45
46
47
48 FieldAlign() int
49
50
51
52
53
54
55
56
57
58
59
60
61 Method(int) Method
62
63
64
65
66
67
68
69
70
71 MethodByName(string) (Method, bool)
72
73
74
75
76
77
78 NumMethod() int
79
80
81
82 Name() string
83
84
85
86
87
88
89 PkgPath() string
90
91
92
93 Size() uintptr
94
95
96
97
98
99
100 String() string
101
102
103 Kind() Kind
104
105
106 Implements(u Type) bool
107
108
109 AssignableTo(u Type) bool
110
111
112
113
114
115 ConvertibleTo(u Type) bool
116
117
118
119
120
121 Comparable() bool
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 Bits() int
139
140
141
142 ChanDir() ChanDir
143
144
145
146
147
148
149
150
151
152
153
154
155
156 IsVariadic() bool
157
158
159
160 Elem() Type
161
162
163
164
165 Field(i int) StructField
166
167
168
169
170
171 FieldByIndex(index []int) StructField
172
173
174
175 FieldByName(name string) (StructField, bool)
176
177
178
179
180
181
182
183
184
185
186
187
188
189 FieldByNameFunc(match func(string) bool) (StructField, bool)
190
191
192
193
194 In(i int) Type
195
196
197
198 Key() Type
199
200
201
202 Len() int
203
204
205
206 NumField() int
207
208
209
210 NumIn() int
211
212
213
214 NumOut() int
215
216
217
218
219 Out(i int) Type
220
221 common() *abi.Type
222 uncommon() *uncommonType
223 }
224
225
226
227
228
229
230
231
232
233
238
239
240
241 type Kind uint
242
243 const (
244 Invalid Kind = iota
245 Bool
246 Int
247 Int8
248 Int16
249 Int32
250 Int64
251 Uint
252 Uint8
253 Uint16
254 Uint32
255 Uint64
256 Uintptr
257 Float32
258 Float64
259 Complex64
260 Complex128
261 Array
262 Chan
263 Func
264 Interface
265 Map
266 Pointer
267 Slice
268 String
269 Struct
270 UnsafePointer
271 )
272
273
274 const Ptr = Pointer
275
276
277
278
279
280 type uncommonType = abi.UncommonType
281
282
283 type common struct {
284 abi.Type
285 }
286
287
288
289 type rtype struct {
290 t abi.Type
291 }
292
293 func (t *rtype) common() *abi.Type {
294 return &t.t
295 }
296
297 func (t *rtype) uncommon() *abi.UncommonType {
298 return t.t.Uncommon()
299 }
300
301 type aNameOff = abi.NameOff
302 type aTypeOff = abi.TypeOff
303 type aTextOff = abi.TextOff
304
305
306 type ChanDir int
307
308 const (
309 RecvDir ChanDir = 1 << iota
310 SendDir
311 BothDir = RecvDir | SendDir
312 )
313
314
315 type arrayType = abi.ArrayType
316
317
318 type chanType = abi.ChanType
319
320
321
322
323
324
325
326
327
328
329
330
331 type funcType = abi.FuncType
332
333
334 type interfaceType struct {
335 abi.InterfaceType
336 }
337
338 func (t *interfaceType) nameOff(off aNameOff) abi.Name {
339 return toRType(&t.Type).nameOff(off)
340 }
341
342 func nameOffFor(t *abi.Type, off aNameOff) abi.Name {
343 return toRType(t).nameOff(off)
344 }
345
346 func typeOffFor(t *abi.Type, off aTypeOff) *abi.Type {
347 return toRType(t).typeOff(off)
348 }
349
350 func (t *interfaceType) typeOff(off aTypeOff) *abi.Type {
351 return toRType(&t.Type).typeOff(off)
352 }
353
354 func (t *interfaceType) common() *abi.Type {
355 return &t.Type
356 }
357
358 func (t *interfaceType) uncommon() *abi.UncommonType {
359 return t.Uncommon()
360 }
361
362
363 type mapType struct {
364 abi.MapType
365 }
366
367
368 type ptrType struct {
369 abi.PtrType
370 }
371
372
373 type sliceType struct {
374 abi.SliceType
375 }
376
377
378 type structField = abi.StructField
379
380
381 type structType struct {
382 abi.StructType
383 }
384
385 func pkgPath(n abi.Name) string {
386 if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
387 return ""
388 }
389 i, l := n.ReadVarint(1)
390 off := 1 + i + l
391 if n.HasTag() {
392 i2, l2 := n.ReadVarint(off)
393 off += i2 + l2
394 }
395 var nameOff int32
396
397
398 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
399 pkgPathName := abi.Name{Bytes: (*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
400 return pkgPathName.Name()
401 }
402
403 func newName(n, tag string, exported, embedded bool) abi.Name {
404 return abi.NewName(n, tag, exported, embedded)
405 }
406
407
411
412
413 type Method struct {
414
415 Name string
416
417
418
419
420
421
422 PkgPath string
423
424 Type Type
425 Func Value
426 Index int
427 }
428
429
430 func (m Method) IsExported() bool {
431 return m.PkgPath == ""
432 }
433
434 const (
435 kindDirectIface = 1 << 5
436 kindGCProg = 1 << 6
437 kindMask = (1 << 5) - 1
438 )
439
440
441 func (k Kind) String() string {
442 if uint(k) < uint(len(kindNames)) {
443 return kindNames[uint(k)]
444 }
445 return "kind" + strconv.Itoa(int(k))
446 }
447
448 var kindNames = []string{
449 Invalid: "invalid",
450 Bool: "bool",
451 Int: "int",
452 Int8: "int8",
453 Int16: "int16",
454 Int32: "int32",
455 Int64: "int64",
456 Uint: "uint",
457 Uint8: "uint8",
458 Uint16: "uint16",
459 Uint32: "uint32",
460 Uint64: "uint64",
461 Uintptr: "uintptr",
462 Float32: "float32",
463 Float64: "float64",
464 Complex64: "complex64",
465 Complex128: "complex128",
466 Array: "array",
467 Chan: "chan",
468 Func: "func",
469 Interface: "interface",
470 Map: "map",
471 Pointer: "ptr",
472 Slice: "slice",
473 String: "string",
474 Struct: "struct",
475 UnsafePointer: "unsafe.Pointer",
476 }
477
478
479
480
481
482
483 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
484
485
486
487
488
489
490 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
491
492
493
494
495
496
497 func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
498
499
500
501
502
503
504 func addReflectOff(ptr unsafe.Pointer) int32
505
506
507
508 func resolveReflectName(n abi.Name) aNameOff {
509 return aNameOff(addReflectOff(unsafe.Pointer(n.Bytes)))
510 }
511
512
513
514 func resolveReflectType(t *abi.Type) aTypeOff {
515 return aTypeOff(addReflectOff(unsafe.Pointer(t)))
516 }
517
518
519
520
521 func resolveReflectText(ptr unsafe.Pointer) aTextOff {
522 return aTextOff(addReflectOff(ptr))
523 }
524
525 func (t *rtype) nameOff(off aNameOff) abi.Name {
526 return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
527 }
528
529 func (t *rtype) typeOff(off aTypeOff) *abi.Type {
530 return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
531 }
532
533 func (t *rtype) textOff(off aTextOff) unsafe.Pointer {
534 return resolveTextOff(unsafe.Pointer(t), int32(off))
535 }
536
537 func textOffFor(t *abi.Type, off aTextOff) unsafe.Pointer {
538 return toRType(t).textOff(off)
539 }
540
541 func (t *rtype) String() string {
542 s := t.nameOff(t.t.Str).Name()
543 if t.t.TFlag&abi.TFlagExtraStar != 0 {
544 return s[1:]
545 }
546 return s
547 }
548
549 func (t *rtype) Size() uintptr { return t.t.Size() }
550
551 func (t *rtype) Bits() int {
552 if t == nil {
553 panic("reflect: Bits of nil Type")
554 }
555 k := t.Kind()
556 if k < Int || k > Complex128 {
557 panic("reflect: Bits of non-arithmetic Type " + t.String())
558 }
559 return int(t.t.Size_) * 8
560 }
561
562 func (t *rtype) Align() int { return t.t.Align() }
563
564 func (t *rtype) FieldAlign() int { return t.t.FieldAlign() }
565
566 func (t *rtype) Kind() Kind { return Kind(t.t.Kind()) }
567
568 func (t *rtype) exportedMethods() []abi.Method {
569 ut := t.uncommon()
570 if ut == nil {
571 return nil
572 }
573 return ut.ExportedMethods()
574 }
575
576 func (t *rtype) NumMethod() int {
577 if t.Kind() == Interface {
578 tt := (*interfaceType)(unsafe.Pointer(t))
579 return tt.NumMethod()
580 }
581 return len(t.exportedMethods())
582 }
583
584 func (t *rtype) Method(i int) (m Method) {
585 if t.Kind() == Interface {
586 tt := (*interfaceType)(unsafe.Pointer(t))
587 return tt.Method(i)
588 }
589 methods := t.exportedMethods()
590 if i < 0 || i >= len(methods) {
591 panic("reflect: Method index out of range")
592 }
593 p := methods[i]
594 pname := t.nameOff(p.Name)
595 m.Name = pname.Name()
596 fl := flag(Func)
597 mtyp := t.typeOff(p.Mtyp)
598 ft := (*funcType)(unsafe.Pointer(mtyp))
599 in := make([]Type, 0, 1+ft.NumIn())
600 in = append(in, t)
601 for _, arg := range ft.InSlice() {
602 in = append(in, toRType(arg))
603 }
604 out := make([]Type, 0, ft.NumOut())
605 for _, ret := range ft.OutSlice() {
606 out = append(out, toRType(ret))
607 }
608 mt := FuncOf(in, out, ft.IsVariadic())
609 m.Type = mt
610 tfn := t.textOff(p.Tfn)
611 fn := unsafe.Pointer(&tfn)
612 m.Func = Value{&mt.(*rtype).t, fn, fl}
613
614 m.Index = i
615 return m
616 }
617
618 func (t *rtype) MethodByName(name string) (m Method, ok bool) {
619 if t.Kind() == Interface {
620 tt := (*interfaceType)(unsafe.Pointer(t))
621 return tt.MethodByName(name)
622 }
623 ut := t.uncommon()
624 if ut == nil {
625 return Method{}, false
626 }
627
628 methods := ut.ExportedMethods()
629
630
631
632 i, j := 0, len(methods)
633 for i < j {
634 h := int(uint(i+j) >> 1)
635
636 if !(t.nameOff(methods[h].Name).Name() >= name) {
637 i = h + 1
638 } else {
639 j = h
640 }
641 }
642
643 if i < len(methods) && name == t.nameOff(methods[i].Name).Name() {
644 return t.Method(i), true
645 }
646
647 return Method{}, false
648 }
649
650 func (t *rtype) PkgPath() string {
651 if t.t.TFlag&abi.TFlagNamed == 0 {
652 return ""
653 }
654 ut := t.uncommon()
655 if ut == nil {
656 return ""
657 }
658 return t.nameOff(ut.PkgPath).Name()
659 }
660
661 func pkgPathFor(t *abi.Type) string {
662 return toRType(t).PkgPath()
663 }
664
665 func (t *rtype) Name() string {
666 if !t.t.HasName() {
667 return ""
668 }
669 s := t.String()
670 i := len(s) - 1
671 sqBrackets := 0
672 for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
673 switch s[i] {
674 case ']':
675 sqBrackets++
676 case '[':
677 sqBrackets--
678 }
679 i--
680 }
681 return s[i+1:]
682 }
683
684 func nameFor(t *abi.Type) string {
685 return toRType(t).Name()
686 }
687
688 func (t *rtype) ChanDir() ChanDir {
689 if t.Kind() != Chan {
690 panic("reflect: ChanDir of non-chan type " + t.String())
691 }
692 tt := (*abi.ChanType)(unsafe.Pointer(t))
693 return ChanDir(tt.Dir)
694 }
695
696 func toRType(t *abi.Type) *rtype {
697 return (*rtype)(unsafe.Pointer(t))
698 }
699
700 func elem(t *abi.Type) *abi.Type {
701 et := t.Elem()
702 if et != nil {
703 return et
704 }
705 panic("reflect: Elem of invalid type " + stringFor(t))
706 }
707
708 func (t *rtype) Elem() Type {
709 return toType(elem(t.common()))
710 }
711
712 func (t *rtype) Field(i int) StructField {
713 if t.Kind() != Struct {
714 panic("reflect: Field of non-struct type " + t.String())
715 }
716 tt := (*structType)(unsafe.Pointer(t))
717 return tt.Field(i)
718 }
719
720 func (t *rtype) FieldByIndex(index []int) StructField {
721 if t.Kind() != Struct {
722 panic("reflect: FieldByIndex of non-struct type " + t.String())
723 }
724 tt := (*structType)(unsafe.Pointer(t))
725 return tt.FieldByIndex(index)
726 }
727
728 func (t *rtype) FieldByName(name string) (StructField, bool) {
729 if t.Kind() != Struct {
730 panic("reflect: FieldByName of non-struct type " + t.String())
731 }
732 tt := (*structType)(unsafe.Pointer(t))
733 return tt.FieldByName(name)
734 }
735
736 func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
737 if t.Kind() != Struct {
738 panic("reflect: FieldByNameFunc of non-struct type " + t.String())
739 }
740 tt := (*structType)(unsafe.Pointer(t))
741 return tt.FieldByNameFunc(match)
742 }
743
744 func (t *rtype) Key() Type {
745 if t.Kind() != Map {
746 panic("reflect: Key of non-map type " + t.String())
747 }
748 tt := (*mapType)(unsafe.Pointer(t))
749 return toType(tt.Key)
750 }
751
752 func (t *rtype) Len() int {
753 if t.Kind() != Array {
754 panic("reflect: Len of non-array type " + t.String())
755 }
756 tt := (*arrayType)(unsafe.Pointer(t))
757 return int(tt.Len)
758 }
759
760 func (t *rtype) NumField() int {
761 if t.Kind() != Struct {
762 panic("reflect: NumField of non-struct type " + t.String())
763 }
764 tt := (*structType)(unsafe.Pointer(t))
765 return len(tt.Fields)
766 }
767
768 func (t *rtype) In(i int) Type {
769 if t.Kind() != Func {
770 panic("reflect: In of non-func type " + t.String())
771 }
772 tt := (*abi.FuncType)(unsafe.Pointer(t))
773 return toType(tt.InSlice()[i])
774 }
775
776 func (t *rtype) NumIn() int {
777 if t.Kind() != Func {
778 panic("reflect: NumIn of non-func type " + t.String())
779 }
780 tt := (*abi.FuncType)(unsafe.Pointer(t))
781 return tt.NumIn()
782 }
783
784 func (t *rtype) NumOut() int {
785 if t.Kind() != Func {
786 panic("reflect: NumOut of non-func type " + t.String())
787 }
788 tt := (*abi.FuncType)(unsafe.Pointer(t))
789 return tt.NumOut()
790 }
791
792 func (t *rtype) Out(i int) Type {
793 if t.Kind() != Func {
794 panic("reflect: Out of non-func type " + t.String())
795 }
796 tt := (*abi.FuncType)(unsafe.Pointer(t))
797 return toType(tt.OutSlice()[i])
798 }
799
800 func (t *rtype) IsVariadic() bool {
801 if t.Kind() != Func {
802 panic("reflect: IsVariadic of non-func type " + t.String())
803 }
804 tt := (*abi.FuncType)(unsafe.Pointer(t))
805 return tt.IsVariadic()
806 }
807
808
809
810
811
812
813
814
815 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
816 return unsafe.Pointer(uintptr(p) + x)
817 }
818
819 func (d ChanDir) String() string {
820 switch d {
821 case SendDir:
822 return "chan<-"
823 case RecvDir:
824 return "<-chan"
825 case BothDir:
826 return "chan"
827 }
828 return "ChanDir" + strconv.Itoa(int(d))
829 }
830
831
832 func (t *interfaceType) Method(i int) (m Method) {
833 if i < 0 || i >= len(t.Methods) {
834 return
835 }
836 p := &t.Methods[i]
837 pname := t.nameOff(p.Name)
838 m.Name = pname.Name()
839 if !pname.IsExported() {
840 m.PkgPath = pkgPath(pname)
841 if m.PkgPath == "" {
842 m.PkgPath = t.PkgPath.Name()
843 }
844 }
845 m.Type = toType(t.typeOff(p.Typ))
846 m.Index = i
847 return
848 }
849
850
851 func (t *interfaceType) NumMethod() int { return len(t.Methods) }
852
853
854 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
855 if t == nil {
856 return
857 }
858 var p *abi.Imethod
859 for i := range t.Methods {
860 p = &t.Methods[i]
861 if t.nameOff(p.Name).Name() == name {
862 return t.Method(i), true
863 }
864 }
865 return
866 }
867
868
869 type StructField struct {
870
871 Name string
872
873
874
875
876 PkgPath string
877
878 Type Type
879 Tag StructTag
880 Offset uintptr
881 Index []int
882 Anonymous bool
883 }
884
885
886 func (f StructField) IsExported() bool {
887 return f.PkgPath == ""
888 }
889
890
891
892
893
894
895
896
897
898 type StructTag string
899
900
901
902
903
904
905 func (tag StructTag) Get(key string) string {
906 v, _ := tag.Lookup(key)
907 return v
908 }
909
910
911
912
913
914
915
916 func (tag StructTag) Lookup(key string) (value string, ok bool) {
917
918
919
920 for tag != "" {
921
922 i := 0
923 for i < len(tag) && tag[i] == ' ' {
924 i++
925 }
926 tag = tag[i:]
927 if tag == "" {
928 break
929 }
930
931
932
933
934
935 i = 0
936 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
937 i++
938 }
939 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
940 break
941 }
942 name := string(tag[:i])
943 tag = tag[i+1:]
944
945
946 i = 1
947 for i < len(tag) && tag[i] != '"' {
948 if tag[i] == '\\' {
949 i++
950 }
951 i++
952 }
953 if i >= len(tag) {
954 break
955 }
956 qvalue := string(tag[:i+1])
957 tag = tag[i+1:]
958
959 if key == name {
960 value, err := strconv.Unquote(qvalue)
961 if err != nil {
962 break
963 }
964 return value, true
965 }
966 }
967 return "", false
968 }
969
970
971 func (t *structType) Field(i int) (f StructField) {
972 if i < 0 || i >= len(t.Fields) {
973 panic("reflect: Field index out of bounds")
974 }
975 p := &t.Fields[i]
976 f.Type = toType(p.Typ)
977 f.Name = p.Name.Name()
978 f.Anonymous = p.Embedded()
979 if !p.Name.IsExported() {
980 f.PkgPath = t.PkgPath.Name()
981 }
982 if tag := p.Name.Tag(); tag != "" {
983 f.Tag = StructTag(tag)
984 }
985 f.Offset = p.Offset
986
987
988
989
990
991
992
993
994 f.Index = []int{i}
995 return
996 }
997
998
999
1000
1001
1002 func (t *structType) FieldByIndex(index []int) (f StructField) {
1003 f.Type = toType(&t.Type)
1004 for i, x := range index {
1005 if i > 0 {
1006 ft := f.Type
1007 if ft.Kind() == Pointer && ft.Elem().Kind() == Struct {
1008 ft = ft.Elem()
1009 }
1010 f.Type = ft
1011 }
1012 f = f.Type.Field(x)
1013 }
1014 return
1015 }
1016
1017
1018 type fieldScan struct {
1019 typ *structType
1020 index []int
1021 }
1022
1023
1024
1025 func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
1026
1027
1028
1029
1030
1031
1032
1033
1034 current := []fieldScan{}
1035 next := []fieldScan{{typ: t}}
1036
1037
1038
1039
1040
1041
1042
1043 var nextCount map[*structType]int
1044
1045
1046
1047
1048
1049
1050 visited := map[*structType]bool{}
1051
1052 for len(next) > 0 {
1053 current, next = next, current[:0]
1054 count := nextCount
1055 nextCount = nil
1056
1057
1058
1059
1060
1061 for _, scan := range current {
1062 t := scan.typ
1063 if visited[t] {
1064
1065
1066
1067 continue
1068 }
1069 visited[t] = true
1070 for i := range t.Fields {
1071 f := &t.Fields[i]
1072
1073 fname := f.Name.Name()
1074 var ntyp *abi.Type
1075 if f.Embedded() {
1076
1077 ntyp = f.Typ
1078 if ntyp.Kind() == abi.Pointer {
1079 ntyp = ntyp.Elem()
1080 }
1081 }
1082
1083
1084 if match(fname) {
1085
1086 if count[t] > 1 || ok {
1087
1088 return StructField{}, false
1089 }
1090 result = t.Field(i)
1091 result.Index = nil
1092 result.Index = append(result.Index, scan.index...)
1093 result.Index = append(result.Index, i)
1094 ok = true
1095 continue
1096 }
1097
1098
1099
1100
1101 if ok || ntyp == nil || ntyp.Kind() != abi.Struct {
1102 continue
1103 }
1104 styp := (*structType)(unsafe.Pointer(ntyp))
1105 if nextCount[styp] > 0 {
1106 nextCount[styp] = 2
1107 continue
1108 }
1109 if nextCount == nil {
1110 nextCount = map[*structType]int{}
1111 }
1112 nextCount[styp] = 1
1113 if count[t] > 1 {
1114 nextCount[styp] = 2
1115 }
1116 var index []int
1117 index = append(index, scan.index...)
1118 index = append(index, i)
1119 next = append(next, fieldScan{styp, index})
1120 }
1121 }
1122 if ok {
1123 break
1124 }
1125 }
1126 return
1127 }
1128
1129
1130
1131 func (t *structType) FieldByName(name string) (f StructField, present bool) {
1132
1133 hasEmbeds := false
1134 if name != "" {
1135 for i := range t.Fields {
1136 tf := &t.Fields[i]
1137 if tf.Name.Name() == name {
1138 return t.Field(i), true
1139 }
1140 if tf.Embedded() {
1141 hasEmbeds = true
1142 }
1143 }
1144 }
1145 if !hasEmbeds {
1146 return
1147 }
1148 return t.FieldByNameFunc(func(s string) bool { return s == name })
1149 }
1150
1151
1152
1153 func TypeOf(i any) Type {
1154 eface := *(*emptyInterface)(unsafe.Pointer(&i))
1155
1156
1157 return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ))))
1158 }
1159
1160
1161 func rtypeOf(i any) *abi.Type {
1162 eface := *(*emptyInterface)(unsafe.Pointer(&i))
1163 return eface.typ
1164 }
1165
1166
1167 var ptrMap sync.Map
1168
1169
1170
1171
1172
1173
1174 func PtrTo(t Type) Type { return PointerTo(t) }
1175
1176
1177
1178 func PointerTo(t Type) Type {
1179 return toRType(t.(*rtype).ptrTo())
1180 }
1181
1182 func (t *rtype) ptrTo() *abi.Type {
1183 at := &t.t
1184 if at.PtrToThis != 0 {
1185 return t.typeOff(at.PtrToThis)
1186 }
1187
1188
1189 if pi, ok := ptrMap.Load(t); ok {
1190 return &pi.(*ptrType).Type
1191 }
1192
1193
1194 s := "*" + t.String()
1195 for _, tt := range typesByString(s) {
1196 p := (*ptrType)(unsafe.Pointer(tt))
1197 if p.Elem != &t.t {
1198 continue
1199 }
1200 pi, _ := ptrMap.LoadOrStore(t, p)
1201 return &pi.(*ptrType).Type
1202 }
1203
1204
1205
1206 var iptr any = (*unsafe.Pointer)(nil)
1207 prototype := *(**ptrType)(unsafe.Pointer(&iptr))
1208 pp := *prototype
1209
1210 pp.Str = resolveReflectName(newName(s, "", false, false))
1211 pp.PtrToThis = 0
1212
1213
1214
1215
1216
1217
1218 pp.Hash = fnv1(t.t.Hash, '*')
1219
1220 pp.Elem = at
1221
1222 pi, _ := ptrMap.LoadOrStore(t, &pp)
1223 return &pi.(*ptrType).Type
1224 }
1225
1226 func ptrTo(t *abi.Type) *abi.Type {
1227 return toRType(t).ptrTo()
1228 }
1229
1230
1231 func fnv1(x uint32, list ...byte) uint32 {
1232 for _, b := range list {
1233 x = x*16777619 ^ uint32(b)
1234 }
1235 return x
1236 }
1237
1238 func (t *rtype) Implements(u Type) bool {
1239 if u == nil {
1240 panic("reflect: nil type passed to Type.Implements")
1241 }
1242 if u.Kind() != Interface {
1243 panic("reflect: non-interface type passed to Type.Implements")
1244 }
1245 return implements(u.common(), t.common())
1246 }
1247
1248 func (t *rtype) AssignableTo(u Type) bool {
1249 if u == nil {
1250 panic("reflect: nil type passed to Type.AssignableTo")
1251 }
1252 uu := u.common()
1253 return directlyAssignable(uu, t.common()) || implements(uu, t.common())
1254 }
1255
1256 func (t *rtype) ConvertibleTo(u Type) bool {
1257 if u == nil {
1258 panic("reflect: nil type passed to Type.ConvertibleTo")
1259 }
1260 return convertOp(u.common(), t.common()) != nil
1261 }
1262
1263 func (t *rtype) Comparable() bool {
1264 return t.t.Equal != nil
1265 }
1266
1267
1268 func implements(T, V *abi.Type) bool {
1269 if T.Kind() != abi.Interface {
1270 return false
1271 }
1272 t := (*interfaceType)(unsafe.Pointer(T))
1273 if len(t.Methods) == 0 {
1274 return true
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 if V.Kind() == abi.Interface {
1290 v := (*interfaceType)(unsafe.Pointer(V))
1291 i := 0
1292 for j := 0; j < len(v.Methods); j++ {
1293 tm := &t.Methods[i]
1294 tmName := t.nameOff(tm.Name)
1295 vm := &v.Methods[j]
1296 vmName := nameOffFor(V, vm.Name)
1297 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Typ) == t.typeOff(tm.Typ) {
1298 if !tmName.IsExported() {
1299 tmPkgPath := pkgPath(tmName)
1300 if tmPkgPath == "" {
1301 tmPkgPath = t.PkgPath.Name()
1302 }
1303 vmPkgPath := pkgPath(vmName)
1304 if vmPkgPath == "" {
1305 vmPkgPath = v.PkgPath.Name()
1306 }
1307 if tmPkgPath != vmPkgPath {
1308 continue
1309 }
1310 }
1311 if i++; i >= len(t.Methods) {
1312 return true
1313 }
1314 }
1315 }
1316 return false
1317 }
1318
1319 v := V.Uncommon()
1320 if v == nil {
1321 return false
1322 }
1323 i := 0
1324 vmethods := v.Methods()
1325 for j := 0; j < int(v.Mcount); j++ {
1326 tm := &t.Methods[i]
1327 tmName := t.nameOff(tm.Name)
1328 vm := vmethods[j]
1329 vmName := nameOffFor(V, vm.Name)
1330 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Mtyp) == t.typeOff(tm.Typ) {
1331 if !tmName.IsExported() {
1332 tmPkgPath := pkgPath(tmName)
1333 if tmPkgPath == "" {
1334 tmPkgPath = t.PkgPath.Name()
1335 }
1336 vmPkgPath := pkgPath(vmName)
1337 if vmPkgPath == "" {
1338 vmPkgPath = nameOffFor(V, v.PkgPath).Name()
1339 }
1340 if tmPkgPath != vmPkgPath {
1341 continue
1342 }
1343 }
1344 if i++; i >= len(t.Methods) {
1345 return true
1346 }
1347 }
1348 }
1349 return false
1350 }
1351
1352
1353
1354
1355
1356 func specialChannelAssignability(T, V *abi.Type) bool {
1357
1358
1359
1360
1361 return V.ChanDir() == abi.BothDir && (nameFor(T) == "" || nameFor(V) == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
1362 }
1363
1364
1365
1366
1367
1368
1369 func directlyAssignable(T, V *abi.Type) bool {
1370
1371 if T == V {
1372 return true
1373 }
1374
1375
1376
1377 if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
1378 return false
1379 }
1380
1381 if T.Kind() == abi.Chan && specialChannelAssignability(T, V) {
1382 return true
1383 }
1384
1385
1386 return haveIdenticalUnderlyingType(T, V, true)
1387 }
1388
1389 func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
1390 if cmpTags {
1391 return T == V
1392 }
1393
1394 if nameFor(T) != nameFor(V) || T.Kind() != V.Kind() || pkgPathFor(T) != pkgPathFor(V) {
1395 return false
1396 }
1397
1398 return haveIdenticalUnderlyingType(T, V, false)
1399 }
1400
1401 func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
1402 if T == V {
1403 return true
1404 }
1405
1406 kind := Kind(T.Kind())
1407 if kind != Kind(V.Kind()) {
1408 return false
1409 }
1410
1411
1412
1413 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
1414 return true
1415 }
1416
1417
1418 switch kind {
1419 case Array:
1420 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1421
1422 case Chan:
1423 return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1424
1425 case Func:
1426 t := (*funcType)(unsafe.Pointer(T))
1427 v := (*funcType)(unsafe.Pointer(V))
1428 if t.OutCount != v.OutCount || t.InCount != v.InCount {
1429 return false
1430 }
1431 for i := 0; i < t.NumIn(); i++ {
1432 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
1433 return false
1434 }
1435 }
1436 for i := 0; i < t.NumOut(); i++ {
1437 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
1438 return false
1439 }
1440 }
1441 return true
1442
1443 case Interface:
1444 t := (*interfaceType)(unsafe.Pointer(T))
1445 v := (*interfaceType)(unsafe.Pointer(V))
1446 if len(t.Methods) == 0 && len(v.Methods) == 0 {
1447 return true
1448 }
1449
1450
1451 return false
1452
1453 case Map:
1454 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1455
1456 case Pointer, Slice:
1457 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1458
1459 case Struct:
1460 t := (*structType)(unsafe.Pointer(T))
1461 v := (*structType)(unsafe.Pointer(V))
1462 if len(t.Fields) != len(v.Fields) {
1463 return false
1464 }
1465 if t.PkgPath.Name() != v.PkgPath.Name() {
1466 return false
1467 }
1468 for i := range t.Fields {
1469 tf := &t.Fields[i]
1470 vf := &v.Fields[i]
1471 if tf.Name.Name() != vf.Name.Name() {
1472 return false
1473 }
1474 if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
1475 return false
1476 }
1477 if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
1478 return false
1479 }
1480 if tf.Offset != vf.Offset {
1481 return false
1482 }
1483 if tf.Embedded() != vf.Embedded() {
1484 return false
1485 }
1486 }
1487 return true
1488 }
1489
1490 return false
1491 }
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 func typelinks() (sections []unsafe.Pointer, offset [][]int32)
1513
1514 func rtypeOff(section unsafe.Pointer, off int32) *abi.Type {
1515 return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0"))
1516 }
1517
1518
1519
1520
1521
1522 func typesByString(s string) []*abi.Type {
1523 sections, offset := typelinks()
1524 var ret []*abi.Type
1525
1526 for offsI, offs := range offset {
1527 section := sections[offsI]
1528
1529
1530
1531 i, j := 0, len(offs)
1532 for i < j {
1533 h := i + (j-i)>>1
1534
1535 if !(stringFor(rtypeOff(section, offs[h])) >= s) {
1536 i = h + 1
1537 } else {
1538 j = h
1539 }
1540 }
1541
1542
1543
1544
1545
1546 for j := i; j < len(offs); j++ {
1547 typ := rtypeOff(section, offs[j])
1548 if stringFor(typ) != s {
1549 break
1550 }
1551 ret = append(ret, typ)
1552 }
1553 }
1554 return ret
1555 }
1556
1557
1558 var lookupCache sync.Map
1559
1560
1561
1562
1563 type cacheKey struct {
1564 kind Kind
1565 t1 *abi.Type
1566 t2 *abi.Type
1567 extra uintptr
1568 }
1569
1570
1571
1572
1573 var funcLookupCache struct {
1574 sync.Mutex
1575
1576
1577
1578 m sync.Map
1579 }
1580
1581
1582
1583
1584
1585
1586 func ChanOf(dir ChanDir, t Type) Type {
1587 typ := t.common()
1588
1589
1590 ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
1591 if ch, ok := lookupCache.Load(ckey); ok {
1592 return ch.(*rtype)
1593 }
1594
1595
1596 if typ.Size_ >= 1<<16 {
1597 panic("reflect.ChanOf: element size too large")
1598 }
1599
1600
1601 var s string
1602 switch dir {
1603 default:
1604 panic("reflect.ChanOf: invalid dir")
1605 case SendDir:
1606 s = "chan<- " + stringFor(typ)
1607 case RecvDir:
1608 s = "<-chan " + stringFor(typ)
1609 case BothDir:
1610 typeStr := stringFor(typ)
1611 if typeStr[0] == '<' {
1612
1613
1614
1615
1616 s = "chan (" + typeStr + ")"
1617 } else {
1618 s = "chan " + typeStr
1619 }
1620 }
1621 for _, tt := range typesByString(s) {
1622 ch := (*chanType)(unsafe.Pointer(tt))
1623 if ch.Elem == typ && ch.Dir == abi.ChanDir(dir) {
1624 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
1625 return ti.(Type)
1626 }
1627 }
1628
1629
1630 var ichan any = (chan unsafe.Pointer)(nil)
1631 prototype := *(**chanType)(unsafe.Pointer(&ichan))
1632 ch := *prototype
1633 ch.TFlag = abi.TFlagRegularMemory
1634 ch.Dir = abi.ChanDir(dir)
1635 ch.Str = resolveReflectName(newName(s, "", false, false))
1636 ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
1637 ch.Elem = typ
1638
1639 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&ch.Type))
1640 return ti.(Type)
1641 }
1642
1643
1644
1645
1646
1647
1648
1649 func MapOf(key, elem Type) Type {
1650 ktyp := key.common()
1651 etyp := elem.common()
1652
1653 if ktyp.Equal == nil {
1654 panic("reflect.MapOf: invalid key type " + stringFor(ktyp))
1655 }
1656
1657
1658 ckey := cacheKey{Map, ktyp, etyp, 0}
1659 if mt, ok := lookupCache.Load(ckey); ok {
1660 return mt.(Type)
1661 }
1662
1663
1664 s := "map[" + stringFor(ktyp) + "]" + stringFor(etyp)
1665 for _, tt := range typesByString(s) {
1666 mt := (*mapType)(unsafe.Pointer(tt))
1667 if mt.Key == ktyp && mt.Elem == etyp {
1668 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
1669 return ti.(Type)
1670 }
1671 }
1672
1673
1674
1675
1676 var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil)
1677 mt := **(**mapType)(unsafe.Pointer(&imap))
1678 mt.Str = resolveReflectName(newName(s, "", false, false))
1679 mt.TFlag = 0
1680 mt.Hash = fnv1(etyp.Hash, 'm', byte(ktyp.Hash>>24), byte(ktyp.Hash>>16), byte(ktyp.Hash>>8), byte(ktyp.Hash))
1681 mt.Key = ktyp
1682 mt.Elem = etyp
1683 mt.Bucket = bucketOf(ktyp, etyp)
1684 mt.Hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
1685 return typehash(ktyp, p, seed)
1686 }
1687 mt.Flags = 0
1688 if ktyp.Size_ > maxKeySize {
1689 mt.KeySize = uint8(goarch.PtrSize)
1690 mt.Flags |= 1
1691 } else {
1692 mt.KeySize = uint8(ktyp.Size_)
1693 }
1694 if etyp.Size_ > maxValSize {
1695 mt.ValueSize = uint8(goarch.PtrSize)
1696 mt.Flags |= 2
1697 } else {
1698 mt.MapType.ValueSize = uint8(etyp.Size_)
1699 }
1700 mt.MapType.BucketSize = uint16(mt.Bucket.Size_)
1701 if isReflexive(ktyp) {
1702 mt.Flags |= 4
1703 }
1704 if needKeyUpdate(ktyp) {
1705 mt.Flags |= 8
1706 }
1707 if hashMightPanic(ktyp) {
1708 mt.Flags |= 16
1709 }
1710 mt.PtrToThis = 0
1711
1712 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&mt.Type))
1713 return ti.(Type)
1714 }
1715
1716 var funcTypes []Type
1717 var funcTypesMutex sync.Mutex
1718
1719 func initFuncTypes(n int) Type {
1720 funcTypesMutex.Lock()
1721 defer funcTypesMutex.Unlock()
1722 if n >= len(funcTypes) {
1723 newFuncTypes := make([]Type, n+1)
1724 copy(newFuncTypes, funcTypes)
1725 funcTypes = newFuncTypes
1726 }
1727 if funcTypes[n] != nil {
1728 return funcTypes[n]
1729 }
1730
1731 funcTypes[n] = StructOf([]StructField{
1732 {
1733 Name: "FuncType",
1734 Type: TypeOf(funcType{}),
1735 },
1736 {
1737 Name: "Args",
1738 Type: ArrayOf(n, TypeOf(&rtype{})),
1739 },
1740 })
1741 return funcTypes[n]
1742 }
1743
1744
1745
1746
1747
1748
1749
1750
1751 func FuncOf(in, out []Type, variadic bool) Type {
1752 if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
1753 panic("reflect.FuncOf: last arg of variadic func must be slice")
1754 }
1755
1756
1757 var ifunc any = (func())(nil)
1758 prototype := *(**funcType)(unsafe.Pointer(&ifunc))
1759 n := len(in) + len(out)
1760
1761 if n > 128 {
1762 panic("reflect.FuncOf: too many arguments")
1763 }
1764
1765 o := New(initFuncTypes(n)).Elem()
1766 ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
1767 args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
1768 *ft = *prototype
1769
1770
1771 var hash uint32
1772 for _, in := range in {
1773 t := in.(*rtype)
1774 args = append(args, t)
1775 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1776 }
1777 if variadic {
1778 hash = fnv1(hash, 'v')
1779 }
1780 hash = fnv1(hash, '.')
1781 for _, out := range out {
1782 t := out.(*rtype)
1783 args = append(args, t)
1784 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1785 }
1786
1787 ft.TFlag = 0
1788 ft.Hash = hash
1789 ft.InCount = uint16(len(in))
1790 ft.OutCount = uint16(len(out))
1791 if variadic {
1792 ft.OutCount |= 1 << 15
1793 }
1794
1795
1796 if ts, ok := funcLookupCache.m.Load(hash); ok {
1797 for _, t := range ts.([]*abi.Type) {
1798 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1799 return toRType(t)
1800 }
1801 }
1802 }
1803
1804
1805 funcLookupCache.Lock()
1806 defer funcLookupCache.Unlock()
1807 if ts, ok := funcLookupCache.m.Load(hash); ok {
1808 for _, t := range ts.([]*abi.Type) {
1809 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1810 return toRType(t)
1811 }
1812 }
1813 }
1814
1815 addToCache := func(tt *abi.Type) Type {
1816 var rts []*abi.Type
1817 if rti, ok := funcLookupCache.m.Load(hash); ok {
1818 rts = rti.([]*abi.Type)
1819 }
1820 funcLookupCache.m.Store(hash, append(rts, tt))
1821 return toType(tt)
1822 }
1823
1824
1825 str := funcStr(ft)
1826 for _, tt := range typesByString(str) {
1827 if haveIdenticalUnderlyingType(&ft.Type, tt, true) {
1828 return addToCache(tt)
1829 }
1830 }
1831
1832
1833 ft.Str = resolveReflectName(newName(str, "", false, false))
1834 ft.PtrToThis = 0
1835 return addToCache(&ft.Type)
1836 }
1837 func stringFor(t *abi.Type) string {
1838 return toRType(t).String()
1839 }
1840
1841
1842 func funcStr(ft *funcType) string {
1843 repr := make([]byte, 0, 64)
1844 repr = append(repr, "func("...)
1845 for i, t := range ft.InSlice() {
1846 if i > 0 {
1847 repr = append(repr, ", "...)
1848 }
1849 if ft.IsVariadic() && i == int(ft.InCount)-1 {
1850 repr = append(repr, "..."...)
1851 repr = append(repr, stringFor((*sliceType)(unsafe.Pointer(t)).Elem)...)
1852 } else {
1853 repr = append(repr, stringFor(t)...)
1854 }
1855 }
1856 repr = append(repr, ')')
1857 out := ft.OutSlice()
1858 if len(out) == 1 {
1859 repr = append(repr, ' ')
1860 } else if len(out) > 1 {
1861 repr = append(repr, " ("...)
1862 }
1863 for i, t := range out {
1864 if i > 0 {
1865 repr = append(repr, ", "...)
1866 }
1867 repr = append(repr, stringFor(t)...)
1868 }
1869 if len(out) > 1 {
1870 repr = append(repr, ')')
1871 }
1872 return string(repr)
1873 }
1874
1875
1876
1877 func isReflexive(t *abi.Type) bool {
1878 switch Kind(t.Kind()) {
1879 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer:
1880 return true
1881 case Float32, Float64, Complex64, Complex128, Interface:
1882 return false
1883 case Array:
1884 tt := (*arrayType)(unsafe.Pointer(t))
1885 return isReflexive(tt.Elem)
1886 case Struct:
1887 tt := (*structType)(unsafe.Pointer(t))
1888 for _, f := range tt.Fields {
1889 if !isReflexive(f.Typ) {
1890 return false
1891 }
1892 }
1893 return true
1894 default:
1895
1896 panic("isReflexive called on non-key type " + stringFor(t))
1897 }
1898 }
1899
1900
1901 func needKeyUpdate(t *abi.Type) bool {
1902 switch Kind(t.Kind()) {
1903 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer:
1904 return false
1905 case Float32, Float64, Complex64, Complex128, Interface, String:
1906
1907
1908
1909 return true
1910 case Array:
1911 tt := (*arrayType)(unsafe.Pointer(t))
1912 return needKeyUpdate(tt.Elem)
1913 case Struct:
1914 tt := (*structType)(unsafe.Pointer(t))
1915 for _, f := range tt.Fields {
1916 if needKeyUpdate(f.Typ) {
1917 return true
1918 }
1919 }
1920 return false
1921 default:
1922
1923 panic("needKeyUpdate called on non-key type " + stringFor(t))
1924 }
1925 }
1926
1927
1928 func hashMightPanic(t *abi.Type) bool {
1929 switch Kind(t.Kind()) {
1930 case Interface:
1931 return true
1932 case Array:
1933 tt := (*arrayType)(unsafe.Pointer(t))
1934 return hashMightPanic(tt.Elem)
1935 case Struct:
1936 tt := (*structType)(unsafe.Pointer(t))
1937 for _, f := range tt.Fields {
1938 if hashMightPanic(f.Typ) {
1939 return true
1940 }
1941 }
1942 return false
1943 default:
1944 return false
1945 }
1946 }
1947
1948
1949
1950
1951
1952 const (
1953 bucketSize uintptr = abi.MapBucketCount
1954 maxKeySize uintptr = abi.MapMaxKeyBytes
1955 maxValSize uintptr = abi.MapMaxElemBytes
1956 )
1957
1958 func bucketOf(ktyp, etyp *abi.Type) *abi.Type {
1959 if ktyp.Size_ > maxKeySize {
1960 ktyp = ptrTo(ktyp)
1961 }
1962 if etyp.Size_ > maxValSize {
1963 etyp = ptrTo(etyp)
1964 }
1965
1966
1967
1968
1969
1970
1971 var gcdata *byte
1972 var ptrdata uintptr
1973
1974 size := bucketSize*(1+ktyp.Size_+etyp.Size_) + goarch.PtrSize
1975 if size&uintptr(ktyp.Align_-1) != 0 || size&uintptr(etyp.Align_-1) != 0 {
1976 panic("reflect: bad size computation in MapOf")
1977 }
1978
1979 if ktyp.PtrBytes != 0 || etyp.PtrBytes != 0 {
1980 nptr := (bucketSize*(1+ktyp.Size_+etyp.Size_) + goarch.PtrSize) / goarch.PtrSize
1981 n := (nptr + 7) / 8
1982
1983
1984 n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
1985 mask := make([]byte, n)
1986 base := bucketSize / goarch.PtrSize
1987
1988 if ktyp.PtrBytes != 0 {
1989 emitGCMask(mask, base, ktyp, bucketSize)
1990 }
1991 base += bucketSize * ktyp.Size_ / goarch.PtrSize
1992
1993 if etyp.PtrBytes != 0 {
1994 emitGCMask(mask, base, etyp, bucketSize)
1995 }
1996 base += bucketSize * etyp.Size_ / goarch.PtrSize
1997
1998 word := base
1999 mask[word/8] |= 1 << (word % 8)
2000 gcdata = &mask[0]
2001 ptrdata = (word + 1) * goarch.PtrSize
2002
2003
2004 if ptrdata != size {
2005 panic("reflect: bad layout computation in MapOf")
2006 }
2007 }
2008
2009 b := &abi.Type{
2010 Align_: goarch.PtrSize,
2011 Size_: size,
2012 Kind_: uint8(Struct),
2013 PtrBytes: ptrdata,
2014 GCData: gcdata,
2015 }
2016 s := "bucket(" + stringFor(ktyp) + "," + stringFor(etyp) + ")"
2017 b.Str = resolveReflectName(newName(s, "", false, false))
2018 return b
2019 }
2020
2021 func (t *rtype) gcSlice(begin, end uintptr) []byte {
2022 return (*[1 << 30]byte)(unsafe.Pointer(t.t.GCData))[begin:end:end]
2023 }
2024
2025
2026
2027 func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
2028 if typ.Kind_&kindGCProg != 0 {
2029 panic("reflect: unexpected GC program")
2030 }
2031 ptrs := typ.PtrBytes / goarch.PtrSize
2032 words := typ.Size_ / goarch.PtrSize
2033 mask := typ.GcSlice(0, (ptrs+7)/8)
2034 for j := uintptr(0); j < ptrs; j++ {
2035 if (mask[j/8]>>(j%8))&1 != 0 {
2036 for i := uintptr(0); i < n; i++ {
2037 k := base + i*words + j
2038 out[k/8] |= 1 << (k % 8)
2039 }
2040 }
2041 }
2042 }
2043
2044
2045
2046 func appendGCProg(dst []byte, typ *abi.Type) []byte {
2047 if typ.Kind_&kindGCProg != 0 {
2048
2049 n := uintptr(*(*uint32)(unsafe.Pointer(typ.GCData)))
2050 prog := typ.GcSlice(4, 4+n-1)
2051 return append(dst, prog...)
2052 }
2053
2054
2055 ptrs := typ.PtrBytes / goarch.PtrSize
2056 mask := typ.GcSlice(0, (ptrs+7)/8)
2057
2058
2059 for ; ptrs > 120; ptrs -= 120 {
2060 dst = append(dst, 120)
2061 dst = append(dst, mask[:15]...)
2062 mask = mask[15:]
2063 }
2064
2065 dst = append(dst, byte(ptrs))
2066 dst = append(dst, mask...)
2067 return dst
2068 }
2069
2070
2071
2072 func SliceOf(t Type) Type {
2073 typ := t.common()
2074
2075
2076 ckey := cacheKey{Slice, typ, nil, 0}
2077 if slice, ok := lookupCache.Load(ckey); ok {
2078 return slice.(Type)
2079 }
2080
2081
2082 s := "[]" + stringFor(typ)
2083 for _, tt := range typesByString(s) {
2084 slice := (*sliceType)(unsafe.Pointer(tt))
2085 if slice.Elem == typ {
2086 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2087 return ti.(Type)
2088 }
2089 }
2090
2091
2092 var islice any = ([]unsafe.Pointer)(nil)
2093 prototype := *(**sliceType)(unsafe.Pointer(&islice))
2094 slice := *prototype
2095 slice.TFlag = 0
2096 slice.Str = resolveReflectName(newName(s, "", false, false))
2097 slice.Hash = fnv1(typ.Hash, '[')
2098 slice.Elem = typ
2099 slice.PtrToThis = 0
2100
2101 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&slice.Type))
2102 return ti.(Type)
2103 }
2104
2105
2106
2107
2108 var structLookupCache struct {
2109 sync.Mutex
2110
2111
2112
2113 m sync.Map
2114 }
2115
2116 type structTypeUncommon struct {
2117 structType
2118 u uncommonType
2119 }
2120
2121
2122 func isLetter(ch rune) bool {
2123 return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
2124 }
2125
2126
2127
2128
2129
2130
2131
2132 func isValidFieldName(fieldName string) bool {
2133 for i, c := range fieldName {
2134 if i == 0 && !isLetter(c) {
2135 return false
2136 }
2137
2138 if !(isLetter(c) || unicode.IsDigit(c)) {
2139 return false
2140 }
2141 }
2142
2143 return len(fieldName) > 0
2144 }
2145
2146
2147
2148
2149
2150
2151
2152
2153 func StructOf(fields []StructField) Type {
2154 var (
2155 hash = fnv1(0, []byte("struct {")...)
2156 size uintptr
2157 typalign uint8
2158 comparable = true
2159 methods []abi.Method
2160
2161 fs = make([]structField, len(fields))
2162 repr = make([]byte, 0, 64)
2163 fset = map[string]struct{}{}
2164
2165 hasGCProg = false
2166 )
2167
2168 lastzero := uintptr(0)
2169 repr = append(repr, "struct {"...)
2170 pkgpath := ""
2171 for i, field := range fields {
2172 if field.Name == "" {
2173 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
2174 }
2175 if !isValidFieldName(field.Name) {
2176 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
2177 }
2178 if field.Type == nil {
2179 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
2180 }
2181 f, fpkgpath := runtimeStructField(field)
2182 ft := f.Typ
2183 if ft.Kind_&kindGCProg != 0 {
2184 hasGCProg = true
2185 }
2186 if fpkgpath != "" {
2187 if pkgpath == "" {
2188 pkgpath = fpkgpath
2189 } else if pkgpath != fpkgpath {
2190 panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
2191 }
2192 }
2193
2194
2195 name := f.Name.Name()
2196 hash = fnv1(hash, []byte(name)...)
2197 repr = append(repr, (" " + name)...)
2198 if f.Embedded() {
2199
2200 if f.Typ.Kind() == abi.Pointer {
2201
2202 elem := ft.Elem()
2203 if k := elem.Kind(); k == abi.Pointer || k == abi.Interface {
2204 panic("reflect.StructOf: illegal embedded field type " + stringFor(ft))
2205 }
2206 }
2207
2208 switch Kind(f.Typ.Kind()) {
2209 case Interface:
2210 ift := (*interfaceType)(unsafe.Pointer(ft))
2211 for im, m := range ift.Methods {
2212 if pkgPath(ift.nameOff(m.Name)) != "" {
2213
2214 panic("reflect: embedded interface with unexported method(s) not implemented")
2215 }
2216
2217 var (
2218 mtyp = ift.typeOff(m.Typ)
2219 ifield = i
2220 imethod = im
2221 ifn Value
2222 tfn Value
2223 )
2224
2225 if ft.Kind_&kindDirectIface != 0 {
2226 tfn = MakeFunc(toRType(mtyp), func(in []Value) []Value {
2227 var args []Value
2228 var recv = in[0]
2229 if len(in) > 1 {
2230 args = in[1:]
2231 }
2232 return recv.Field(ifield).Method(imethod).Call(args)
2233 })
2234 ifn = MakeFunc(toRType(mtyp), func(in []Value) []Value {
2235 var args []Value
2236 var recv = in[0]
2237 if len(in) > 1 {
2238 args = in[1:]
2239 }
2240 return recv.Field(ifield).Method(imethod).Call(args)
2241 })
2242 } else {
2243 tfn = MakeFunc(toRType(mtyp), func(in []Value) []Value {
2244 var args []Value
2245 var recv = in[0]
2246 if len(in) > 1 {
2247 args = in[1:]
2248 }
2249 return recv.Field(ifield).Method(imethod).Call(args)
2250 })
2251 ifn = MakeFunc(toRType(mtyp), func(in []Value) []Value {
2252 var args []Value
2253 var recv = Indirect(in[0])
2254 if len(in) > 1 {
2255 args = in[1:]
2256 }
2257 return recv.Field(ifield).Method(imethod).Call(args)
2258 })
2259 }
2260
2261 methods = append(methods, abi.Method{
2262 Name: resolveReflectName(ift.nameOff(m.Name)),
2263 Mtyp: resolveReflectType(mtyp),
2264 Ifn: resolveReflectText(unsafe.Pointer(&ifn)),
2265 Tfn: resolveReflectText(unsafe.Pointer(&tfn)),
2266 })
2267 }
2268 case Pointer:
2269 ptr := (*ptrType)(unsafe.Pointer(ft))
2270 if unt := ptr.Uncommon(); unt != nil {
2271 if i > 0 && unt.Mcount > 0 {
2272
2273 panic("reflect: embedded type with methods not implemented if type is not first field")
2274 }
2275 if len(fields) > 1 {
2276 panic("reflect: embedded type with methods not implemented if there is more than one field")
2277 }
2278 for _, m := range unt.Methods() {
2279 mname := nameOffFor(ft, m.Name)
2280 if pkgPath(mname) != "" {
2281
2282
2283 panic("reflect: embedded interface with unexported method(s) not implemented")
2284 }
2285 methods = append(methods, abi.Method{
2286 Name: resolveReflectName(mname),
2287 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2288 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2289 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2290 })
2291 }
2292 }
2293 if unt := ptr.Elem.Uncommon(); unt != nil {
2294 for _, m := range unt.Methods() {
2295 mname := nameOffFor(ft, m.Name)
2296 if pkgPath(mname) != "" {
2297
2298
2299 panic("reflect: embedded interface with unexported method(s) not implemented")
2300 }
2301 methods = append(methods, abi.Method{
2302 Name: resolveReflectName(mname),
2303 Mtyp: resolveReflectType(typeOffFor(ptr.Elem, m.Mtyp)),
2304 Ifn: resolveReflectText(textOffFor(ptr.Elem, m.Ifn)),
2305 Tfn: resolveReflectText(textOffFor(ptr.Elem, m.Tfn)),
2306 })
2307 }
2308 }
2309 default:
2310 if unt := ft.Uncommon(); unt != nil {
2311 if i > 0 && unt.Mcount > 0 {
2312
2313 panic("reflect: embedded type with methods not implemented if type is not first field")
2314 }
2315 if len(fields) > 1 && ft.Kind_&kindDirectIface != 0 {
2316 panic("reflect: embedded type with methods not implemented for non-pointer type")
2317 }
2318 for _, m := range unt.Methods() {
2319 mname := nameOffFor(ft, m.Name)
2320 if pkgPath(mname) != "" {
2321
2322
2323 panic("reflect: embedded interface with unexported method(s) not implemented")
2324 }
2325 methods = append(methods, abi.Method{
2326 Name: resolveReflectName(mname),
2327 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2328 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2329 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2330 })
2331
2332 }
2333 }
2334 }
2335 }
2336 if _, dup := fset[name]; dup && name != "_" {
2337 panic("reflect.StructOf: duplicate field " + name)
2338 }
2339 fset[name] = struct{}{}
2340
2341 hash = fnv1(hash, byte(ft.Hash>>24), byte(ft.Hash>>16), byte(ft.Hash>>8), byte(ft.Hash))
2342
2343 repr = append(repr, (" " + stringFor(ft))...)
2344 if f.Name.HasTag() {
2345 hash = fnv1(hash, []byte(f.Name.Tag())...)
2346 repr = append(repr, (" " + strconv.Quote(f.Name.Tag()))...)
2347 }
2348 if i < len(fields)-1 {
2349 repr = append(repr, ';')
2350 }
2351
2352 comparable = comparable && (ft.Equal != nil)
2353
2354 offset := align(size, uintptr(ft.Align_))
2355 if offset < size {
2356 panic("reflect.StructOf: struct size would exceed virtual address space")
2357 }
2358 if ft.Align_ > typalign {
2359 typalign = ft.Align_
2360 }
2361 size = offset + ft.Size_
2362 if size < offset {
2363 panic("reflect.StructOf: struct size would exceed virtual address space")
2364 }
2365 f.Offset = offset
2366
2367 if ft.Size_ == 0 {
2368 lastzero = size
2369 }
2370
2371 fs[i] = f
2372 }
2373
2374 if size > 0 && lastzero == size {
2375
2376
2377
2378
2379
2380 size++
2381 if size == 0 {
2382 panic("reflect.StructOf: struct size would exceed virtual address space")
2383 }
2384 }
2385
2386 var typ *structType
2387 var ut *uncommonType
2388
2389 if len(methods) == 0 {
2390 t := new(structTypeUncommon)
2391 typ = &t.structType
2392 ut = &t.u
2393 } else {
2394
2395
2396
2397
2398
2399 tt := New(StructOf([]StructField{
2400 {Name: "S", Type: TypeOf(structType{})},
2401 {Name: "U", Type: TypeOf(uncommonType{})},
2402 {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
2403 }))
2404
2405 typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer())
2406 ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer())
2407
2408 copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]abi.Method), methods)
2409 }
2410
2411
2412
2413
2414 ut.Mcount = uint16(len(methods))
2415 ut.Xcount = ut.Mcount
2416 ut.Moff = uint32(unsafe.Sizeof(uncommonType{}))
2417
2418 if len(fs) > 0 {
2419 repr = append(repr, ' ')
2420 }
2421 repr = append(repr, '}')
2422 hash = fnv1(hash, '}')
2423 str := string(repr)
2424
2425
2426 s := align(size, uintptr(typalign))
2427 if s < size {
2428 panic("reflect.StructOf: struct size would exceed virtual address space")
2429 }
2430 size = s
2431
2432
2433 var istruct any = struct{}{}
2434 prototype := *(**structType)(unsafe.Pointer(&istruct))
2435 *typ = *prototype
2436 typ.Fields = fs
2437 if pkgpath != "" {
2438 typ.PkgPath = newName(pkgpath, "", false, false)
2439 }
2440
2441
2442 if ts, ok := structLookupCache.m.Load(hash); ok {
2443 for _, st := range ts.([]Type) {
2444 t := st.common()
2445 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2446 return toType(t)
2447 }
2448 }
2449 }
2450
2451
2452 structLookupCache.Lock()
2453 defer structLookupCache.Unlock()
2454 if ts, ok := structLookupCache.m.Load(hash); ok {
2455 for _, st := range ts.([]Type) {
2456 t := st.common()
2457 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2458 return toType(t)
2459 }
2460 }
2461 }
2462
2463 addToCache := func(t Type) Type {
2464 var ts []Type
2465 if ti, ok := structLookupCache.m.Load(hash); ok {
2466 ts = ti.([]Type)
2467 }
2468 structLookupCache.m.Store(hash, append(ts, t))
2469 return t
2470 }
2471
2472
2473 for _, t := range typesByString(str) {
2474 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2475
2476
2477
2478 return addToCache(toType(t))
2479 }
2480 }
2481
2482 typ.Str = resolveReflectName(newName(str, "", false, false))
2483 typ.TFlag = 0
2484 typ.Hash = hash
2485 typ.Size_ = size
2486 typ.PtrBytes = typeptrdata(&typ.Type)
2487 typ.Align_ = typalign
2488 typ.FieldAlign_ = typalign
2489 typ.PtrToThis = 0
2490 if len(methods) > 0 {
2491 typ.TFlag |= abi.TFlagUncommon
2492 }
2493
2494 if hasGCProg {
2495 lastPtrField := 0
2496 for i, ft := range fs {
2497 if ft.Typ.Pointers() {
2498 lastPtrField = i
2499 }
2500 }
2501 prog := []byte{0, 0, 0, 0}
2502 var off uintptr
2503 for i, ft := range fs {
2504 if i > lastPtrField {
2505
2506
2507 break
2508 }
2509 if !ft.Typ.Pointers() {
2510
2511 continue
2512 }
2513
2514 if ft.Offset > off {
2515 n := (ft.Offset - off) / goarch.PtrSize
2516 prog = append(prog, 0x01, 0x00)
2517 if n > 1 {
2518 prog = append(prog, 0x81)
2519 prog = appendVarint(prog, n-1)
2520 }
2521 off = ft.Offset
2522 }
2523
2524 prog = appendGCProg(prog, ft.Typ)
2525 off += ft.Typ.PtrBytes
2526 }
2527 prog = append(prog, 0)
2528 *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
2529 typ.Kind_ |= kindGCProg
2530 typ.GCData = &prog[0]
2531 } else {
2532 typ.Kind_ &^= kindGCProg
2533 bv := new(bitVector)
2534 addTypeBits(bv, 0, &typ.Type)
2535 if len(bv.data) > 0 {
2536 typ.GCData = &bv.data[0]
2537 }
2538 }
2539 typ.Equal = nil
2540 if comparable {
2541 typ.Equal = func(p, q unsafe.Pointer) bool {
2542 for _, ft := range typ.Fields {
2543 pi := add(p, ft.Offset, "&x.field safe")
2544 qi := add(q, ft.Offset, "&x.field safe")
2545 if !ft.Typ.Equal(pi, qi) {
2546 return false
2547 }
2548 }
2549 return true
2550 }
2551 }
2552
2553 switch {
2554 case len(fs) == 1 && !ifaceIndir(fs[0].Typ):
2555
2556 typ.Kind_ |= kindDirectIface
2557 default:
2558 typ.Kind_ &^= kindDirectIface
2559 }
2560
2561 return addToCache(toType(&typ.Type))
2562 }
2563
2564
2565
2566
2567 func runtimeStructField(field StructField) (structField, string) {
2568 if field.Anonymous && field.PkgPath != "" {
2569 panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
2570 }
2571
2572 if field.IsExported() {
2573
2574
2575 c := field.Name[0]
2576 if 'a' <= c && c <= 'z' || c == '_' {
2577 panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
2578 }
2579 }
2580
2581 resolveReflectType(field.Type.common())
2582 f := structField{
2583 Name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
2584 Typ: field.Type.common(),
2585 Offset: 0,
2586 }
2587 return f, field.PkgPath
2588 }
2589
2590
2591
2592
2593 func typeptrdata(t *abi.Type) uintptr {
2594 switch t.Kind() {
2595 case abi.Struct:
2596 st := (*structType)(unsafe.Pointer(t))
2597
2598 field := -1
2599 for i := range st.Fields {
2600 ft := st.Fields[i].Typ
2601 if ft.Pointers() {
2602 field = i
2603 }
2604 }
2605 if field == -1 {
2606 return 0
2607 }
2608 f := st.Fields[field]
2609 return f.Offset + f.Typ.PtrBytes
2610
2611 default:
2612 panic("reflect.typeptrdata: unexpected type, " + stringFor(t))
2613 }
2614 }
2615
2616
2617 const maxPtrmaskBytes = 2048
2618
2619
2620
2621
2622
2623
2624 func ArrayOf(length int, elem Type) Type {
2625 if length < 0 {
2626 panic("reflect: negative length passed to ArrayOf")
2627 }
2628
2629 typ := elem.common()
2630
2631
2632 ckey := cacheKey{Array, typ, nil, uintptr(length)}
2633 if array, ok := lookupCache.Load(ckey); ok {
2634 return array.(Type)
2635 }
2636
2637
2638 s := "[" + strconv.Itoa(length) + "]" + stringFor(typ)
2639 for _, tt := range typesByString(s) {
2640 array := (*arrayType)(unsafe.Pointer(tt))
2641 if array.Elem == typ {
2642 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2643 return ti.(Type)
2644 }
2645 }
2646
2647
2648 var iarray any = [1]unsafe.Pointer{}
2649 prototype := *(**arrayType)(unsafe.Pointer(&iarray))
2650 array := *prototype
2651 array.TFlag = typ.TFlag & abi.TFlagRegularMemory
2652 array.Str = resolveReflectName(newName(s, "", false, false))
2653 array.Hash = fnv1(typ.Hash, '[')
2654 for n := uint32(length); n > 0; n >>= 8 {
2655 array.Hash = fnv1(array.Hash, byte(n))
2656 }
2657 array.Hash = fnv1(array.Hash, ']')
2658 array.Elem = typ
2659 array.PtrToThis = 0
2660 if typ.Size_ > 0 {
2661 max := ^uintptr(0) / typ.Size_
2662 if uintptr(length) > max {
2663 panic("reflect.ArrayOf: array size would exceed virtual address space")
2664 }
2665 }
2666 array.Size_ = typ.Size_ * uintptr(length)
2667 if length > 0 && typ.PtrBytes != 0 {
2668 array.PtrBytes = typ.Size_*uintptr(length-1) + typ.PtrBytes
2669 }
2670 array.Align_ = typ.Align_
2671 array.FieldAlign_ = typ.FieldAlign_
2672 array.Len = uintptr(length)
2673 array.Slice = &(SliceOf(elem).(*rtype).t)
2674
2675 switch {
2676 case typ.PtrBytes == 0 || array.Size_ == 0:
2677
2678 array.GCData = nil
2679 array.PtrBytes = 0
2680
2681 case length == 1:
2682
2683 array.Kind_ |= typ.Kind_ & kindGCProg
2684 array.GCData = typ.GCData
2685 array.PtrBytes = typ.PtrBytes
2686
2687 case typ.Kind_&kindGCProg == 0 && array.Size_ <= maxPtrmaskBytes*8*goarch.PtrSize:
2688
2689
2690
2691 n := (array.PtrBytes/goarch.PtrSize + 7) / 8
2692
2693 n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
2694 mask := make([]byte, n)
2695 emitGCMask(mask, 0, typ, array.Len)
2696 array.GCData = &mask[0]
2697
2698 default:
2699
2700
2701 prog := []byte{0, 0, 0, 0}
2702 prog = appendGCProg(prog, typ)
2703
2704 elemPtrs := typ.PtrBytes / goarch.PtrSize
2705 elemWords := typ.Size_ / goarch.PtrSize
2706 if elemPtrs < elemWords {
2707
2708 prog = append(prog, 0x01, 0x00)
2709 if elemPtrs+1 < elemWords {
2710 prog = append(prog, 0x81)
2711 prog = appendVarint(prog, elemWords-elemPtrs-1)
2712 }
2713 }
2714
2715 if elemWords < 0x80 {
2716 prog = append(prog, byte(elemWords|0x80))
2717 } else {
2718 prog = append(prog, 0x80)
2719 prog = appendVarint(prog, elemWords)
2720 }
2721 prog = appendVarint(prog, uintptr(length)-1)
2722 prog = append(prog, 0)
2723 *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
2724 array.Kind_ |= kindGCProg
2725 array.GCData = &prog[0]
2726 array.PtrBytes = array.Size_
2727 }
2728
2729 etyp := typ
2730 esize := etyp.Size()
2731
2732 array.Equal = nil
2733 if eequal := etyp.Equal; eequal != nil {
2734 array.Equal = func(p, q unsafe.Pointer) bool {
2735 for i := 0; i < length; i++ {
2736 pi := arrayAt(p, i, esize, "i < length")
2737 qi := arrayAt(q, i, esize, "i < length")
2738 if !eequal(pi, qi) {
2739 return false
2740 }
2741
2742 }
2743 return true
2744 }
2745 }
2746
2747 switch {
2748 case length == 1 && !ifaceIndir(typ):
2749
2750 array.Kind_ |= kindDirectIface
2751 default:
2752 array.Kind_ &^= kindDirectIface
2753 }
2754
2755 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
2756 return ti.(Type)
2757 }
2758
2759 func appendVarint(x []byte, v uintptr) []byte {
2760 for ; v >= 0x80; v >>= 7 {
2761 x = append(x, byte(v|0x80))
2762 }
2763 x = append(x, byte(v))
2764 return x
2765 }
2766
2767
2768
2769
2770
2771
2772 func toType(t *abi.Type) Type {
2773 if t == nil {
2774 return nil
2775 }
2776 return toRType(t)
2777 }
2778
2779 type layoutKey struct {
2780 ftyp *funcType
2781 rcvr *abi.Type
2782 }
2783
2784 type layoutType struct {
2785 t *abi.Type
2786 framePool *sync.Pool
2787 abid abiDesc
2788 }
2789
2790 var layoutCache sync.Map
2791
2792
2793
2794
2795
2796
2797
2798
2799 func funcLayout(t *funcType, rcvr *abi.Type) (frametype *abi.Type, framePool *sync.Pool, abid abiDesc) {
2800 if t.Kind() != abi.Func {
2801 panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
2802 }
2803 if rcvr != nil && rcvr.Kind() == abi.Interface {
2804 panic("reflect: funcLayout with interface receiver " + stringFor(rcvr))
2805 }
2806 k := layoutKey{t, rcvr}
2807 if lti, ok := layoutCache.Load(k); ok {
2808 lt := lti.(layoutType)
2809 return lt.t, lt.framePool, lt.abid
2810 }
2811
2812
2813 abid = newAbiDesc(t, rcvr)
2814
2815
2816 x := &abi.Type{
2817 Align_: goarch.PtrSize,
2818
2819
2820
2821
2822 Size_: align(abid.retOffset+abid.ret.stackBytes, goarch.PtrSize),
2823 PtrBytes: uintptr(abid.stackPtrs.n) * goarch.PtrSize,
2824 }
2825 if abid.stackPtrs.n > 0 {
2826 x.GCData = &abid.stackPtrs.data[0]
2827 }
2828
2829 var s string
2830 if rcvr != nil {
2831 s = "methodargs(" + stringFor(rcvr) + ")(" + stringFor(&t.Type) + ")"
2832 } else {
2833 s = "funcargs(" + stringFor(&t.Type) + ")"
2834 }
2835 x.Str = resolveReflectName(newName(s, "", false, false))
2836
2837
2838 framePool = &sync.Pool{New: func() any {
2839 return unsafe_New(x)
2840 }}
2841 lti, _ := layoutCache.LoadOrStore(k, layoutType{
2842 t: x,
2843 framePool: framePool,
2844 abid: abid,
2845 })
2846 lt := lti.(layoutType)
2847 return lt.t, lt.framePool, lt.abid
2848 }
2849
2850
2851 func ifaceIndir(t *abi.Type) bool {
2852 return t.Kind_&kindDirectIface == 0
2853 }
2854
2855
2856 type bitVector struct {
2857 n uint32
2858 data []byte
2859 }
2860
2861
2862 func (bv *bitVector) append(bit uint8) {
2863 if bv.n%(8*goarch.PtrSize) == 0 {
2864
2865
2866
2867 for i := 0; i < goarch.PtrSize; i++ {
2868 bv.data = append(bv.data, 0)
2869 }
2870 }
2871 bv.data[bv.n/8] |= bit << (bv.n % 8)
2872 bv.n++
2873 }
2874
2875 func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
2876 if t.PtrBytes == 0 {
2877 return
2878 }
2879
2880 switch Kind(t.Kind_ & kindMask) {
2881 case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
2882
2883 for bv.n < uint32(offset/uintptr(goarch.PtrSize)) {
2884 bv.append(0)
2885 }
2886 bv.append(1)
2887
2888 case Interface:
2889
2890 for bv.n < uint32(offset/uintptr(goarch.PtrSize)) {
2891 bv.append(0)
2892 }
2893 bv.append(1)
2894 bv.append(1)
2895
2896 case Array:
2897
2898 tt := (*arrayType)(unsafe.Pointer(t))
2899 for i := 0; i < int(tt.Len); i++ {
2900 addTypeBits(bv, offset+uintptr(i)*tt.Elem.Size_, tt.Elem)
2901 }
2902
2903 case Struct:
2904
2905 tt := (*structType)(unsafe.Pointer(t))
2906 for i := range tt.Fields {
2907 f := &tt.Fields[i]
2908 addTypeBits(bv, offset+f.Offset, f.Typ)
2909 }
2910 }
2911 }
2912
View as plain text