Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(268)

Delta Between Two Patch Sets: src/pkg/reflect/type.go

Issue 6572043: code review 6572043: reflect: add ArrayOf, ChanOf, MapOf, SliceOf (Closed)
Left Patch Set: diff -r 7252ea907502 https://code.google.com/p/go/ Created 11 years, 4 months ago
Right Patch Set: diff -r 6e9d872ffc66 https://code.google.com/p/go/ Created 11 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/reflect/makefunc.go ('k') | src/pkg/reflect/value.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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
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
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
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
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
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
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
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b