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