libgo: Merge from revision 18783:00cce3a34d7e of master library.
[official-gcc.git] / libgo / go / reflect / type.go
blobf8e2c59b614db17f8f46f2b1d26b4d9d1c78d6c3
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package reflect implements run-time reflection, allowing a program to
6 // manipulate objects with arbitrary types. The typical use is to take a value
7 // with static type interface{} and extract its dynamic type information by
8 // calling TypeOf, which returns a Type.
9 //
10 // A call to ValueOf returns a Value representing the run-time data.
11 // Zero takes a Type and returns a Value representing a zero value
12 // for that type.
14 // See "The Laws of Reflection" for an introduction to reflection in Go:
15 // http://golang.org/doc/articles/laws_of_reflection.html
16 package reflect
18 import (
19 "strconv"
20 "sync"
21 "unsafe"
24 // Type is the representation of a Go type.
26 // Not all methods apply to all kinds of types. Restrictions,
27 // if any, are noted in the documentation for each method.
28 // Use the Kind method to find out the kind of type before
29 // calling kind-specific methods. Calling a method
30 // inappropriate to the kind of type causes a run-time panic.
31 type Type interface {
32 // Methods applicable to all types.
34 // Align returns the alignment in bytes of a value of
35 // this type when allocated in memory.
36 Align() int
38 // FieldAlign returns the alignment in bytes of a value of
39 // this type when used as a field in a struct.
40 FieldAlign() int
42 // Method returns the i'th method in the type's method set.
43 // It panics if i is not in the range [0, NumMethod()).
45 // For a non-interface type T or *T, the returned Method's Type and Func
46 // fields describe a function whose first argument is the receiver.
48 // For an interface type, the returned Method's Type field gives the
49 // method signature, without a receiver, and the Func field is nil.
50 Method(int) Method
52 // MethodByName returns the method with that name in the type's
53 // method set and a boolean indicating if the method was found.
55 // For a non-interface type T or *T, the returned Method's Type and Func
56 // fields describe a function whose first argument is the receiver.
58 // For an interface type, the returned Method's Type field gives the
59 // method signature, without a receiver, and the Func field is nil.
60 MethodByName(string) (Method, bool)
62 // NumMethod returns the number of methods in the type's method set.
63 NumMethod() int
65 // Name returns the type's name within its package.
66 // It returns an empty string for unnamed types.
67 Name() string
69 // PkgPath returns a named type's package path, that is, the import path
70 // that uniquely identifies the package, such as "encoding/base64".
71 // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int),
72 // the package path will be the empty string.
73 PkgPath() string
75 // Size returns the number of bytes needed to store
76 // a value of the given type; it is analogous to unsafe.Sizeof.
77 Size() uintptr
79 // String returns a string representation of the type.
80 // The string representation may use shortened package names
81 // (e.g., base64 instead of "encoding/base64") and is not
82 // guaranteed to be unique among types. To test for equality,
83 // compare the Types directly.
84 String() string
86 // Used internally by gccgo--the string retaining quoting.
87 rawString() string
89 // Kind returns the specific kind of this type.
90 Kind() Kind
92 // Implements returns true if the type implements the interface type u.
93 Implements(u Type) bool
95 // AssignableTo returns true if a value of the type is assignable to type u.
96 AssignableTo(u Type) bool
98 // ConvertibleTo returns true if a value of the type is convertible to type u.
99 ConvertibleTo(u Type) bool
101 // Methods applicable only to some types, depending on Kind.
102 // The methods allowed for each kind are:
104 // Int*, Uint*, Float*, Complex*: Bits
105 // Array: Elem, Len
106 // Chan: ChanDir, Elem
107 // Func: In, NumIn, Out, NumOut, IsVariadic.
108 // Map: Key, Elem
109 // Ptr: Elem
110 // Slice: Elem
111 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
113 // Bits returns the size of the type in bits.
114 // It panics if the type's Kind is not one of the
115 // sized or unsized Int, Uint, Float, or Complex kinds.
116 Bits() int
118 // ChanDir returns a channel type's direction.
119 // It panics if the type's Kind is not Chan.
120 ChanDir() ChanDir
122 // IsVariadic returns true if a function type's final input parameter
123 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
124 // implicit actual type []T.
126 // For concreteness, if t represents func(x int, y ... float64), then
128 // t.NumIn() == 2
129 // t.In(0) is the reflect.Type for "int"
130 // t.In(1) is the reflect.Type for "[]float64"
131 // t.IsVariadic() == true
133 // IsVariadic panics if the type's Kind is not Func.
134 IsVariadic() bool
136 // Elem returns a type's element type.
137 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
138 Elem() Type
140 // Field returns a struct type's i'th field.
141 // It panics if the type's Kind is not Struct.
142 // It panics if i is not in the range [0, NumField()).
143 Field(i int) StructField
145 // FieldByIndex returns the nested field corresponding
146 // to the index sequence. It is equivalent to calling Field
147 // successively for each index i.
148 // It panics if the type's Kind is not Struct.
149 FieldByIndex(index []int) StructField
151 // FieldByName returns the struct field with the given name
152 // and a boolean indicating if the field was found.
153 FieldByName(name string) (StructField, bool)
155 // FieldByNameFunc returns the first struct field with a name
156 // that satisfies the match function and a boolean indicating if
157 // the field was found.
158 FieldByNameFunc(match func(string) bool) (StructField, bool)
160 // In returns the type of a function type's i'th input parameter.
161 // It panics if the type's Kind is not Func.
162 // It panics if i is not in the range [0, NumIn()).
163 In(i int) Type
165 // Key returns a map type's key type.
166 // It panics if the type's Kind is not Map.
167 Key() Type
169 // Len returns an array type's length.
170 // It panics if the type's Kind is not Array.
171 Len() int
173 // NumField returns a struct type's field count.
174 // It panics if the type's Kind is not Struct.
175 NumField() int
177 // NumIn returns a function type's input parameter count.
178 // It panics if the type's Kind is not Func.
179 NumIn() int
181 // NumOut returns a function type's output parameter count.
182 // It panics if the type's Kind is not Func.
183 NumOut() int
185 // Out returns the type of a function type's i'th output parameter.
186 // It panics if the type's Kind is not Func.
187 // It panics if i is not in the range [0, NumOut()).
188 Out(i int) Type
190 common() *rtype
191 uncommon() *uncommonType
194 // BUG(rsc): FieldByName and related functions consider struct field names to be equal
195 // if the names are equal, even if they are unexported names originating
196 // in different packages. The practical effect of this is that the result of
197 // t.FieldByName("x") is not well defined if the struct type t contains
198 // multiple fields named x (embedded from different packages).
199 // FieldByName may return one of the fields named x or may report that there are none.
200 // See golang.org/issue/4876 for more details.
203 * These data structures are known to the compiler (../../cmd/gc/reflect.c).
204 * A few are known to ../runtime/type.go to convey to debuggers.
205 * They are also known to ../runtime/type.h.
208 // A Kind represents the specific kind of type that a Type represents.
209 // The zero Kind is not a valid kind.
210 type Kind uint
212 const (
213 Invalid Kind = iota
214 Bool
216 Int8
217 Int16
218 Int32
219 Int64
220 Uint
221 Uint8
222 Uint16
223 Uint32
224 Uint64
225 Uintptr
226 Float32
227 Float64
228 Complex64
229 Complex128
230 Array
231 Chan
232 Func
233 Interface
236 Slice
237 String
238 Struct
239 UnsafePointer
242 // rtype is the common implementation of most values.
243 // It is embedded in other, public struct types, but always
244 // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
245 // so that code cannot convert from, say, *arrayType to *ptrType.
246 type rtype struct {
247 kind uint8 // enumeration for C
248 align int8 // alignment of variable with this type
249 fieldAlign uint8 // alignment of struct field with this type
250 _ uint8 // unused/padding
251 size uintptr // size in bytes
252 hash uint32 // hash of type; avoids computation in hash tables
254 hashfn uintptr // hash function code
255 equalfn uintptr // equality function code
257 string *string // string form; unnecessary but undeniably useful
258 *uncommonType // (relatively) uncommon fields
259 ptrToThis *rtype // type for pointer to this type, if used in binary or has methods
260 zero unsafe.Pointer // pointer to zero value
263 // Method on non-interface type
264 type method struct {
265 name *string // name of method
266 pkgPath *string // nil for exported Names; otherwise import path
267 mtyp *rtype // method type (without receiver)
268 typ *rtype // .(*FuncType) underneath (with receiver)
269 tfn unsafe.Pointer // fn used for normal method call
272 // uncommonType is present only for types with names or methods
273 // (if T is a named type, the uncommonTypes for T and *T have methods).
274 // Using a pointer to this struct reduces the overall size required
275 // to describe an unnamed type with no methods.
276 type uncommonType struct {
277 name *string // name of type
278 pkgPath *string // import path; nil for built-in types like int, string
279 methods []method // methods associated with type
282 // ChanDir represents a channel type's direction.
283 type ChanDir int
285 const (
286 RecvDir ChanDir = 1 << iota // <-chan
287 SendDir // chan<-
288 BothDir = RecvDir | SendDir // chan
291 // arrayType represents a fixed array type.
292 type arrayType struct {
293 rtype `reflect:"array"`
294 elem *rtype // array element type
295 slice *rtype // slice type
296 len uintptr
299 // chanType represents a channel type.
300 type chanType struct {
301 rtype `reflect:"chan"`
302 elem *rtype // channel element type
303 dir uintptr // channel direction (ChanDir)
306 // funcType represents a function type.
307 type funcType struct {
308 rtype `reflect:"func"`
309 dotdotdot bool // last input parameter is ...
310 in []*rtype // input parameter types
311 out []*rtype // output parameter types
314 // imethod represents a method on an interface type
315 type imethod struct {
316 name *string // name of method
317 pkgPath *string // nil for exported Names; otherwise import path
318 typ *rtype // .(*FuncType) underneath
321 // interfaceType represents an interface type.
322 type interfaceType struct {
323 rtype `reflect:"interface"`
324 methods []imethod // sorted by hash
327 // mapType represents a map type.
328 type mapType struct {
329 rtype `reflect:"map"`
330 key *rtype // map key type
331 elem *rtype // map element (value) type
332 // bucket *rtype // internal bucket structure
333 // hmap *rtype // internal map header
336 // ptrType represents a pointer type.
337 type ptrType struct {
338 rtype `reflect:"ptr"`
339 elem *rtype // pointer element (pointed at) type
342 // sliceType represents a slice type.
343 type sliceType struct {
344 rtype `reflect:"slice"`
345 elem *rtype // slice element type
348 // Struct field
349 type structField struct {
350 name *string // nil for embedded fields
351 pkgPath *string // nil for exported Names; otherwise import path
352 typ *rtype // type of field
353 tag *string // nil if no tag
354 offset uintptr // byte offset of field within struct
357 // structType represents a struct type.
358 type structType struct {
359 rtype `reflect:"struct"`
360 fields []structField // sorted by offset
363 // NOTE: These are copied from ../runtime/mgc0.h.
364 // They must be kept in sync.
365 const (
366 _GC_END = iota
367 _GC_PTR
368 _GC_APTR
369 _GC_ARRAY_START
370 _GC_ARRAY_NEXT
371 _GC_CALL
372 _GC_CHAN_PTR
373 _GC_STRING
374 _GC_EFACE
375 _GC_IFACE
376 _GC_SLICE
377 _GC_REGION
378 _GC_NUM_INSTR
382 * The compiler knows the exact layout of all the data structures above.
383 * The compiler does not know about the data structures and methods below.
386 // Method represents a single method.
387 type Method struct {
388 // Name is the method name.
389 // PkgPath is the package path that qualifies a lower case (unexported)
390 // method name. It is empty for upper case (exported) method names.
391 // The combination of PkgPath and Name uniquely identifies a method
392 // in a method set.
393 // See http://golang.org/ref/spec#Uniqueness_of_identifiers
394 Name string
395 PkgPath string
397 Type Type // method type
398 Func Value // func with receiver as first argument
399 Index int // index for Type.Method
402 // High bit says whether type has
403 // embedded pointers,to help garbage collector.
404 const (
405 kindMask = 0x7f
406 kindNoPointers = 0x80
409 func (k Kind) String() string {
410 if int(k) < len(kindNames) {
411 return kindNames[k]
413 return "kind" + strconv.Itoa(int(k))
416 var kindNames = []string{
417 Invalid: "invalid",
418 Bool: "bool",
419 Int: "int",
420 Int8: "int8",
421 Int16: "int16",
422 Int32: "int32",
423 Int64: "int64",
424 Uint: "uint",
425 Uint8: "uint8",
426 Uint16: "uint16",
427 Uint32: "uint32",
428 Uint64: "uint64",
429 Uintptr: "uintptr",
430 Float32: "float32",
431 Float64: "float64",
432 Complex64: "complex64",
433 Complex128: "complex128",
434 Array: "array",
435 Chan: "chan",
436 Func: "func",
437 Interface: "interface",
438 Map: "map",
439 Ptr: "ptr",
440 Slice: "slice",
441 String: "string",
442 Struct: "struct",
443 UnsafePointer: "unsafe.Pointer",
446 func (t *uncommonType) uncommon() *uncommonType {
447 return t
450 func (t *uncommonType) PkgPath() string {
451 if t == nil || t.pkgPath == nil {
452 return ""
454 return *t.pkgPath
457 func (t *uncommonType) Name() string {
458 if t == nil || t.name == nil {
459 return ""
461 return *t.name
464 func (t *rtype) rawString() string { return *t.string }
466 func (t *rtype) String() string {
467 // For gccgo, strip out quoted strings.
468 s := *t.string
469 var q bool
470 r := make([]byte, len(s))
471 j := 0
472 for i := 0; i < len(s); i++ {
473 if s[i] == '\t' {
474 q = !q
475 } else if !q {
476 r[j] = s[i]
480 return string(r[:j])
483 func (t *rtype) Size() uintptr { return t.size }
485 func (t *rtype) Bits() int {
486 if t == nil {
487 panic("reflect: Bits of nil Type")
489 k := t.Kind()
490 if k < Int || k > Complex128 {
491 panic("reflect: Bits of non-arithmetic Type " + t.String())
493 return int(t.size) * 8
496 func (t *rtype) Align() int { return int(t.align) }
498 func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
500 func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
502 func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 }
504 func (t *rtype) common() *rtype { return t }
506 func (t *uncommonType) Method(i int) (m Method) {
507 if t == nil || i < 0 || i >= len(t.methods) {
508 panic("reflect: Method index out of range")
510 p := &t.methods[i]
511 if p.name != nil {
512 m.Name = *p.name
514 fl := flag(Func) << flagKindShift
515 if p.pkgPath != nil {
516 m.PkgPath = *p.pkgPath
517 fl |= flagRO
519 mt := p.typ
520 m.Type = toType(mt)
521 x := new(unsafe.Pointer)
522 *x = unsafe.Pointer(&p.tfn)
523 m.Func = Value{mt, unsafe.Pointer(x) /* 0, */, fl | flagIndir | flagMethodFn}
524 m.Index = i
525 return
528 func (t *uncommonType) NumMethod() int {
529 if t == nil {
530 return 0
532 return len(t.methods)
535 func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
536 if t == nil {
537 return
539 var p *method
540 for i := range t.methods {
541 p = &t.methods[i]
542 if p.name != nil && *p.name == name {
543 return t.Method(i), true
546 return
549 // TODO(rsc): 6g supplies these, but they are not
550 // as efficient as they could be: they have commonType
551 // as the receiver instead of *rtype.
552 func (t *rtype) NumMethod() int {
553 if t.Kind() == Interface {
554 tt := (*interfaceType)(unsafe.Pointer(t))
555 return tt.NumMethod()
557 return t.uncommonType.NumMethod()
560 func (t *rtype) Method(i int) (m Method) {
561 if t.Kind() == Interface {
562 tt := (*interfaceType)(unsafe.Pointer(t))
563 return tt.Method(i)
565 return t.uncommonType.Method(i)
568 func (t *rtype) MethodByName(name string) (m Method, ok bool) {
569 if t.Kind() == Interface {
570 tt := (*interfaceType)(unsafe.Pointer(t))
571 return tt.MethodByName(name)
573 return t.uncommonType.MethodByName(name)
576 func (t *rtype) PkgPath() string {
577 return t.uncommonType.PkgPath()
580 func (t *rtype) Name() string {
581 return t.uncommonType.Name()
584 func (t *rtype) ChanDir() ChanDir {
585 if t.Kind() != Chan {
586 panic("reflect: ChanDir of non-chan type")
588 tt := (*chanType)(unsafe.Pointer(t))
589 return ChanDir(tt.dir)
592 func (t *rtype) IsVariadic() bool {
593 if t.Kind() != Func {
594 panic("reflect: IsVariadic of non-func type")
596 tt := (*funcType)(unsafe.Pointer(t))
597 return tt.dotdotdot
600 func (t *rtype) Elem() Type {
601 switch t.Kind() {
602 case Array:
603 tt := (*arrayType)(unsafe.Pointer(t))
604 return toType(tt.elem)
605 case Chan:
606 tt := (*chanType)(unsafe.Pointer(t))
607 return toType(tt.elem)
608 case Map:
609 tt := (*mapType)(unsafe.Pointer(t))
610 return toType(tt.elem)
611 case Ptr:
612 tt := (*ptrType)(unsafe.Pointer(t))
613 return toType(tt.elem)
614 case Slice:
615 tt := (*sliceType)(unsafe.Pointer(t))
616 return toType(tt.elem)
618 panic("reflect: Elem of invalid type")
621 func (t *rtype) Field(i int) StructField {
622 if t.Kind() != Struct {
623 panic("reflect: Field of non-struct type")
625 tt := (*structType)(unsafe.Pointer(t))
626 return tt.Field(i)
629 func (t *rtype) FieldByIndex(index []int) StructField {
630 if t.Kind() != Struct {
631 panic("reflect: FieldByIndex of non-struct type")
633 tt := (*structType)(unsafe.Pointer(t))
634 return tt.FieldByIndex(index)
637 func (t *rtype) FieldByName(name string) (StructField, bool) {
638 if t.Kind() != Struct {
639 panic("reflect: FieldByName of non-struct type")
641 tt := (*structType)(unsafe.Pointer(t))
642 return tt.FieldByName(name)
645 func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
646 if t.Kind() != Struct {
647 panic("reflect: FieldByNameFunc of non-struct type")
649 tt := (*structType)(unsafe.Pointer(t))
650 return tt.FieldByNameFunc(match)
653 func (t *rtype) In(i int) Type {
654 if t.Kind() != Func {
655 panic("reflect: In of non-func type")
657 tt := (*funcType)(unsafe.Pointer(t))
658 return toType(tt.in[i])
661 func (t *rtype) Key() Type {
662 if t.Kind() != Map {
663 panic("reflect: Key of non-map type")
665 tt := (*mapType)(unsafe.Pointer(t))
666 return toType(tt.key)
669 func (t *rtype) Len() int {
670 if t.Kind() != Array {
671 panic("reflect: Len of non-array type")
673 tt := (*arrayType)(unsafe.Pointer(t))
674 return int(tt.len)
677 func (t *rtype) NumField() int {
678 if t.Kind() != Struct {
679 panic("reflect: NumField of non-struct type")
681 tt := (*structType)(unsafe.Pointer(t))
682 return len(tt.fields)
685 func (t *rtype) NumIn() int {
686 if t.Kind() != Func {
687 panic("reflect: NumIn of non-func type")
689 tt := (*funcType)(unsafe.Pointer(t))
690 return len(tt.in)
693 func (t *rtype) NumOut() int {
694 if t.Kind() != Func {
695 panic("reflect: NumOut of non-func type")
697 tt := (*funcType)(unsafe.Pointer(t))
698 return len(tt.out)
701 func (t *rtype) Out(i int) Type {
702 if t.Kind() != Func {
703 panic("reflect: Out of non-func type")
705 tt := (*funcType)(unsafe.Pointer(t))
706 return toType(tt.out[i])
709 func (d ChanDir) String() string {
710 switch d {
711 case SendDir:
712 return "chan<-"
713 case RecvDir:
714 return "<-chan"
715 case BothDir:
716 return "chan"
718 return "ChanDir" + strconv.Itoa(int(d))
721 // Method returns the i'th method in the type's method set.
722 func (t *interfaceType) Method(i int) (m Method) {
723 if i < 0 || i >= len(t.methods) {
724 return
726 p := &t.methods[i]
727 m.Name = *p.name
728 if p.pkgPath != nil {
729 m.PkgPath = *p.pkgPath
731 m.Type = toType(p.typ)
732 m.Index = i
733 return
736 // NumMethod returns the number of interface methods in the type's method set.
737 func (t *interfaceType) NumMethod() int { return len(t.methods) }
739 // MethodByName method with the given name in the type's method set.
740 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
741 if t == nil {
742 return
744 var p *imethod
745 for i := range t.methods {
746 p = &t.methods[i]
747 if *p.name == name {
748 return t.Method(i), true
751 return
754 // A StructField describes a single field in a struct.
755 type StructField struct {
756 // Name is the field name.
757 // PkgPath is the package path that qualifies a lower case (unexported)
758 // field name. It is empty for upper case (exported) field names.
759 // See http://golang.org/ref/spec#Uniqueness_of_identifiers
760 Name string
761 PkgPath string
763 Type Type // field type
764 Tag StructTag // field tag string
765 Offset uintptr // offset within struct, in bytes
766 Index []int // index sequence for Type.FieldByIndex
767 Anonymous bool // is an embedded field
770 // A StructTag is the tag string in a struct field.
772 // By convention, tag strings are a concatenation of
773 // optionally space-separated key:"value" pairs.
774 // Each key is a non-empty string consisting of non-control
775 // characters other than space (U+0020 ' '), quote (U+0022 '"'),
776 // and colon (U+003A ':'). Each value is quoted using U+0022 '"'
777 // characters and Go string literal syntax.
778 type StructTag string
780 // Get returns the value associated with key in the tag string.
781 // If there is no such key in the tag, Get returns the empty string.
782 // If the tag does not have the conventional format, the value
783 // returned by Get is unspecified.
784 func (tag StructTag) Get(key string) string {
785 for tag != "" {
786 // skip leading space
787 i := 0
788 for i < len(tag) && tag[i] == ' ' {
791 tag = tag[i:]
792 if tag == "" {
793 break
796 // scan to colon.
797 // a space or a quote is a syntax error
798 i = 0
799 for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
802 if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
803 break
805 name := string(tag[:i])
806 tag = tag[i+1:]
808 // scan quoted string to find value
809 i = 1
810 for i < len(tag) && tag[i] != '"' {
811 if tag[i] == '\\' {
816 if i >= len(tag) {
817 break
819 qvalue := string(tag[:i+1])
820 tag = tag[i+1:]
822 if key == name {
823 value, _ := strconv.Unquote(qvalue)
824 return value
827 return ""
830 // Field returns the i'th struct field.
831 func (t *structType) Field(i int) (f StructField) {
832 if i < 0 || i >= len(t.fields) {
833 return
835 p := &t.fields[i]
836 f.Type = toType(p.typ)
837 if p.name != nil {
838 f.Name = *p.name
839 } else {
840 t := f.Type
841 if t.Kind() == Ptr {
842 t = t.Elem()
844 f.Name = t.Name()
845 f.Anonymous = true
847 if p.pkgPath != nil {
848 f.PkgPath = *p.pkgPath
850 if p.tag != nil {
851 f.Tag = StructTag(*p.tag)
853 f.Offset = p.offset
855 // NOTE(rsc): This is the only allocation in the interface
856 // presented by a reflect.Type. It would be nice to avoid,
857 // at least in the common cases, but we need to make sure
858 // that misbehaving clients of reflect cannot affect other
859 // uses of reflect. One possibility is CL 5371098, but we
860 // postponed that ugliness until there is a demonstrated
861 // need for the performance. This is issue 2320.
862 f.Index = []int{i}
863 return
866 // TODO(gri): Should there be an error/bool indicator if the index
867 // is wrong for FieldByIndex?
869 // FieldByIndex returns the nested field corresponding to index.
870 func (t *structType) FieldByIndex(index []int) (f StructField) {
871 f.Type = toType(&t.rtype)
872 for i, x := range index {
873 if i > 0 {
874 ft := f.Type
875 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
876 ft = ft.Elem()
878 f.Type = ft
880 f = f.Type.Field(x)
882 return
885 // A fieldScan represents an item on the fieldByNameFunc scan work list.
886 type fieldScan struct {
887 typ *structType
888 index []int
891 // FieldByNameFunc returns the struct field with a name that satisfies the
892 // match function and a boolean to indicate if the field was found.
893 func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
894 // This uses the same condition that the Go language does: there must be a unique instance
895 // of the match at a given depth level. If there are multiple instances of a match at the
896 // same depth, they annihilate each other and inhibit any possible match at a lower level.
897 // The algorithm is breadth first search, one depth level at a time.
899 // The current and next slices are work queues:
900 // current lists the fields to visit on this depth level,
901 // and next lists the fields on the next lower level.
902 current := []fieldScan{}
903 next := []fieldScan{{typ: t}}
905 // nextCount records the number of times an embedded type has been
906 // encountered and considered for queueing in the 'next' slice.
907 // We only queue the first one, but we increment the count on each.
908 // If a struct type T can be reached more than once at a given depth level,
909 // then it annihilates itself and need not be considered at all when we
910 // process that next depth level.
911 var nextCount map[*structType]int
913 // visited records the structs that have been considered already.
914 // Embedded pointer fields can create cycles in the graph of
915 // reachable embedded types; visited avoids following those cycles.
916 // It also avoids duplicated effort: if we didn't find the field in an
917 // embedded type T at level 2, we won't find it in one at level 4 either.
918 visited := map[*structType]bool{}
920 for len(next) > 0 {
921 current, next = next, current[:0]
922 count := nextCount
923 nextCount = nil
925 // Process all the fields at this depth, now listed in 'current'.
926 // The loop queues embedded fields found in 'next', for processing during the next
927 // iteration. The multiplicity of the 'current' field counts is recorded
928 // in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
929 for _, scan := range current {
930 t := scan.typ
931 if visited[t] {
932 // We've looked through this type before, at a higher level.
933 // That higher level would shadow the lower level we're now at,
934 // so this one can't be useful to us. Ignore it.
935 continue
937 visited[t] = true
938 for i := range t.fields {
939 f := &t.fields[i]
940 // Find name and type for field f.
941 var fname string
942 var ntyp *rtype
943 if f.name != nil {
944 fname = *f.name
945 } else {
946 // Anonymous field of type T or *T.
947 // Name taken from type.
948 ntyp = f.typ
949 if ntyp.Kind() == Ptr {
950 ntyp = ntyp.Elem().common()
952 fname = ntyp.Name()
955 // Does it match?
956 if match(fname) {
957 // Potential match
958 if count[t] > 1 || ok {
959 // Name appeared multiple times at this level: annihilate.
960 return StructField{}, false
962 result = t.Field(i)
963 result.Index = nil
964 result.Index = append(result.Index, scan.index...)
965 result.Index = append(result.Index, i)
966 ok = true
967 continue
970 // Queue embedded struct fields for processing with next level,
971 // but only if we haven't seen a match yet at this level and only
972 // if the embedded types haven't already been queued.
973 if ok || ntyp == nil || ntyp.Kind() != Struct {
974 continue
976 ntyp = toType(ntyp).common()
977 styp := (*structType)(unsafe.Pointer(ntyp))
978 if nextCount[styp] > 0 {
979 nextCount[styp] = 2 // exact multiple doesn't matter
980 continue
982 if nextCount == nil {
983 nextCount = map[*structType]int{}
985 nextCount[styp] = 1
986 if count[t] > 1 {
987 nextCount[styp] = 2 // exact multiple doesn't matter
989 var index []int
990 index = append(index, scan.index...)
991 index = append(index, i)
992 next = append(next, fieldScan{styp, index})
995 if ok {
996 break
999 return
1002 // FieldByName returns the struct field with the given name
1003 // and a boolean to indicate if the field was found.
1004 func (t *structType) FieldByName(name string) (f StructField, present bool) {
1005 // Quick check for top-level name, or struct without anonymous fields.
1006 hasAnon := false
1007 if name != "" {
1008 for i := range t.fields {
1009 tf := &t.fields[i]
1010 if tf.name == nil {
1011 hasAnon = true
1012 continue
1014 if *tf.name == name {
1015 return t.Field(i), true
1019 if !hasAnon {
1020 return
1022 return t.FieldByNameFunc(func(s string) bool { return s == name })
1025 // TypeOf returns the reflection Type of the value in the interface{}.
1026 // TypeOf(nil) returns nil.
1027 func TypeOf(i interface{}) Type {
1028 eface := *(*emptyInterface)(unsafe.Pointer(&i))
1029 return toType(eface.typ)
1032 // ptrMap is the cache for PtrTo.
1033 var ptrMap struct {
1034 sync.RWMutex
1035 m map[*rtype]*ptrType
1038 // garbage collection bytecode program for pointer to memory without pointers.
1039 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
1040 type ptrDataGC struct {
1041 width uintptr // sizeof(ptr)
1042 op uintptr // _GC_APTR
1043 off uintptr // 0
1044 end uintptr // _GC_END
1047 var ptrDataGCProg = ptrDataGC{
1048 width: unsafe.Sizeof((*byte)(nil)),
1049 op: _GC_APTR,
1050 off: 0,
1051 end: _GC_END,
1054 // garbage collection bytecode program for pointer to memory with pointers.
1055 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
1056 type ptrGC struct {
1057 width uintptr // sizeof(ptr)
1058 op uintptr // _GC_PTR
1059 off uintptr // 0
1060 elemgc unsafe.Pointer // element gc type
1061 end uintptr // _GC_END
1064 // PtrTo returns the pointer type with element t.
1065 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
1066 func PtrTo(t Type) Type {
1067 return t.(*rtype).ptrTo()
1070 func (t *rtype) ptrTo() *rtype {
1071 if p := t.ptrToThis; p != nil {
1072 return p
1075 // Otherwise, synthesize one.
1076 // This only happens for pointers with no methods.
1077 // We keep the mapping in a map on the side, because
1078 // this operation is rare and a separate map lets us keep
1079 // the type structures in read-only memory.
1080 ptrMap.RLock()
1081 if m := ptrMap.m; m != nil {
1082 if p := m[t]; p != nil {
1083 ptrMap.RUnlock()
1084 return &p.rtype
1087 ptrMap.RUnlock()
1088 ptrMap.Lock()
1089 if ptrMap.m == nil {
1090 ptrMap.m = make(map[*rtype]*ptrType)
1092 p := ptrMap.m[t]
1093 if p != nil {
1094 // some other goroutine won the race and created it
1095 ptrMap.Unlock()
1096 return &p.rtype
1099 s := "*" + *t.string
1101 canonicalTypeLock.RLock()
1102 r, ok := canonicalType[s]
1103 canonicalTypeLock.RUnlock()
1104 if ok {
1105 ptrMap.m[t] = (*ptrType)(unsafe.Pointer(r.(*rtype)))
1106 ptrMap.Unlock()
1107 return r.(*rtype)
1110 // initialize p using *byte's ptrType as a prototype.
1111 p = new(ptrType)
1112 var iptr interface{} = (*unsafe.Pointer)(nil)
1113 prototype := *(**ptrType)(unsafe.Pointer(&iptr))
1114 *p = *prototype
1116 p.string = &s
1118 // For the type structures linked into the binary, the
1119 // compiler provides a good hash of the string.
1120 // Create a good hash for the new string by using
1121 // the FNV-1 hash's mixing function to combine the
1122 // old hash and the new "*".
1123 // p.hash = fnv1(t.hash, '*')
1124 // This is the gccgo version.
1125 p.hash = (t.hash << 4) + 9
1127 p.uncommonType = nil
1128 p.ptrToThis = nil
1129 p.zero = unsafe.Pointer(&make([]byte, p.size)[0])
1130 p.elem = t
1132 q := canonicalize(&p.rtype)
1133 p = (*ptrType)(unsafe.Pointer(q.(*rtype)))
1135 ptrMap.m[t] = p
1136 ptrMap.Unlock()
1137 return &p.rtype
1140 // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
1141 func fnv1(x uint32, list ...byte) uint32 {
1142 for _, b := range list {
1143 x = x*16777619 ^ uint32(b)
1145 return x
1148 func (t *rtype) Implements(u Type) bool {
1149 if u == nil {
1150 panic("reflect: nil type passed to Type.Implements")
1152 if u.Kind() != Interface {
1153 panic("reflect: non-interface type passed to Type.Implements")
1155 return implements(u.(*rtype), t)
1158 func (t *rtype) AssignableTo(u Type) bool {
1159 if u == nil {
1160 panic("reflect: nil type passed to Type.AssignableTo")
1162 uu := u.(*rtype)
1163 return directlyAssignable(uu, t) || implements(uu, t)
1166 func (t *rtype) ConvertibleTo(u Type) bool {
1167 if u == nil {
1168 panic("reflect: nil type passed to Type.ConvertibleTo")
1170 uu := u.(*rtype)
1171 return convertOp(uu, t) != nil
1174 // implements returns true if the type V implements the interface type T.
1175 func implements(T, V *rtype) bool {
1176 if T.Kind() != Interface {
1177 return false
1179 t := (*interfaceType)(unsafe.Pointer(T))
1180 if len(t.methods) == 0 {
1181 return true
1184 // The same algorithm applies in both cases, but the
1185 // method tables for an interface type and a concrete type
1186 // are different, so the code is duplicated.
1187 // In both cases the algorithm is a linear scan over the two
1188 // lists - T's methods and V's methods - simultaneously.
1189 // Since method tables are stored in a unique sorted order
1190 // (alphabetical, with no duplicate method names), the scan
1191 // through V's methods must hit a match for each of T's
1192 // methods along the way, or else V does not implement T.
1193 // This lets us run the scan in overall linear time instead of
1194 // the quadratic time a naive search would require.
1195 // See also ../runtime/iface.c.
1196 if V.Kind() == Interface {
1197 v := (*interfaceType)(unsafe.Pointer(V))
1198 i := 0
1199 for j := 0; j < len(v.methods); j++ {
1200 tm := &t.methods[i]
1201 vm := &v.methods[j]
1202 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() {
1203 if i++; i >= len(t.methods) {
1204 return true
1208 return false
1211 v := V.uncommon()
1212 if v == nil {
1213 return false
1215 i := 0
1216 for j := 0; j < len(v.methods); j++ {
1217 tm := &t.methods[i]
1218 vm := &v.methods[j]
1219 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() {
1220 if i++; i >= len(t.methods) {
1221 return true
1225 return false
1228 // directlyAssignable returns true if a value x of type V can be directly
1229 // assigned (using memmove) to a value of type T.
1230 // http://golang.org/doc/go_spec.html#Assignability
1231 // Ignoring the interface rules (implemented elsewhere)
1232 // and the ideal constant rules (no ideal constants at run time).
1233 func directlyAssignable(T, V *rtype) bool {
1234 // x's type V is identical to T?
1235 if T == V {
1236 return true
1239 // Otherwise at least one of T and V must be unnamed
1240 // and they must have the same kind.
1241 if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
1242 return false
1245 // x's type T and V must have identical underlying types.
1246 return haveIdenticalUnderlyingType(T, V)
1249 func haveIdenticalUnderlyingType(T, V *rtype) bool {
1250 if T == V {
1251 return true
1254 kind := T.Kind()
1255 if kind != V.Kind() {
1256 return false
1259 // Non-composite types of equal kind have same underlying type
1260 // (the predefined instance of the type).
1261 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
1262 return true
1265 // Composite types.
1266 switch kind {
1267 case Array:
1268 return T.Elem() == V.Elem() && T.Len() == V.Len()
1270 case Chan:
1271 // Special case:
1272 // x is a bidirectional channel value, T is a channel type,
1273 // and x's type V and T have identical element types.
1274 if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
1275 return true
1278 // Otherwise continue test for identical underlying type.
1279 return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
1281 case Func:
1282 t := (*funcType)(unsafe.Pointer(T))
1283 v := (*funcType)(unsafe.Pointer(V))
1284 if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
1285 return false
1287 for i, typ := range t.in {
1288 if typ != v.in[i] {
1289 return false
1292 for i, typ := range t.out {
1293 if typ != v.out[i] {
1294 return false
1297 return true
1299 case Interface:
1300 t := (*interfaceType)(unsafe.Pointer(T))
1301 v := (*interfaceType)(unsafe.Pointer(V))
1302 if len(t.methods) == 0 && len(v.methods) == 0 {
1303 return true
1305 // Might have the same methods but still
1306 // need a run time conversion.
1307 return false
1309 case Map:
1310 return T.Key() == V.Key() && T.Elem() == V.Elem()
1312 case Ptr, Slice:
1313 return T.Elem() == V.Elem()
1315 case Struct:
1316 t := (*structType)(unsafe.Pointer(T))
1317 v := (*structType)(unsafe.Pointer(V))
1318 if len(t.fields) != len(v.fields) {
1319 return false
1321 for i := range t.fields {
1322 tf := &t.fields[i]
1323 vf := &v.fields[i]
1324 if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) {
1325 return false
1327 if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) {
1328 return false
1330 if tf.typ != vf.typ {
1331 return false
1333 if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
1334 return false
1336 if tf.offset != vf.offset {
1337 return false
1340 return true
1343 return false
1346 // The lookupCache caches ChanOf, MapOf, and SliceOf lookups.
1347 var lookupCache struct {
1348 sync.RWMutex
1349 m map[cacheKey]*rtype
1352 // A cacheKey is the key for use in the lookupCache.
1353 // Four values describe any of the types we are looking for:
1354 // type kind, one or two subtypes, and an extra integer.
1355 type cacheKey struct {
1356 kind Kind
1357 t1 *rtype
1358 t2 *rtype
1359 extra uintptr
1362 // cacheGet looks for a type under the key k in the lookupCache.
1363 // If it finds one, it returns that type.
1364 // If not, it returns nil with the cache locked.
1365 // The caller is expected to use cachePut to unlock the cache.
1366 func cacheGet(k cacheKey) Type {
1367 lookupCache.RLock()
1368 t := lookupCache.m[k]
1369 lookupCache.RUnlock()
1370 if t != nil {
1371 return t
1374 lookupCache.Lock()
1375 t = lookupCache.m[k]
1376 if t != nil {
1377 lookupCache.Unlock()
1378 return t
1381 if lookupCache.m == nil {
1382 lookupCache.m = make(map[cacheKey]*rtype)
1385 return nil
1388 // cachePut stores the given type in the cache, unlocks the cache,
1389 // and returns the type. It is expected that the cache is locked
1390 // because cacheGet returned nil.
1391 func cachePut(k cacheKey, t *rtype) Type {
1392 t = toType(t).common()
1393 lookupCache.m[k] = t
1394 lookupCache.Unlock()
1395 return t
1398 // garbage collection bytecode program for chan.
1399 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
1400 type chanGC struct {
1401 width uintptr // sizeof(map)
1402 op uintptr // _GC_CHAN_PTR
1403 off uintptr // 0
1404 typ *rtype // map type
1405 end uintptr // _GC_END
1408 type badGC struct {
1409 width uintptr
1410 end uintptr
1413 // ChanOf returns the channel type with the given direction and element type.
1414 // For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
1416 // The gc runtime imposes a limit of 64 kB on channel element types.
1417 // If t's size is equal to or exceeds this limit, ChanOf panics.
1418 func ChanOf(dir ChanDir, t Type) Type {
1419 typ := t.(*rtype)
1421 // Look in cache.
1422 ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
1423 if ch := cacheGet(ckey); ch != nil {
1424 return ch
1427 // This restriction is imposed by the gc compiler and the runtime.
1428 if typ.size >= 1<<16 {
1429 lookupCache.Unlock()
1430 panic("reflect.ChanOf: element size too large")
1433 // Look in known types.
1434 // TODO: Precedence when constructing string.
1435 var s string
1436 switch dir {
1437 default:
1438 lookupCache.Unlock()
1439 panic("reflect.ChanOf: invalid dir")
1440 case SendDir:
1441 s = "chan<- " + *typ.string
1442 case RecvDir:
1443 s = "<-chan " + *typ.string
1444 case BothDir:
1445 s = "chan " + *typ.string
1448 // Make a channel type.
1449 var ichan interface{} = (chan unsafe.Pointer)(nil)
1450 prototype := *(**chanType)(unsafe.Pointer(&ichan))
1451 ch := new(chanType)
1452 *ch = *prototype
1453 ch.string = &s
1455 // gccgo uses a different hash.
1456 // ch.hash = fnv1(typ.hash, 'c', byte(dir))
1457 ch.hash = 0
1458 if dir&SendDir != 0 {
1459 ch.hash += 1
1461 if dir&RecvDir != 0 {
1462 ch.hash += 2
1464 ch.hash += typ.hash << 2
1465 ch.hash <<= 3
1466 ch.hash += 15
1468 ch.elem = typ
1469 ch.uncommonType = nil
1470 ch.ptrToThis = nil
1471 ch.zero = unsafe.Pointer(&make([]byte, ch.size)[0])
1473 // INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
1474 //ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
1476 return cachePut(ckey, &ch.rtype)
1479 func ismapkey(*rtype) bool // implemented in runtime
1481 // MapOf returns the map type with the given key and element types.
1482 // For example, if k represents int and e represents string,
1483 // MapOf(k, e) represents map[int]string.
1485 // If the key type is not a valid map key type (that is, if it does
1486 // not implement Go's == operator), MapOf panics.
1487 func MapOf(key, elem Type) Type {
1488 ktyp := key.(*rtype)
1489 etyp := elem.(*rtype)
1491 if !ismapkey(ktyp) {
1492 panic("reflect.MapOf: invalid key type " + ktyp.String())
1495 // Look in cache.
1496 ckey := cacheKey{Map, ktyp, etyp, 0}
1497 if mt := cacheGet(ckey); mt != nil {
1498 return mt
1501 // Look in known types.
1502 s := "map[" + *ktyp.string + "]" + *etyp.string
1504 // Make a map type.
1505 var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
1506 prototype := *(**mapType)(unsafe.Pointer(&imap))
1507 mt := new(mapType)
1508 *mt = *prototype
1509 mt.string = &s
1511 // gccgo uses a different hash
1512 // mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
1513 mt.hash = ktyp.hash + etyp.hash + 2 + 14
1515 mt.key = ktyp
1516 mt.elem = etyp
1517 // mt.bucket = bucketOf(ktyp, etyp)
1518 // mt.hmap = hMapOf(mt.bucket)
1519 mt.uncommonType = nil
1520 mt.ptrToThis = nil
1521 mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0])
1523 // INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues
1524 // fail when mt.gc is wrong.
1525 //mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END})
1527 return cachePut(ckey, &mt.rtype)
1530 // Make sure these routines stay in sync with ../../pkg/runtime/hashmap.c!
1531 // These types exist only for GC, so we only fill out GC relevant info.
1532 // Currently, that's just size and the GC program. We also fill in string
1533 // for possible debugging use.
1534 const (
1535 _BUCKETSIZE = 8
1536 _MAXKEYSIZE = 128
1537 _MAXVALSIZE = 128
1540 func bucketOf(ktyp, etyp *rtype) *rtype {
1541 if ktyp.size > _MAXKEYSIZE {
1542 ktyp = PtrTo(ktyp).(*rtype)
1544 if etyp.size > _MAXVALSIZE {
1545 etyp = PtrTo(etyp).(*rtype)
1547 ptrsize := unsafe.Sizeof(uintptr(0))
1549 gc := make([]uintptr, 1) // first entry is size, filled in at the end
1550 offset := _BUCKETSIZE * unsafe.Sizeof(uint8(0)) // topbits
1551 gc = append(gc, _GC_PTR, offset, 0 /*self pointer set below*/) // overflow
1552 offset += ptrsize
1554 // keys
1555 if ktyp.kind&kindNoPointers == 0 {
1556 gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, ktyp.size)
1557 gc = appendGCProgram(gc, ktyp)
1558 gc = append(gc, _GC_ARRAY_NEXT)
1560 offset += _BUCKETSIZE * ktyp.size
1562 // values
1563 if etyp.kind&kindNoPointers == 0 {
1564 gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, etyp.size)
1565 gc = appendGCProgram(gc, etyp)
1566 gc = append(gc, _GC_ARRAY_NEXT)
1568 offset += _BUCKETSIZE * etyp.size
1570 gc = append(gc, _GC_END)
1571 gc[0] = offset
1572 gc[3] = uintptr(unsafe.Pointer(&gc[0])) // set self pointer
1574 b := new(rtype)
1575 b.size = offset
1576 // b.gc = unsafe.Pointer(&gc[0])
1577 s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
1578 b.string = &s
1579 return b
1582 // Take the GC program for "t" and append it to the GC program "gc".
1583 func appendGCProgram(gc []uintptr, t *rtype) []uintptr {
1584 // p := t.gc
1585 var p unsafe.Pointer
1586 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
1587 loop:
1588 for {
1589 var argcnt int
1590 switch *(*uintptr)(p) {
1591 case _GC_END:
1592 // Note: _GC_END not included in append
1593 break loop
1594 case _GC_ARRAY_NEXT:
1595 argcnt = 0
1596 case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
1597 argcnt = 1
1598 case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
1599 argcnt = 2
1600 case _GC_ARRAY_START, _GC_REGION:
1601 argcnt = 3
1602 default:
1603 panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
1605 for i := 0; i < argcnt+1; i++ {
1606 gc = append(gc, *(*uintptr)(p))
1607 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
1610 return gc
1612 func hMapOf(bucket *rtype) *rtype {
1613 ptrsize := unsafe.Sizeof(uintptr(0))
1615 // make gc program & compute hmap size
1616 gc := make([]uintptr, 1) // first entry is size, filled in at the end
1617 offset := unsafe.Sizeof(uint(0)) // count
1618 offset += unsafe.Sizeof(uint32(0)) // flags
1619 offset += unsafe.Sizeof(uint32(0)) // hash0
1620 offset += unsafe.Sizeof(uint8(0)) // B
1621 offset += unsafe.Sizeof(uint8(0)) // keysize
1622 offset += unsafe.Sizeof(uint8(0)) // valuesize
1623 offset = (offset + 1) / 2 * 2
1624 offset += unsafe.Sizeof(uint16(0)) // bucketsize
1625 offset = (offset + ptrsize - 1) / ptrsize * ptrsize
1626 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
1627 offset += ptrsize
1628 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
1629 offset += ptrsize
1630 offset += ptrsize // nevacuate
1631 gc = append(gc, _GC_END)
1632 gc[0] = offset
1634 h := new(rtype)
1635 h.size = offset
1636 // h.gc = unsafe.Pointer(&gc[0])
1637 s := "hmap(" + *bucket.string + ")"
1638 h.string = &s
1639 return h
1642 // garbage collection bytecode program for slice of non-zero-length values.
1643 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
1644 type sliceGC struct {
1645 width uintptr // sizeof(slice)
1646 op uintptr // _GC_SLICE
1647 off uintptr // 0
1648 elemgc unsafe.Pointer // element gc program
1649 end uintptr // _GC_END
1652 // garbage collection bytecode program for slice of zero-length values.
1653 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
1654 type sliceEmptyGC struct {
1655 width uintptr // sizeof(slice)
1656 op uintptr // _GC_APTR
1657 off uintptr // 0
1658 end uintptr // _GC_END
1661 var sliceEmptyGCProg = sliceEmptyGC{
1662 width: unsafe.Sizeof([]byte(nil)),
1663 op: _GC_APTR,
1664 off: 0,
1665 end: _GC_END,
1668 // SliceOf returns the slice type with element type t.
1669 // For example, if t represents int, SliceOf(t) represents []int.
1670 func SliceOf(t Type) Type {
1671 typ := t.(*rtype)
1673 // Look in cache.
1674 ckey := cacheKey{Slice, typ, nil, 0}
1675 if slice := cacheGet(ckey); slice != nil {
1676 return slice
1679 // Look in known types.
1680 s := "[]" + *typ.string
1682 // Make a slice type.
1683 var islice interface{} = ([]unsafe.Pointer)(nil)
1684 prototype := *(**sliceType)(unsafe.Pointer(&islice))
1685 slice := new(sliceType)
1686 *slice = *prototype
1687 slice.string = &s
1689 // gccgo uses a different hash.
1690 // slice.hash = fnv1(typ.hash, '[')
1691 slice.hash = typ.hash + 1 + 13
1693 slice.elem = typ
1694 slice.uncommonType = nil
1695 slice.ptrToThis = nil
1696 slice.zero = unsafe.Pointer(&make([]byte, slice.size)[0])
1698 // INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
1699 //slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
1701 return cachePut(ckey, &slice.rtype)
1704 // ArrayOf returns the array type with the given count and element type.
1705 // For example, if t represents int, ArrayOf(5, t) represents [5]int.
1707 // If the resulting type would be larger than the available address space,
1708 // ArrayOf panics.
1710 // TODO(rsc): Unexported for now. Export once the alg field is set correctly
1711 // for the type. This may require significant work.
1712 func arrayOf(count int, elem Type) Type {
1713 typ := elem.(*rtype)
1714 slice := SliceOf(elem)
1716 // Look in cache.
1717 ckey := cacheKey{Array, typ, nil, uintptr(count)}
1718 if slice := cacheGet(ckey); slice != nil {
1719 return slice
1722 // Look in known types.
1723 s := "[" + strconv.Itoa(count) + "]" + *typ.string
1725 // Make an array type.
1726 var iarray interface{} = [1]unsafe.Pointer{}
1727 prototype := *(**arrayType)(unsafe.Pointer(&iarray))
1728 array := new(arrayType)
1729 *array = *prototype
1730 array.string = &s
1732 // gccgo uses a different hash.
1733 // array.hash = fnv1(typ.hash, '[')
1734 // for n := uint32(count); n > 0; n >>= 8 {
1735 // array.hash = fnv1(array.hash, byte(n))
1736 // }
1737 // array.hash = fnv1(array.hash, ']')
1738 array.hash = typ.hash + 1 + 13
1740 array.elem = typ
1741 max := ^uintptr(0) / typ.size
1742 if uintptr(count) > max {
1743 panic("reflect.ArrayOf: array size would exceed virtual address space")
1745 array.size = typ.size * uintptr(count)
1746 array.align = typ.align
1747 array.fieldAlign = typ.fieldAlign
1748 // TODO: array.alg
1749 // TODO: array.gc
1750 array.uncommonType = nil
1751 array.ptrToThis = nil
1752 array.zero = unsafe.Pointer(&make([]byte, array.size)[0])
1753 array.len = uintptr(count)
1754 array.slice = slice.(*rtype)
1756 return cachePut(ckey, &array.rtype)
1759 // toType converts from a *rtype to a Type that can be returned
1760 // to the client of package reflect. In gc, the only concern is that
1761 // a nil *rtype must be replaced by a nil Type, but in gccgo this
1762 // function takes care of ensuring that multiple *rtype for the same
1763 // type are coalesced into a single Type.
1764 var canonicalType = make(map[string]Type)
1766 var canonicalTypeLock sync.RWMutex
1768 func canonicalize(t Type) Type {
1769 if t == nil {
1770 return nil
1772 u := t.uncommon()
1773 var s string
1774 if u == nil || u.PkgPath() == "" {
1775 s = t.rawString()
1776 } else {
1777 s = u.PkgPath() + "." + u.Name()
1779 canonicalTypeLock.RLock()
1780 if r, ok := canonicalType[s]; ok {
1781 canonicalTypeLock.RUnlock()
1782 return r
1784 canonicalTypeLock.RUnlock()
1785 canonicalTypeLock.Lock()
1786 if r, ok := canonicalType[s]; ok {
1787 canonicalTypeLock.Unlock()
1788 return r
1790 canonicalType[s] = t
1791 canonicalTypeLock.Unlock()
1792 return t
1795 func toType(p *rtype) Type {
1796 if p == nil {
1797 return nil
1799 return canonicalize(p)