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