Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package reflect implements run-time reflection, allowing a program to | 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 | 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 | 7 // with static type interface{} and extract its dynamic type information by |
8 // calling TypeOf, which returns a Type. | 8 // calling TypeOf, which returns a Type. |
9 // | 9 // |
10 // A call to ValueOf returns a Value representing the run-time data. | 10 // A call to ValueOf returns a Value representing the run-time data. |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 Func | 221 Func |
222 Interface | 222 Interface |
223 Map | 223 Map |
224 Ptr | 224 Ptr |
225 Slice | 225 Slice |
226 String | 226 String |
227 Struct | 227 Struct |
228 UnsafePointer | 228 UnsafePointer |
229 ) | 229 ) |
230 | 230 |
231 // The compiler can only construct empty interface values at | |
232 // compile time; non-empty interface values get created | |
233 // during initialization. Type is an empty interface | |
234 // so that the compiler can lay out references as data. | |
235 // The underlying type is *reflect.ArrayType and so on. | |
236 type runtimeType interface{} | |
237 | |
238 // rtype is the common implementation of most values. | 231 // rtype is the common implementation of most values. |
r
2012/11/07 21:41:51
why the name change?
rsc
2012/11/07 21:54:21
There are two names being merged into one here. Be
| |
239 // It is embedded in other, public struct types, but always | 232 // It is embedded in other, public struct types, but always |
240 // with a unique tag like `reflect:"array"` or `reflect:"ptr"` | 233 // with a unique tag like `reflect:"array"` or `reflect:"ptr"` |
241 // so that code cannot convert from, say, *arrayType to *ptrType. | 234 // so that code cannot convert from, say, *arrayType to *ptrType. |
242 type rtype struct { | 235 type rtype struct { |
243 » size uintptr // size in bytes | 236 » size uintptr // size in bytes |
244 » hash uint32 // hash of type; avoids computation in hash t ables | 237 » hash uint32 // hash of type; avoids computation in hash table s |
245 » _ uint8 // unused/padding | 238 » _ uint8 // unused/padding |
246 » align uint8 // alignment of variable with this type | 239 » align uint8 // alignment of variable with this type |
247 » fieldAlign uint8 // alignment of struct field with this type | 240 » fieldAlign uint8 // alignment of struct field with this type |
248 » kind uint8 // enumeration for C | 241 » kind uint8 // enumeration for C |
249 » alg *uintptr // algorithm table (../runtime/runtime.h:/Alg ) | 242 » alg *uintptr // algorithm table (../runtime/runtime.h:/Alg) |
250 » gc uintptr // garbage collection data | 243 » gc uintptr // garbage collection data |
251 » string *string // string form; unnecessary but undeniably us eful | 244 » string *string // string form; unnecessary but undeniably useful |
252 » *uncommonType // (relatively) uncommon fields | 245 » *uncommonType // (relatively) uncommon fields |
253 » ptrToThis *rtype // type for pointer to this type, if used in binary or has methods | 246 » ptrToThis *rtype // type for pointer to this type, if used in bina ry or has methods |
remyoudompheng
2012/11/07 21:54:15
gofmt-ing was lost here
| |
254 } | 247 } |
255 | 248 |
256 // Method on non-interface type | 249 // Method on non-interface type |
257 type method struct { | 250 type method struct { |
258 name *string // name of method | 251 name *string // name of method |
259 pkgPath *string // nil for exported Names; otherwise import path | 252 pkgPath *string // nil for exported Names; otherwise import path |
260 » mtyp *rtype // method type (without receiver) | 253 » mtyp *rtype // method type (without receiver) |
261 » typ *rtype // .(*FuncType) underneath (with receiver) | 254 » typ *rtype // .(*FuncType) underneath (with receiver) |
262 ifn unsafe.Pointer // fn used in interface call (one-word receiver) | 255 ifn unsafe.Pointer // fn used in interface call (one-word receiver) |
263 tfn unsafe.Pointer // fn used for normal method call | 256 tfn unsafe.Pointer // fn used for normal method call |
264 } | 257 } |
265 | 258 |
266 // uncommonType is present only for types with names or methods | 259 // uncommonType is present only for types with names or methods |
267 // (if T is a named type, the uncommonTypes for T and *T have methods). | 260 // (if T is a named type, the uncommonTypes for T and *T have methods). |
268 // Using a pointer to this struct reduces the overall size required | 261 // Using a pointer to this struct reduces the overall size required |
269 // to describe an unnamed type with no methods. | 262 // to describe an unnamed type with no methods. |
270 type uncommonType struct { | 263 type uncommonType struct { |
271 name *string // name of type | 264 name *string // name of type |
272 pkgPath *string // import path; nil for built-in types like int, string | 265 pkgPath *string // import path; nil for built-in types like int, string |
273 methods []method // methods associated with type | 266 methods []method // methods associated with type |
274 } | 267 } |
275 | 268 |
276 // ChanDir represents a channel type's direction. | 269 // ChanDir represents a channel type's direction. |
277 type ChanDir int | 270 type ChanDir int |
278 | 271 |
279 const ( | 272 const ( |
280 RecvDir ChanDir = 1 << iota // <-chan | 273 RecvDir ChanDir = 1 << iota // <-chan |
281 SendDir // chan<- | 274 SendDir // chan<- |
282 BothDir = RecvDir | SendDir // chan | 275 BothDir = RecvDir | SendDir // chan |
283 ) | 276 ) |
284 | 277 |
285 // arrayType represents a fixed array type. | 278 // arrayType represents a fixed array type. |
286 type arrayType struct { | 279 type arrayType struct { |
287 rtype `reflect:"array"` | 280 rtype `reflect:"array"` |
288 » elem *rtype // array element type | 281 » elem *rtype // array element type |
289 » slice *rtype // slice type | 282 » slice *rtype // slice type |
290 » len uintptr | 283 » len uintptr |
291 } | 284 } |
292 | 285 |
293 // chanType represents a channel type. | 286 // chanType represents a channel type. |
294 type chanType struct { | 287 type chanType struct { |
295 rtype `reflect:"chan"` | 288 rtype `reflect:"chan"` |
296 » elem *rtype // channel element type | 289 » elem *rtype // channel element type |
297 » dir uintptr // channel direction (ChanDir) | 290 » dir uintptr // channel direction (ChanDir) |
298 } | 291 } |
299 | 292 |
300 // funcType represents a function type. | 293 // funcType represents a function type. |
301 type funcType struct { | 294 type funcType struct { |
302 » rtype `reflect:"func"` | 295 » rtype `reflect:"func"` |
303 » dotdotdot bool // last input parameter is ... | 296 » dotdotdot bool // last input parameter is ... |
304 » in []*rtype // input parameter types | 297 » in []*rtype // input parameter types |
305 » out []*rtype // output parameter types | 298 » out []*rtype // output parameter types |
306 } | 299 } |
307 | 300 |
308 // imethod represents a method on an interface type | 301 // imethod represents a method on an interface type |
309 type imethod struct { | 302 type imethod struct { |
310 » name *string // name of method | 303 » name *string // name of method |
311 » pkgPath *string // nil for exported Names; otherwise import path | 304 » pkgPath *string // nil for exported Names; otherwise import path |
312 » typ *rtype // .(*FuncType) underneath | 305 » typ *rtype // .(*FuncType) underneath |
313 } | 306 } |
314 | 307 |
315 // interfaceType represents an interface type. | 308 // interfaceType represents an interface type. |
316 type interfaceType struct { | 309 type interfaceType struct { |
317 » rtype `reflect:"interface"` | 310 » rtype `reflect:"interface"` |
318 » methods []imethod // sorted by hash | 311 » methods []imethod // sorted by hash |
319 } | 312 } |
320 | 313 |
321 // mapType represents a map type. | 314 // mapType represents a map type. |
322 type mapType struct { | 315 type mapType struct { |
323 rtype `reflect:"map"` | 316 rtype `reflect:"map"` |
324 » key *rtype // map key type | 317 » key *rtype // map key type |
325 » elem *rtype // map element (value) type | 318 » elem *rtype // map element (value) type |
326 } | 319 } |
327 | 320 |
328 // ptrType represents a pointer type. | 321 // ptrType represents a pointer type. |
329 type ptrType struct { | 322 type ptrType struct { |
330 rtype `reflect:"ptr"` | 323 rtype `reflect:"ptr"` |
331 » elem *rtype // pointer element (pointed at) type | 324 » elem *rtype // pointer element (pointed at) type |
332 } | 325 } |
333 | 326 |
334 // sliceType represents a slice type. | 327 // sliceType represents a slice type. |
335 type sliceType struct { | 328 type sliceType struct { |
336 rtype `reflect:"slice"` | 329 rtype `reflect:"slice"` |
337 » elem *rtype // slice element type | 330 » elem *rtype // slice element type |
338 } | 331 } |
339 | 332 |
340 // Struct field | 333 // Struct field |
341 type structField struct { | 334 type structField struct { |
342 » name *string // nil for embedded fields | 335 » name *string // nil for embedded fields |
343 » pkgPath *string // nil for exported Names; otherwise import path | 336 » pkgPath *string // nil for exported Names; otherwise import path |
344 » typ *rtype // type of field | 337 » typ *rtype // type of field |
345 » tag *string // nil if no tag | 338 » tag *string // nil if no tag |
346 » offset uintptr // byte offset of field within struct | 339 » offset uintptr // byte offset of field within struct |
347 } | 340 } |
348 | 341 |
349 // structType represents a struct type. | 342 // structType represents a struct type. |
350 type structType struct { | 343 type structType struct { |
351 » rtype `reflect:"struct"` | 344 » rtype `reflect:"struct"` |
352 » fields []structField // sorted by offset | 345 » fields []structField // sorted by offset |
353 } | 346 } |
354 | 347 |
355 /* | 348 /* |
356 * The compiler knows the exact layout of all the data structures above. | 349 * The compiler knows the exact layout of all the data structures above. |
357 * The compiler does not know about the data structures and methods below. | 350 * The compiler does not know about the data structures and methods below. |
358 */ | 351 */ |
359 | 352 |
360 // Method represents a single method. | 353 // Method represents a single method. |
361 type Method struct { | 354 type Method struct { |
362 // Name is the method name. | 355 // Name is the method name. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 return *t.pkgPath | 418 return *t.pkgPath |
426 } | 419 } |
427 | 420 |
428 func (t *uncommonType) Name() string { | 421 func (t *uncommonType) Name() string { |
429 if t == nil || t.name == nil { | 422 if t == nil || t.name == nil { |
430 return "" | 423 return "" |
431 } | 424 } |
432 return *t.name | 425 return *t.name |
433 } | 426 } |
434 | 427 |
435 func (t *rtype) toType() Type { | |
436 if t == nil { | |
437 return nil | |
438 } | |
439 return t | |
440 } | |
441 | |
442 func (t *rtype) String() string { return *t.string } | 428 func (t *rtype) String() string { return *t.string } |
443 | 429 |
444 func (t *rtype) Size() uintptr { return t.size } | 430 func (t *rtype) Size() uintptr { return t.size } |
445 | 431 |
446 func (t *rtype) Bits() int { | 432 func (t *rtype) Bits() int { |
447 if t == nil { | 433 if t == nil { |
448 panic("reflect: Bits of nil Type") | 434 panic("reflect: Bits of nil Type") |
449 } | 435 } |
450 k := t.Kind() | 436 k := t.Kind() |
451 if k < Int || k > Complex128 { | 437 if k < Int || k > Complex128 { |
(...skipping 16 matching lines...) Expand all Loading... | |
468 } | 454 } |
469 p := &t.methods[i] | 455 p := &t.methods[i] |
470 if p.name != nil { | 456 if p.name != nil { |
471 m.Name = *p.name | 457 m.Name = *p.name |
472 } | 458 } |
473 fl := flag(Func) << flagKindShift | 459 fl := flag(Func) << flagKindShift |
474 if p.pkgPath != nil { | 460 if p.pkgPath != nil { |
475 m.PkgPath = *p.pkgPath | 461 m.PkgPath = *p.pkgPath |
476 fl |= flagRO | 462 fl |= flagRO |
477 } | 463 } |
478 » mt := toCommonType(p.typ) | 464 » mt := p.typ |
479 m.Type = mt | 465 m.Type = mt |
480 fn := p.tfn | 466 fn := p.tfn |
481 m.Func = Value{mt, fn, fl} | 467 m.Func = Value{mt, fn, fl} |
482 m.Index = i | 468 m.Index = i |
483 return | 469 return |
484 } | 470 } |
485 | 471 |
486 func (t *uncommonType) NumMethod() int { | 472 func (t *uncommonType) NumMethod() int { |
487 if t == nil { | 473 if t == nil { |
488 return 0 | 474 return 0 |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
819 // need for the performance. This is issue 2320. | 805 // need for the performance. This is issue 2320. |
820 f.Index = []int{i} | 806 f.Index = []int{i} |
821 return | 807 return |
822 } | 808 } |
823 | 809 |
824 // TODO(gri): Should there be an error/bool indicator if the index | 810 // TODO(gri): Should there be an error/bool indicator if the index |
825 // is wrong for FieldByIndex? | 811 // is wrong for FieldByIndex? |
826 | 812 |
827 // FieldByIndex returns the nested field corresponding to index. | 813 // FieldByIndex returns the nested field corresponding to index. |
828 func (t *structType) FieldByIndex(index []int) (f StructField) { | 814 func (t *structType) FieldByIndex(index []int) (f StructField) { |
829 » f.Type = Type(t.toType()) | 815 » f.Type = toType(&t.rtype) |
830 for i, x := range index { | 816 for i, x := range index { |
831 if i > 0 { | 817 if i > 0 { |
832 ft := f.Type | 818 ft := f.Type |
833 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { | 819 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { |
834 ft = ft.Elem() | 820 ft = ft.Elem() |
835 } | 821 } |
836 f.Type = ft | 822 f.Type = ft |
837 } | 823 } |
838 f = f.Type.Field(x) | 824 f = f.Type.Field(x) |
839 } | 825 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 for i := range t.fields { | 882 for i := range t.fields { |
897 f := &t.fields[i] | 883 f := &t.fields[i] |
898 // Find name and type for field f. | 884 // Find name and type for field f. |
899 var fname string | 885 var fname string |
900 var ntyp *rtype | 886 var ntyp *rtype |
901 if f.name != nil { | 887 if f.name != nil { |
902 fname = *f.name | 888 fname = *f.name |
903 } else { | 889 } else { |
904 // Anonymous field of type T or *T. | 890 // Anonymous field of type T or *T. |
905 // Name taken from type. | 891 // Name taken from type. |
906 » » » » » ntyp = toCommonType(f.typ) | 892 » » » » » ntyp = f.typ |
907 if ntyp.Kind() == Ptr { | 893 if ntyp.Kind() == Ptr { |
908 ntyp = ntyp.Elem().common() | 894 ntyp = ntyp.Elem().common() |
909 } | 895 } |
910 fname = ntyp.Name() | 896 fname = ntyp.Name() |
911 } | 897 } |
912 | 898 |
913 // Does it match? | 899 // Does it match? |
914 if match(fname) { | 900 if match(fname) { |
915 // Potential match | 901 // Potential match |
916 if count[t] > 1 || ok { | 902 if count[t] > 1 || ok { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
969 return t.Field(i), true | 955 return t.Field(i), true |
970 } | 956 } |
971 } | 957 } |
972 } | 958 } |
973 if !hasAnon { | 959 if !hasAnon { |
974 return | 960 return |
975 } | 961 } |
976 return t.FieldByNameFunc(func(s string) bool { return s == name }) | 962 return t.FieldByNameFunc(func(s string) bool { return s == name }) |
977 } | 963 } |
978 | 964 |
979 // Convert runtime type to reflect type. | |
980 func toCommonType(p *rtype) *rtype { | |
r
2012/11/07 21:41:51
if the name changes (which i don't feel is necessa
rsc
2012/11/07 21:54:21
A dreg. Gone.
| |
981 return p | |
982 } | |
983 | |
984 func toType(p *rtype) Type { | |
r
2012/11/07 21:41:51
ditto, almost but not quite because of the nil int
rsc
2012/11/07 21:54:21
Will be gone soon. This is another nice side effec
| |
985 if p == nil { | |
986 return nil | |
987 } | |
988 return p | |
989 } | |
990 | |
991 // TypeOf returns the reflection Type of the value in the interface{}. | 965 // TypeOf returns the reflection Type of the value in the interface{}. |
992 // TypeOf(nil) returns nil. | 966 // TypeOf(nil) returns nil. |
993 func TypeOf(i interface{}) Type { | 967 func TypeOf(i interface{}) Type { |
994 eface := *(*emptyInterface)(unsafe.Pointer(&i)) | 968 eface := *(*emptyInterface)(unsafe.Pointer(&i)) |
995 return toType(eface.typ) | 969 return toType(eface.typ) |
996 } | 970 } |
997 | 971 |
998 // ptrMap is the cache for PtrTo. | 972 // ptrMap is the cache for PtrTo. |
999 var ptrMap struct { | 973 var ptrMap struct { |
1000 sync.RWMutex | 974 sync.RWMutex |
(...skipping 13 matching lines...) Expand all Loading... | |
1014 | 988 |
1015 // Otherwise, synthesize one. | 989 // Otherwise, synthesize one. |
1016 // This only happens for pointers with no methods. | 990 // This only happens for pointers with no methods. |
1017 // We keep the mapping in a map on the side, because | 991 // We keep the mapping in a map on the side, because |
1018 // this operation is rare and a separate map lets us keep | 992 // this operation is rare and a separate map lets us keep |
1019 // the type structures in read-only memory. | 993 // the type structures in read-only memory. |
1020 ptrMap.RLock() | 994 ptrMap.RLock() |
1021 if m := ptrMap.m; m != nil { | 995 if m := ptrMap.m; m != nil { |
1022 if p := m[t]; p != nil { | 996 if p := m[t]; p != nil { |
1023 ptrMap.RUnlock() | 997 ptrMap.RUnlock() |
1024 » » » return &p.rtype; | 998 » » » return &p.rtype |
1025 } | 999 } |
1026 } | 1000 } |
1027 ptrMap.RUnlock() | 1001 ptrMap.RUnlock() |
1028 ptrMap.Lock() | 1002 ptrMap.Lock() |
1029 if ptrMap.m == nil { | 1003 if ptrMap.m == nil { |
1030 ptrMap.m = make(map[*rtype]*ptrType) | 1004 ptrMap.m = make(map[*rtype]*ptrType) |
1031 } | 1005 } |
1032 p := ptrMap.m[t] | 1006 p := ptrMap.m[t] |
1033 if p != nil { | 1007 if p != nil { |
1034 // some other goroutine won the race and created it | 1008 // some other goroutine won the race and created it |
1035 ptrMap.Unlock() | 1009 ptrMap.Unlock() |
1036 return &p.rtype | 1010 return &p.rtype |
1037 } | 1011 } |
1038 | 1012 |
1039 // Create a new ptrType starting with the description | 1013 // Create a new ptrType starting with the description |
1040 » // of a *unsafe.Pointer. | 1014 » // of an *unsafe.Pointer. |
1041 p = new(ptrType) | 1015 p = new(ptrType) |
1042 var iptr interface{} = (*unsafe.Pointer)(nil) | 1016 var iptr interface{} = (*unsafe.Pointer)(nil) |
1043 prototype := *(**ptrType)(unsafe.Pointer(&iptr)) | 1017 prototype := *(**ptrType)(unsafe.Pointer(&iptr)) |
1044 *p = *prototype | 1018 *p = *prototype |
1045 | 1019 |
1046 s := "*" + *t.string | 1020 s := "*" + *t.string |
1047 p.string = &s | 1021 p.string = &s |
1048 | 1022 |
1049 // For the type structures linked into the binary, the | 1023 // For the type structures linked into the binary, the |
1050 // compiler provides a good hash of the string. | 1024 // compiler provides a good hash of the string. |
1051 // Create a good hash for the new string by using | 1025 // Create a good hash for the new string by using |
1052 // the FNV-1 hash's mixing function to combine the | 1026 // the FNV-1 hash's mixing function to combine the |
1053 // old hash and the new "*". | 1027 // old hash and the new "*". |
1054 » p.hash = t.hash*16777619 ^ '*' | 1028 » p.hash = fnv1(t.hash, '*') |
1055 | 1029 |
1056 p.uncommonType = nil | 1030 p.uncommonType = nil |
1057 p.ptrToThis = nil | 1031 p.ptrToThis = nil |
1058 p.elem = t | 1032 p.elem = t |
1059 | 1033 |
1060 ptrMap.m[t] = p | 1034 ptrMap.m[t] = p |
1061 ptrMap.Unlock() | 1035 ptrMap.Unlock() |
1062 return &p.rtype | 1036 return &p.rtype |
1037 } | |
1038 | |
1039 // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash func tion. | |
1040 func fnv1(x uint32, list ...byte) uint32 { | |
1041 for _, b := range list { | |
1042 x = x*16777619 ^ uint32(b) | |
1043 } | |
1044 return x | |
1063 } | 1045 } |
1064 | 1046 |
1065 func (t *rtype) Implements(u Type) bool { | 1047 func (t *rtype) Implements(u Type) bool { |
1066 if u == nil { | 1048 if u == nil { |
1067 panic("reflect: nil type passed to Type.Implements") | 1049 panic("reflect: nil type passed to Type.Implements") |
1068 } | 1050 } |
1069 if u.Kind() != Interface { | 1051 if u.Kind() != Interface { |
1070 panic("reflect: non-interface type passed to Type.Implements") | 1052 panic("reflect: non-interface type passed to Type.Implements") |
1071 } | 1053 } |
1072 return implements(u.(*rtype), t) | 1054 return implements(u.(*rtype), t) |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1262 | 1244 |
1263 // typelinks is implemented in package runtime. | 1245 // typelinks is implemented in package runtime. |
1264 // It retuns a slice of all the 'typelink' information in the binary, | 1246 // It retuns a slice of all the 'typelink' information in the binary, |
1265 // which is to say a slice of known types, sorted by string. | 1247 // which is to say a slice of known types, sorted by string. |
1266 // Note that strings are not unique identifiers for types: | 1248 // Note that strings are not unique identifiers for types: |
1267 // there can be more than one with a given string. | 1249 // there can be more than one with a given string. |
1268 // Only types we might want to look up are included: | 1250 // Only types we might want to look up are included: |
1269 // channels, maps, slices, and arrays. | 1251 // channels, maps, slices, and arrays. |
1270 func typelinks() []*rtype | 1252 func typelinks() []*rtype |
1271 | 1253 |
1272 // typesByName returns the subslice of typelinks() with the given string. | 1254 // typesByString returns the subslice of typelinks() whose elements have |
1255 // the given string representation. | |
1273 // It may be empty (no known types with that string) or may have | 1256 // It may be empty (no known types with that string) or may have |
1274 // multiple elements (multiple types with that string). | 1257 // multiple elements (multiple types with that string). |
1275 func typesByString(s string) []*rtype { | 1258 func typesByString(s string) []*rtype { |
1276 typ := typelinks() | 1259 typ := typelinks() |
1277 » | 1260 |
1278 // We are looking for the first index i where the string becomes >= s. | 1261 // We are looking for the first index i where the string becomes >= s. |
1279 // This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s). | 1262 // This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s). |
1280 i, j := 0, len(typ) | 1263 i, j := 0, len(typ) |
1281 for i < j { | 1264 for i < j { |
1282 h := i + (j-i)/2 // avoid overflow when computing h | 1265 h := i + (j-i)/2 // avoid overflow when computing h |
1283 // i ≤ h < j | 1266 // i ≤ h < j |
1284 if !(*typ[h].string >= s) { | 1267 if !(*typ[h].string >= s) { |
1285 i = h + 1 // preserves f(i-1) == false | 1268 i = h + 1 // preserves f(i-1) == false |
1286 } else { | 1269 } else { |
1287 j = h // preserves f(j) == true | 1270 j = h // preserves f(j) == true |
1288 } | 1271 } |
1289 } | 1272 } |
1290 // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i. | 1273 // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i. |
1291 » | 1274 |
1292 // Having found the first, linear scan forward to find the last. | 1275 // Having found the first, linear scan forward to find the last. |
1293 // We could do a second binary search, but the caller is going | 1276 // We could do a second binary search, but the caller is going |
1294 // to do a linear scan anyway. | 1277 // to do a linear scan anyway. |
1295 j = i | 1278 j = i |
1296 for j < len(typ) && *typ[j].string == s { | 1279 for j < len(typ) && *typ[j].string == s { |
1297 j++ | 1280 j++ |
1298 } | 1281 } |
1282 | |
1283 // This slice will be empty if the string is not found. | |
1299 return typ[i:j] | 1284 return typ[i:j] |
1300 } | 1285 } |
1301 | 1286 |
1302 // The lookupCache caches ChanOf, MapOf, and SliceOf lookups. | 1287 // The lookupCache caches ChanOf, MapOf, and SliceOf lookups. |
1303 var lookupCache struct { | 1288 var lookupCache struct { |
1304 sync.RWMutex | 1289 sync.RWMutex |
1305 m map[cacheKey]*rtype | 1290 m map[cacheKey]*rtype |
1306 } | 1291 } |
1307 | 1292 |
1308 // A cacheKey is the key for use in the lookupCache. | 1293 // A cacheKey is the key for use in the lookupCache. |
1309 // Four values describe any of the types we are looking for: | 1294 // Four values describe any of the types we are looking for: |
1310 // type kind, one or two subtypes, and an extra integer. | 1295 // type kind, one or two subtypes, and an extra integer. |
1311 type cacheKey struct { | 1296 type cacheKey struct { |
1312 » kind Kind | 1297 » kind Kind |
1313 » t1 *rtype | 1298 » t1 *rtype |
1314 » t2 *rtype | 1299 » t2 *rtype |
1315 extra uintptr | 1300 extra uintptr |
1316 } | 1301 } |
1317 | 1302 |
1318 // cacheGet looks for a type under the key k in the lookupCache. | 1303 // cacheGet looks for a type under the key k in the lookupCache. |
1319 // If it finds one, it returns that type. | 1304 // If it finds one, it returns that type. |
1320 // If not, it returns nil with the cache locked. | 1305 // If not, it returns nil with the cache locked. |
1321 // The caller is expected to use cachePut to unlock the cache. | 1306 // The caller is expected to use cachePut to unlock the cache. |
1322 func cacheGet(k cacheKey) Type { | 1307 func cacheGet(k cacheKey) Type { |
1323 lookupCache.RLock() | 1308 lookupCache.RLock() |
1324 t := lookupCache.m[k] | 1309 t := lookupCache.m[k] |
1325 lookupCache.RUnlock() | 1310 lookupCache.RUnlock() |
1326 if t != nil { | 1311 if t != nil { |
1327 return t | 1312 return t |
1328 } | 1313 } |
1329 | 1314 |
1330 lookupCache.Lock() | 1315 lookupCache.Lock() |
1331 t = lookupCache.m[k] | 1316 t = lookupCache.m[k] |
1332 if t != nil { | 1317 if t != nil { |
1333 lookupCache.Unlock() | 1318 lookupCache.Unlock() |
1334 return t | 1319 return t |
1335 } | 1320 } |
1336 » | 1321 |
1337 if lookupCache.m == nil { | 1322 if lookupCache.m == nil { |
1338 lookupCache.m = make(map[cacheKey]*rtype) | 1323 lookupCache.m = make(map[cacheKey]*rtype) |
1339 } | 1324 } |
1340 | 1325 |
1341 return nil | 1326 return nil |
1342 } | 1327 } |
1343 | 1328 |
1344 // cachePut stores the given type in the cache, unlocks the cache, | 1329 // cachePut stores the given type in the cache, unlocks the cache, |
1345 // and returns the type. It is expected that the cache is locked | 1330 // and returns the type. It is expected that the cache is locked |
1346 // because cacheGet returned nil. | 1331 // because cacheGet returned nil. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1383 s = "<-chan " + *typ.string | 1368 s = "<-chan " + *typ.string |
1384 case BothDir: | 1369 case BothDir: |
1385 s = "chan " + *typ.string | 1370 s = "chan " + *typ.string |
1386 } | 1371 } |
1387 for _, tt := range typesByString(s) { | 1372 for _, tt := range typesByString(s) { |
1388 ch := (*chanType)(unsafe.Pointer(tt)) | 1373 ch := (*chanType)(unsafe.Pointer(tt)) |
1389 if ch.elem == typ && ch.dir == uintptr(dir) { | 1374 if ch.elem == typ && ch.dir == uintptr(dir) { |
1390 return cachePut(ckey, tt) | 1375 return cachePut(ckey, tt) |
1391 } | 1376 } |
1392 } | 1377 } |
1393 » | 1378 |
1394 // Make a channel type. | 1379 // Make a channel type. |
1395 var ichan interface{} = (chan unsafe.Pointer)(nil) | 1380 var ichan interface{} = (chan unsafe.Pointer)(nil) |
1396 prototype := *(**chanType)(unsafe.Pointer(&ichan)) | 1381 prototype := *(**chanType)(unsafe.Pointer(&ichan)) |
1397 ch := new(chanType) | 1382 ch := new(chanType) |
1398 *ch = *prototype | 1383 *ch = *prototype |
1399 ch.string = &s | 1384 ch.string = &s |
1400 » ch.hash = typ.hash*16777619 ^ 'c' | 1385 » ch.hash = fnv1(typ.hash, 'c', byte(dir)) |
1401 » ch.hash = typ.hash*16777619 ^ uint32(dir) | |
1402 ch.elem = typ | 1386 ch.elem = typ |
1403 ch.uncommonType = nil | 1387 ch.uncommonType = nil |
1404 ch.ptrToThis = nil | 1388 ch.ptrToThis = nil |
1405 | 1389 |
1406 return cachePut(ckey, &ch.rtype) | 1390 return cachePut(ckey, &ch.rtype) |
1407 } | 1391 } |
1408 | 1392 |
1409 // MapOf returns the map type with the given key and value types. | 1393 // MapOf returns the map type with the given key and element types. |
1410 // For example, if k represents int and v represents string, | 1394 // For example, if k represents int and e represents string, |
1411 // MapOf(k, v) represents map[int]string. | 1395 // MapOf(k, e) represents map[int]string. |
1412 // | 1396 // |
1413 // If the key type is not a valid map key type (that is, if it does | 1397 // If the key type is not a valid map key type (that is, if it does |
1414 // not implement Go's == operator), MapOf panics. | 1398 // not implement Go's == operator), MapOf panics. TODO(rsc). |
1415 func MapOf(key, elem Type) Type { | 1399 func MapOf(key, elem Type) Type { |
1416 ktyp := key.(*rtype) | 1400 ktyp := key.(*rtype) |
1417 etyp := elem.(*rtype) | 1401 etyp := elem.(*rtype) |
1418 » | 1402 |
1419 // TODO: Check for invalid key types. | 1403 // TODO: Check for invalid key types. |
1420 | 1404 |
1421 // Look in cache. | 1405 // Look in cache. |
1422 ckey := cacheKey{Map, ktyp, etyp, 0} | 1406 ckey := cacheKey{Map, ktyp, etyp, 0} |
1423 if mt := cacheGet(ckey); mt != nil { | 1407 if mt := cacheGet(ckey); mt != nil { |
1424 return mt | 1408 return mt |
1425 } | 1409 } |
1426 | 1410 |
1427 // Look in known types. | 1411 // Look in known types. |
1428 s := "map[" + *ktyp.string + "]" + *etyp.string | 1412 s := "map[" + *ktyp.string + "]" + *etyp.string |
1429 for _, tt := range typesByString(s) { | 1413 for _, tt := range typesByString(s) { |
1430 mt := (*mapType)(unsafe.Pointer(tt)) | 1414 mt := (*mapType)(unsafe.Pointer(tt)) |
1431 if mt.key == ktyp && mt.elem == etyp { | 1415 if mt.key == ktyp && mt.elem == etyp { |
1432 return cachePut(ckey, tt) | 1416 return cachePut(ckey, tt) |
1433 } | 1417 } |
1434 } | 1418 } |
1435 | 1419 |
1436 // Make a map type. | 1420 // Make a map type. |
1437 var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) | 1421 var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) |
1438 prototype := *(**mapType)(unsafe.Pointer(&imap)) | 1422 prototype := *(**mapType)(unsafe.Pointer(&imap)) |
1439 mt := new(mapType) | 1423 mt := new(mapType) |
1440 *mt = *prototype | 1424 *mt = *prototype |
1441 mt.string = &s | 1425 mt.string = &s |
1442 » mt.hash = etyp.hash*16777619 ^ 'm' | 1426 » mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash)) |
1443 » mt.hash = mt.hash*16777619 ^ (ktyp.hash>>24) | |
1444 » mt.hash = mt.hash*16777619 ^ ((ktyp.hash>>16)&0xFF) | |
1445 » mt.hash = mt.hash*16777619 ^ ((ktyp.hash>>8)&0xFF) | |
1446 » mt.hash = mt.hash*16777619 ^ (ktyp.hash&0xFF) | |
1447 mt.key = ktyp | 1427 mt.key = ktyp |
1448 mt.elem = etyp | 1428 mt.elem = etyp |
1449 mt.uncommonType = nil | 1429 mt.uncommonType = nil |
1450 mt.ptrToThis = nil | 1430 mt.ptrToThis = nil |
1451 | 1431 |
1452 return cachePut(ckey, &mt.rtype) | 1432 return cachePut(ckey, &mt.rtype) |
1453 } | 1433 } |
1454 | 1434 |
1455 // SliceOf returns the slice type with element type t. | 1435 // SliceOf returns the slice type with element type t. |
1456 // For example, if t represents int, SliceOf(t) represents []int. | 1436 // For example, if t represents int, SliceOf(t) represents []int. |
1457 func SliceOf(t Type) Type { | 1437 func SliceOf(t Type) Type { |
1458 typ := t.(*rtype) | 1438 typ := t.(*rtype) |
1459 » | 1439 |
1460 // Look in cache. | 1440 // Look in cache. |
1461 ckey := cacheKey{Slice, typ, nil, 0} | 1441 ckey := cacheKey{Slice, typ, nil, 0} |
1462 if slice := cacheGet(ckey); slice != nil { | 1442 if slice := cacheGet(ckey); slice != nil { |
1463 return slice | 1443 return slice |
1464 } | 1444 } |
1465 | 1445 |
1466 // Look in known types. | 1446 // Look in known types. |
1467 s := "[]" + *typ.string | 1447 s := "[]" + *typ.string |
1468 for _, tt := range typesByString(s) { | 1448 for _, tt := range typesByString(s) { |
1469 slice := (*sliceType)(unsafe.Pointer(tt)) | 1449 slice := (*sliceType)(unsafe.Pointer(tt)) |
1470 if slice.elem == typ { | 1450 if slice.elem == typ { |
1471 return cachePut(ckey, tt) | 1451 return cachePut(ckey, tt) |
1472 } | 1452 } |
1473 } | 1453 } |
1474 » | 1454 |
1475 // Make a slice type. | 1455 // Make a slice type. |
1476 var islice interface{} = ([]unsafe.Pointer)(nil) | 1456 var islice interface{} = ([]unsafe.Pointer)(nil) |
1477 prototype := *(**sliceType)(unsafe.Pointer(&islice)) | 1457 prototype := *(**sliceType)(unsafe.Pointer(&islice)) |
1478 slice := new(sliceType) | 1458 slice := new(sliceType) |
1479 *slice = *prototype | 1459 *slice = *prototype |
1480 slice.string = &s | 1460 slice.string = &s |
1481 » slice.hash = typ.hash*16777619 ^ '[' | 1461 » slice.hash = fnv1(typ.hash, '[') |
1482 slice.elem = typ | 1462 slice.elem = typ |
1483 slice.uncommonType = nil | 1463 slice.uncommonType = nil |
1484 slice.ptrToThis = nil | 1464 slice.ptrToThis = nil |
1485 | 1465 |
1486 » return cachePut(ckey, &slice.rtype)» | 1466 » return cachePut(ckey, &slice.rtype) |
1487 } | 1467 } |
1488 | 1468 |
1489 // ArrayOf returns the array type with the given count and element type. | 1469 // ArrayOf returns the array type with the given count and element type. |
1490 // For example, if t represents int, ArrayOf(5, t) represents [5]int. | 1470 // For example, if t represents int, ArrayOf(5, t) represents [5]int. |
1491 // | 1471 // |
1492 // If the resulting type would be larger than the available address space, | 1472 // If the resulting type would be larger than the available address space, |
1493 // ArrayOf panics. | 1473 // ArrayOf panics. |
1494 func ArrayOf(count int, elem Type) Type { | 1474 // |
1475 // TODO(rsc): Unexported for now. Export once the alg field is set correctly | |
1476 // for the type. This may require significant work. | |
1477 func arrayOf(count int, elem Type) Type { | |
1495 typ := elem.(*rtype) | 1478 typ := elem.(*rtype) |
1496 slice := SliceOf(elem) | 1479 slice := SliceOf(elem) |
1497 » | 1480 |
1498 // Look in cache. | 1481 // Look in cache. |
1499 ckey := cacheKey{Array, typ, nil, uintptr(count)} | 1482 ckey := cacheKey{Array, typ, nil, uintptr(count)} |
1500 if slice := cacheGet(ckey); slice != nil { | 1483 if slice := cacheGet(ckey); slice != nil { |
1501 return slice | 1484 return slice |
1502 } | 1485 } |
1503 | 1486 |
1504 // Look in known types. | 1487 // Look in known types. |
1505 s := "[" + strconv.Itoa(count) + "]" + *typ.string | 1488 s := "[" + strconv.Itoa(count) + "]" + *typ.string |
1506 for _, tt := range typesByString(s) { | 1489 for _, tt := range typesByString(s) { |
1507 slice := (*sliceType)(unsafe.Pointer(tt)) | 1490 slice := (*sliceType)(unsafe.Pointer(tt)) |
1508 if slice.elem == typ { | 1491 if slice.elem == typ { |
1509 return cachePut(ckey, tt) | 1492 return cachePut(ckey, tt) |
1510 } | 1493 } |
1511 } | 1494 } |
1512 » | 1495 |
1513 // Make an array type. | 1496 // Make an array type. |
1514 var iarray interface{} = [1]unsafe.Pointer{} | 1497 var iarray interface{} = [1]unsafe.Pointer{} |
1515 prototype := *(**arrayType)(unsafe.Pointer(&iarray)) | 1498 prototype := *(**arrayType)(unsafe.Pointer(&iarray)) |
1516 array := new(arrayType) | 1499 array := new(arrayType) |
1517 *array = *prototype | 1500 *array = *prototype |
1518 array.string = &s | 1501 array.string = &s |
1519 » array.hash = typ.hash*16777619 ^ '[' | 1502 » array.hash = fnv1(typ.hash, '[') |
1520 for n := uint32(count); n > 0; n >>= 8 { | 1503 for n := uint32(count); n > 0; n >>= 8 { |
1521 » » array.hash = array.hash*16777619 ^ (n&0xFF) | 1504 » » array.hash = fnv1(array.hash, byte(n)) |
1522 » } | 1505 » } |
1523 » array.hash = array.hash*16777619 ^ ']' | 1506 » array.hash = fnv1(array.hash, ']') |
1524 array.elem = typ | 1507 array.elem = typ |
1525 » array.size = typ.size*uintptr(count) // TODO check | 1508 » max := ^uintptr(0) / typ.size |
1509 » if uintptr(count) > max { | |
1510 » » panic("reflect.ArrayOf: array size would exceed virtual address space") | |
1511 » } | |
1512 » array.size = typ.size * uintptr(count) | |
1526 array.align = typ.align | 1513 array.align = typ.align |
1527 array.fieldAlign = typ.fieldAlign | 1514 array.fieldAlign = typ.fieldAlign |
1528 // TODO: array.alg | 1515 // TODO: array.alg |
1529 // TODO: array.gc | 1516 // TODO: array.gc |
1530 array.uncommonType = nil | 1517 array.uncommonType = nil |
1531 array.ptrToThis = nil | 1518 array.ptrToThis = nil |
1532 array.len = uintptr(count) | 1519 array.len = uintptr(count) |
1533 array.slice = slice.(*rtype) | 1520 array.slice = slice.(*rtype) |
1534 | 1521 |
1535 » // TODO: Size. | 1522 » return cachePut(ckey, &array.rtype) |
1536 | 1523 } |
1537 » return cachePut(ckey, &array.rtype)» | 1524 |
1538 } | 1525 // toType converts from a *rtype to a Type that can be returned |
1526 // to the client of package reflect. In gc, the only concern is that | |
1527 // a nil *rtype must be replaced by a nil Type, but in gccgo this | |
1528 // function takes care of ensuring that multiple *rtype for the same | |
1529 // type are coalesced into a single Type. | |
1530 func toType(t *rtype) Type { | |
1531 » if t == nil { | |
1532 » » return nil | |
1533 » } | |
1534 » return t | |
1535 } | |
LEFT | RIGHT |