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