LEFT | RIGHT |
(no file at all) | |
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 | 5 package reflect |
6 | 6 |
7 import ( | 7 import ( |
8 "math" | 8 "math" |
9 "runtime" | 9 "runtime" |
10 "strconv" | 10 "strconv" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 // Its IsValid method returns false, its Kind method returns Invalid, | 53 // Its IsValid method returns false, its Kind method returns Invalid, |
54 // its String method returns "<invalid Value>", and all other methods panic. | 54 // its String method returns "<invalid Value>", and all other methods panic. |
55 // Most functions and methods never return an invalid value. | 55 // Most functions and methods never return an invalid value. |
56 // If one does, its documentation states the conditions explicitly. | 56 // If one does, its documentation states the conditions explicitly. |
57 // | 57 // |
58 // A Value can be used concurrently by multiple goroutines provided that | 58 // A Value can be used concurrently by multiple goroutines provided that |
59 // the underlying Go value can be used concurrently for the equivalent | 59 // the underlying Go value can be used concurrently for the equivalent |
60 // direct operations. | 60 // direct operations. |
61 type Value struct { | 61 type Value struct { |
62 // typ holds the type of the value represented by a Value. | 62 // typ holds the type of the value represented by a Value. |
63 » typ *commonType | 63 » typ *rtype |
64 | 64 |
65 // val holds the 1-word representation of the value. | 65 // val holds the 1-word representation of the value. |
66 // If flag's flagIndir bit is set, then val is a pointer to the data. | 66 // If flag's flagIndir bit is set, then val is a pointer to the data. |
67 // Otherwise val is a word holding the actual data. | 67 // Otherwise val is a word holding the actual data. |
68 // When the data is smaller than a word, it begins at | 68 // When the data is smaller than a word, it begins at |
69 // the first byte (in the memory address sense) of val. | 69 // the first byte (in the memory address sense) of val. |
70 // We use unsafe.Pointer so that the garbage collector | 70 // We use unsafe.Pointer so that the garbage collector |
71 // knows that val could be a pointer. | 71 // knows that val could be a pointer. |
72 val unsafe.Pointer | 72 val unsafe.Pointer |
73 | 73 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w)) | 204 *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w)) |
205 case 7: | 205 case 7: |
206 *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w)) | 206 *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w)) |
207 case 8: | 207 case 8: |
208 *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w)) | 208 *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w)) |
209 } | 209 } |
210 } | 210 } |
211 | 211 |
212 // emptyInterface is the header for an interface{} value. | 212 // emptyInterface is the header for an interface{} value. |
213 type emptyInterface struct { | 213 type emptyInterface struct { |
214 » typ *runtimeType | 214 » typ *rtype |
215 word iword | 215 word iword |
216 } | 216 } |
217 | 217 |
218 // nonEmptyInterface is the header for a interface value with methods. | 218 // nonEmptyInterface is the header for a interface value with methods. |
219 type nonEmptyInterface struct { | 219 type nonEmptyInterface struct { |
220 // see ../runtime/iface.c:/Itab | 220 // see ../runtime/iface.c:/Itab |
221 itab *struct { | 221 itab *struct { |
222 » » ityp *runtimeType // static interface type | 222 » » ityp *rtype // static interface type |
223 » » typ *runtimeType // dynamic concrete type | 223 » » typ *rtype // dynamic concrete type |
224 link unsafe.Pointer | 224 link unsafe.Pointer |
225 bad int32 | 225 bad int32 |
226 unused int32 | 226 unused int32 |
227 fun [100000]unsafe.Pointer // method table | 227 fun [100000]unsafe.Pointer // method table |
228 } | 228 } |
229 word iword | 229 word iword |
230 } | 230 } |
231 | 231 |
232 // mustBe panics if f's kind is not expected. | 232 // mustBe panics if f's kind is not expected. |
233 // Making this a method on flag instead of on Value | 233 // Making this a method on flag instead of on Value |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 i := int(v.flag) >> flagMethodShift | 369 i := int(v.flag) >> flagMethodShift |
370 if v.typ.Kind() == Interface { | 370 if v.typ.Kind() == Interface { |
371 tt := (*interfaceType)(unsafe.Pointer(v.typ)) | 371 tt := (*interfaceType)(unsafe.Pointer(v.typ)) |
372 if i < 0 || i >= len(tt.methods) { | 372 if i < 0 || i >= len(tt.methods) { |
373 panic("reflect: broken Value") | 373 panic("reflect: broken Value") |
374 } | 374 } |
375 m := &tt.methods[i] | 375 m := &tt.methods[i] |
376 if m.pkgPath != nil { | 376 if m.pkgPath != nil { |
377 panic(method + " of unexported method") | 377 panic(method + " of unexported method") |
378 } | 378 } |
379 » » » t = toCommonType(m.typ) | 379 » » » t = m.typ |
380 iface := (*nonEmptyInterface)(v.val) | 380 iface := (*nonEmptyInterface)(v.val) |
381 if iface.itab == nil { | 381 if iface.itab == nil { |
382 panic(method + " of method on nil interface valu
e") | 382 panic(method + " of method on nil interface valu
e") |
383 } | 383 } |
384 fn = iface.itab.fun[i] | 384 fn = iface.itab.fun[i] |
385 rcvr = iface.word | 385 rcvr = iface.word |
386 } else { | 386 } else { |
387 ut := v.typ.uncommon() | 387 ut := v.typ.uncommon() |
388 if ut == nil || i < 0 || i >= len(ut.methods) { | 388 if ut == nil || i < 0 || i >= len(ut.methods) { |
389 panic("reflect: broken Value") | 389 panic("reflect: broken Value") |
390 } | 390 } |
391 m := &ut.methods[i] | 391 m := &ut.methods[i] |
392 if m.pkgPath != nil { | 392 if m.pkgPath != nil { |
393 panic(method + " of unexported method") | 393 panic(method + " of unexported method") |
394 } | 394 } |
395 fn = m.ifn | 395 fn = m.ifn |
396 » » » t = toCommonType(m.mtyp) | 396 » » » t = m.mtyp |
397 rcvr = v.iword() | 397 rcvr = v.iword() |
398 } | 398 } |
399 } else if v.flag&flagIndir != 0 { | 399 } else if v.flag&flagIndir != 0 { |
400 fn = *(*unsafe.Pointer)(v.val) | 400 fn = *(*unsafe.Pointer)(v.val) |
401 } else { | 401 } else { |
402 fn = v.val | 402 fn = v.val |
403 } | 403 } |
404 | 404 |
405 if fn == nil { | 405 if fn == nil { |
406 panic("reflect.Value.Call: call of nil function") | 406 panic("reflect.Value.Call: call of nil function") |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 args := make([]unsafe.Pointer, size/ptrSize) | 506 args := make([]unsafe.Pointer, size/ptrSize) |
507 ptr := uintptr(unsafe.Pointer(&args[0])) | 507 ptr := uintptr(unsafe.Pointer(&args[0])) |
508 off := uintptr(0) | 508 off := uintptr(0) |
509 if v.flag&flagMethod != 0 { | 509 if v.flag&flagMethod != 0 { |
510 // Hard-wired first argument. | 510 // Hard-wired first argument. |
511 *(*iword)(unsafe.Pointer(ptr)) = rcvr | 511 *(*iword)(unsafe.Pointer(ptr)) = rcvr |
512 off = ptrSize | 512 off = ptrSize |
513 } | 513 } |
514 for i, v := range in { | 514 for i, v := range in { |
515 v.mustBeExported() | 515 v.mustBeExported() |
516 » » targ := t.In(i).(*commonType) | 516 » » targ := t.In(i).(*rtype) |
517 a := uintptr(targ.align) | 517 a := uintptr(targ.align) |
518 off = (off + a - 1) &^ (a - 1) | 518 off = (off + a - 1) &^ (a - 1) |
519 n := targ.size | 519 n := targ.size |
520 addr := unsafe.Pointer(ptr + off) | 520 addr := unsafe.Pointer(ptr + off) |
521 v = v.assignTo("reflect.Value.Call", targ, (*interface{})(addr)) | 521 v = v.assignTo("reflect.Value.Call", targ, (*interface{})(addr)) |
522 if v.flag&flagIndir == 0 { | 522 if v.flag&flagIndir == 0 { |
523 storeIword(addr, iword(v.val), n) | 523 storeIword(addr, iword(v.val), n) |
524 } else { | 524 } else { |
525 memmove(addr, v.val, n) | 525 memmove(addr, v.val, n) |
526 } | 526 } |
(...skipping 27 matching lines...) Expand all Loading... |
554 // callReflect converts a call of a function with a concrete argument | 554 // callReflect converts a call of a function with a concrete argument |
555 // frame into a call using Values. | 555 // frame into a call using Values. |
556 // It is in this file so that it can be next to the call method above. | 556 // It is in this file so that it can be next to the call method above. |
557 // The remainder of the MakeFunc implementation is in makefunc.go. | 557 // The remainder of the MakeFunc implementation is in makefunc.go. |
558 func callReflect(ftyp *funcType, f func([]Value) []Value, frame unsafe.Pointer)
{ | 558 func callReflect(ftyp *funcType, f func([]Value) []Value, frame unsafe.Pointer)
{ |
559 // Copy argument frame into Values. | 559 // Copy argument frame into Values. |
560 ptr := frame | 560 ptr := frame |
561 off := uintptr(0) | 561 off := uintptr(0) |
562 in := make([]Value, 0, len(ftyp.in)) | 562 in := make([]Value, 0, len(ftyp.in)) |
563 for _, arg := range ftyp.in { | 563 for _, arg := range ftyp.in { |
564 » » typ := toCommonType(arg) | 564 » » typ := arg |
565 off += -off & uintptr(typ.align-1) | 565 off += -off & uintptr(typ.align-1) |
566 v := Value{typ, nil, flag(typ.Kind()) << flagKindShift} | 566 v := Value{typ, nil, flag(typ.Kind()) << flagKindShift} |
567 if typ.size <= ptrSize { | 567 if typ.size <= ptrSize { |
568 // value fits in word. | 568 // value fits in word. |
569 v.val = unsafe.Pointer(loadIword(unsafe.Pointer(uintptr(
ptr)+off), typ.size)) | 569 v.val = unsafe.Pointer(loadIword(unsafe.Pointer(uintptr(
ptr)+off), typ.size)) |
570 } else { | 570 } else { |
571 // value does not fit in word. | 571 // value does not fit in word. |
572 // Must make a copy, because f might keep a reference to
it, | 572 // Must make a copy, because f might keep a reference to
it, |
573 // and we cannot let f keep a reference to the stack fra
me | 573 // and we cannot let f keep a reference to the stack fra
me |
574 // after this function returns, not even a read-only ref
erence. | 574 // after this function returns, not even a read-only ref
erence. |
575 v.val = unsafe_New(typ) | 575 v.val = unsafe_New(typ) |
576 memmove(v.val, unsafe.Pointer(uintptr(ptr)+off), typ.siz
e) | 576 memmove(v.val, unsafe.Pointer(uintptr(ptr)+off), typ.siz
e) |
577 v.flag |= flagIndir | 577 v.flag |= flagIndir |
578 } | 578 } |
579 in = append(in, v) | 579 in = append(in, v) |
580 off += typ.size | 580 off += typ.size |
581 } | 581 } |
582 | 582 |
583 // Call underlying function. | 583 // Call underlying function. |
584 out := f(in) | 584 out := f(in) |
585 if len(out) != len(ftyp.out) { | 585 if len(out) != len(ftyp.out) { |
586 panic("reflect: wrong return count from function created by Make
Func") | 586 panic("reflect: wrong return count from function created by Make
Func") |
587 } | 587 } |
588 | 588 |
589 // Copy results back into argument frame. | 589 // Copy results back into argument frame. |
590 if len(ftyp.out) > 0 { | 590 if len(ftyp.out) > 0 { |
591 off += -off & (ptrSize - 1) | 591 off += -off & (ptrSize - 1) |
592 for i, arg := range ftyp.out { | 592 for i, arg := range ftyp.out { |
593 » » » typ := toCommonType(arg) | 593 » » » typ := arg |
594 v := out[i] | 594 v := out[i] |
595 if v.typ != typ { | 595 if v.typ != typ { |
596 panic("reflect: function created by MakeFunc usi
ng " + funcName(f) + | 596 panic("reflect: function created by MakeFunc usi
ng " + funcName(f) + |
597 " returned wrong type: have " + | 597 " returned wrong type: have " + |
598 out[i].typ.String() + " for " + typ.Stri
ng()) | 598 out[i].typ.String() + " for " + typ.Stri
ng()) |
599 } | 599 } |
600 if v.flag&flagRO != 0 { | 600 if v.flag&flagRO != 0 { |
601 panic("reflect: function created by MakeFunc usi
ng " + funcName(f) + | 601 panic("reflect: function created by MakeFunc usi
ng " + funcName(f) + |
602 " returned value obtained from unexporte
d field") | 602 " returned value obtained from unexporte
d field") |
603 } | 603 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 | 666 |
667 // Elem returns the value that the interface v contains | 667 // Elem returns the value that the interface v contains |
668 // or that the pointer v points to. | 668 // or that the pointer v points to. |
669 // It panics if v's Kind is not Interface or Ptr. | 669 // It panics if v's Kind is not Interface or Ptr. |
670 // It returns the zero Value if v is nil. | 670 // It returns the zero Value if v is nil. |
671 func (v Value) Elem() Value { | 671 func (v Value) Elem() Value { |
672 k := v.kind() | 672 k := v.kind() |
673 switch k { | 673 switch k { |
674 case Interface: | 674 case Interface: |
675 var ( | 675 var ( |
676 » » » typ *commonType | 676 » » » typ *rtype |
677 val unsafe.Pointer | 677 val unsafe.Pointer |
678 ) | 678 ) |
679 if v.typ.NumMethod() == 0 { | 679 if v.typ.NumMethod() == 0 { |
680 eface := (*emptyInterface)(v.val) | 680 eface := (*emptyInterface)(v.val) |
681 if eface.typ == nil { | 681 if eface.typ == nil { |
682 // nil interface value | 682 // nil interface value |
683 return Value{} | 683 return Value{} |
684 } | 684 } |
685 » » » typ = toCommonType(eface.typ) | 685 » » » typ = eface.typ |
686 val = unsafe.Pointer(eface.word) | 686 val = unsafe.Pointer(eface.word) |
687 } else { | 687 } else { |
688 iface := (*nonEmptyInterface)(v.val) | 688 iface := (*nonEmptyInterface)(v.val) |
689 if iface.itab == nil { | 689 if iface.itab == nil { |
690 // nil interface value | 690 // nil interface value |
691 return Value{} | 691 return Value{} |
692 } | 692 } |
693 » » » typ = toCommonType(iface.itab.typ) | 693 » » » typ = iface.itab.typ |
694 val = unsafe.Pointer(iface.word) | 694 val = unsafe.Pointer(iface.word) |
695 } | 695 } |
696 fl := v.flag & flagRO | 696 fl := v.flag & flagRO |
697 fl |= flag(typ.Kind()) << flagKindShift | 697 fl |= flag(typ.Kind()) << flagKindShift |
698 if typ.size > ptrSize { | 698 if typ.size > ptrSize { |
699 fl |= flagIndir | 699 fl |= flagIndir |
700 } | 700 } |
701 return Value{typ, val, fl} | 701 return Value{typ, val, fl} |
702 | 702 |
703 case Ptr: | 703 case Ptr: |
704 val := v.val | 704 val := v.val |
705 if v.flag&flagIndir != 0 { | 705 if v.flag&flagIndir != 0 { |
706 val = *(*unsafe.Pointer)(val) | 706 val = *(*unsafe.Pointer)(val) |
707 } | 707 } |
708 // The returned value's address is v's value. | 708 // The returned value's address is v's value. |
709 if val == nil { | 709 if val == nil { |
710 return Value{} | 710 return Value{} |
711 } | 711 } |
712 tt := (*ptrType)(unsafe.Pointer(v.typ)) | 712 tt := (*ptrType)(unsafe.Pointer(v.typ)) |
713 » » typ := toCommonType(tt.elem) | 713 » » typ := tt.elem |
714 fl := v.flag&flagRO | flagIndir | flagAddr | 714 fl := v.flag&flagRO | flagIndir | flagAddr |
715 fl |= flag(typ.Kind() << flagKindShift) | 715 fl |= flag(typ.Kind() << flagKindShift) |
716 return Value{typ, val, fl} | 716 return Value{typ, val, fl} |
717 } | 717 } |
718 panic(&ValueError{"reflect.Value.Elem", k}) | 718 panic(&ValueError{"reflect.Value.Elem", k}) |
719 } | 719 } |
720 | 720 |
721 // Field returns the i'th field of the struct v. | 721 // Field returns the i'th field of the struct v. |
722 // It panics if v's Kind is not Struct or i is out of range. | 722 // It panics if v's Kind is not Struct or i is out of range. |
723 func (v Value) Field(i int) Value { | 723 func (v Value) Field(i int) Value { |
724 v.mustBe(Struct) | 724 v.mustBe(Struct) |
725 tt := (*structType)(unsafe.Pointer(v.typ)) | 725 tt := (*structType)(unsafe.Pointer(v.typ)) |
726 if i < 0 || i >= len(tt.fields) { | 726 if i < 0 || i >= len(tt.fields) { |
727 panic("reflect: Field index out of range") | 727 panic("reflect: Field index out of range") |
728 } | 728 } |
729 field := &tt.fields[i] | 729 field := &tt.fields[i] |
730 » typ := toCommonType(field.typ) | 730 » typ := field.typ |
731 | 731 |
732 // Inherit permission bits from v. | 732 // Inherit permission bits from v. |
733 fl := v.flag & (flagRO | flagIndir | flagAddr) | 733 fl := v.flag & (flagRO | flagIndir | flagAddr) |
734 // Using an unexported field forces flagRO. | 734 // Using an unexported field forces flagRO. |
735 if field.pkgPath != nil { | 735 if field.pkgPath != nil { |
736 fl |= flagRO | 736 fl |= flagRO |
737 } | 737 } |
738 fl |= flag(typ.Kind()) << flagKindShift | 738 fl |= flag(typ.Kind()) << flagKindShift |
739 | 739 |
740 var val unsafe.Pointer | 740 var val unsafe.Pointer |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 return float64(*(*float32)(unsafe.Pointer(&v.val))) | 803 return float64(*(*float32)(unsafe.Pointer(&v.val))) |
804 case Float64: | 804 case Float64: |
805 if v.flag&flagIndir != 0 { | 805 if v.flag&flagIndir != 0 { |
806 return *(*float64)(v.val) | 806 return *(*float64)(v.val) |
807 } | 807 } |
808 return *(*float64)(unsafe.Pointer(&v.val)) | 808 return *(*float64)(unsafe.Pointer(&v.val)) |
809 } | 809 } |
810 panic(&ValueError{"reflect.Value.Float", k}) | 810 panic(&ValueError{"reflect.Value.Float", k}) |
811 } | 811 } |
812 | 812 |
813 var uint8Type = TypeOf(uint8(0)).(*commonType) | 813 var uint8Type = TypeOf(uint8(0)).(*rtype) |
814 | 814 |
815 // Index returns v's i'th element. | 815 // Index returns v's i'th element. |
816 // It panics if v's Kind is not Array, Slice, or String or i is out of range. | 816 // It panics if v's Kind is not Array, Slice, or String or i is out of range. |
817 func (v Value) Index(i int) Value { | 817 func (v Value) Index(i int) Value { |
818 k := v.kind() | 818 k := v.kind() |
819 switch k { | 819 switch k { |
820 case Array: | 820 case Array: |
821 tt := (*arrayType)(unsafe.Pointer(v.typ)) | 821 tt := (*arrayType)(unsafe.Pointer(v.typ)) |
822 if i < 0 || i > int(tt.len) { | 822 if i < 0 || i > int(tt.len) { |
823 panic("reflect: array index out of range") | 823 panic("reflect: array index out of range") |
824 } | 824 } |
825 » » typ := toCommonType(tt.elem) | 825 » » typ := tt.elem |
826 fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as o
verall array | 826 fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as o
verall array |
827 fl |= flag(typ.Kind()) << flagKindShift | 827 fl |= flag(typ.Kind()) << flagKindShift |
828 offset := uintptr(i) * typ.size | 828 offset := uintptr(i) * typ.size |
829 | 829 |
830 var val unsafe.Pointer | 830 var val unsafe.Pointer |
831 switch { | 831 switch { |
832 case fl&flagIndir != 0: | 832 case fl&flagIndir != 0: |
833 // Indirect. Just bump pointer. | 833 // Indirect. Just bump pointer. |
834 val = unsafe.Pointer(uintptr(v.val) + offset) | 834 val = unsafe.Pointer(uintptr(v.val) + offset) |
835 case bigEndian: | 835 case bigEndian: |
836 // Direct. Discard leading bytes. | 836 // Direct. Discard leading bytes. |
837 val = unsafe.Pointer(uintptr(v.val) << (offset * 8)) | 837 val = unsafe.Pointer(uintptr(v.val) << (offset * 8)) |
838 default: | 838 default: |
839 // Direct. Discard leading bytes. | 839 // Direct. Discard leading bytes. |
840 val = unsafe.Pointer(uintptr(v.val) >> (offset * 8)) | 840 val = unsafe.Pointer(uintptr(v.val) >> (offset * 8)) |
841 } | 841 } |
842 return Value{typ, val, fl} | 842 return Value{typ, val, fl} |
843 | 843 |
844 case Slice: | 844 case Slice: |
845 // Element flag same as Elem of Ptr. | 845 // Element flag same as Elem of Ptr. |
846 // Addressable, indirect, possibly read-only. | 846 // Addressable, indirect, possibly read-only. |
847 fl := flagAddr | flagIndir | v.flag&flagRO | 847 fl := flagAddr | flagIndir | v.flag&flagRO |
848 s := (*SliceHeader)(v.val) | 848 s := (*SliceHeader)(v.val) |
849 if i < 0 || i >= s.Len { | 849 if i < 0 || i >= s.Len { |
850 panic("reflect: slice index out of range") | 850 panic("reflect: slice index out of range") |
851 } | 851 } |
852 tt := (*sliceType)(unsafe.Pointer(v.typ)) | 852 tt := (*sliceType)(unsafe.Pointer(v.typ)) |
853 » » typ := toCommonType(tt.elem) | 853 » » typ := tt.elem |
854 fl |= flag(typ.Kind()) << flagKindShift | 854 fl |= flag(typ.Kind()) << flagKindShift |
855 val := unsafe.Pointer(s.Data + uintptr(i)*typ.size) | 855 val := unsafe.Pointer(s.Data + uintptr(i)*typ.size) |
856 return Value{typ, val, fl} | 856 return Value{typ, val, fl} |
857 | 857 |
858 case String: | 858 case String: |
859 fl := v.flag&flagRO | flag(Uint8<<flagKindShift) | 859 fl := v.flag&flagRO | flag(Uint8<<flagKindShift) |
860 s := (*StringHeader)(v.val) | 860 s := (*StringHeader)(v.val) |
861 if i < 0 || i >= s.Len { | 861 if i < 0 || i >= s.Len { |
862 panic("reflect: string index out of range") | 862 panic("reflect: string index out of range") |
863 } | 863 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 if v.NumMethod() == 0 { | 937 if v.NumMethod() == 0 { |
938 return *(*interface{})(v.val) | 938 return *(*interface{})(v.val) |
939 } | 939 } |
940 return *(*interface { | 940 return *(*interface { |
941 M() | 941 M() |
942 })(v.val) | 942 })(v.val) |
943 } | 943 } |
944 | 944 |
945 // Non-interface value. | 945 // Non-interface value. |
946 var eface emptyInterface | 946 var eface emptyInterface |
947 » eface.typ = v.typ.runtimeType() | 947 » eface.typ = v.typ |
948 eface.word = v.iword() | 948 eface.word = v.iword() |
949 | 949 |
950 if v.flag&flagIndir != 0 && v.typ.size > ptrSize { | 950 if v.flag&flagIndir != 0 && v.typ.size > ptrSize { |
951 // eface.word is a pointer to the actual data, | 951 // eface.word is a pointer to the actual data, |
952 // which might be changed. We need to return | 952 // which might be changed. We need to return |
953 // a pointer to unchanging data, so make a copy. | 953 // a pointer to unchanging data, so make a copy. |
954 ptr := unsafe_New(v.typ) | 954 ptr := unsafe_New(v.typ) |
955 memmove(ptr, unsafe.Pointer(eface.word), v.typ.size) | 955 memmove(ptr, unsafe.Pointer(eface.word), v.typ.size) |
956 eface.word = iword(ptr) | 956 eface.word = iword(ptr) |
957 } | 957 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 v.mustBe(Map) | 1038 v.mustBe(Map) |
1039 tt := (*mapType)(unsafe.Pointer(v.typ)) | 1039 tt := (*mapType)(unsafe.Pointer(v.typ)) |
1040 | 1040 |
1041 // Do not require key to be exported, so that DeepEqual | 1041 // Do not require key to be exported, so that DeepEqual |
1042 // and other programs can use all the keys returned by | 1042 // and other programs can use all the keys returned by |
1043 // MapKeys as arguments to MapIndex. If either the map | 1043 // MapKeys as arguments to MapIndex. If either the map |
1044 // or the key is unexported, though, the result will be | 1044 // or the key is unexported, though, the result will be |
1045 // considered unexported. This is consistent with the | 1045 // considered unexported. This is consistent with the |
1046 // behavior for structs, which allow read but not write | 1046 // behavior for structs, which allow read but not write |
1047 // of unexported fields. | 1047 // of unexported fields. |
1048 » key = key.assignTo("reflect.Value.MapIndex", toCommonType(tt.key), nil) | 1048 » key = key.assignTo("reflect.Value.MapIndex", tt.key, nil) |
1049 | 1049 |
1050 » word, ok := mapaccess(v.typ.runtimeType(), v.iword(), key.iword()) | 1050 » word, ok := mapaccess(v.typ, v.iword(), key.iword()) |
1051 if !ok { | 1051 if !ok { |
1052 return Value{} | 1052 return Value{} |
1053 } | 1053 } |
1054 » typ := toCommonType(tt.elem) | 1054 » typ := tt.elem |
1055 fl := (v.flag | key.flag) & flagRO | 1055 fl := (v.flag | key.flag) & flagRO |
1056 if typ.size > ptrSize { | 1056 if typ.size > ptrSize { |
1057 fl |= flagIndir | 1057 fl |= flagIndir |
1058 } | 1058 } |
1059 fl |= flag(typ.Kind()) << flagKindShift | 1059 fl |= flag(typ.Kind()) << flagKindShift |
1060 return Value{typ, unsafe.Pointer(word), fl} | 1060 return Value{typ, unsafe.Pointer(word), fl} |
1061 } | 1061 } |
1062 | 1062 |
1063 // MapKeys returns a slice containing all the keys present in the map, | 1063 // MapKeys returns a slice containing all the keys present in the map, |
1064 // in unspecified order. | 1064 // in unspecified order. |
1065 // It panics if v's Kind is not Map. | 1065 // It panics if v's Kind is not Map. |
1066 // It returns an empty slice if v represents a nil map. | 1066 // It returns an empty slice if v represents a nil map. |
1067 func (v Value) MapKeys() []Value { | 1067 func (v Value) MapKeys() []Value { |
1068 v.mustBe(Map) | 1068 v.mustBe(Map) |
1069 tt := (*mapType)(unsafe.Pointer(v.typ)) | 1069 tt := (*mapType)(unsafe.Pointer(v.typ)) |
1070 » keyType := toCommonType(tt.key) | 1070 » keyType := tt.key |
1071 | 1071 |
1072 fl := v.flag & flagRO | 1072 fl := v.flag & flagRO |
1073 fl |= flag(keyType.Kind()) << flagKindShift | 1073 fl |= flag(keyType.Kind()) << flagKindShift |
1074 if keyType.size > ptrSize { | 1074 if keyType.size > ptrSize { |
1075 fl |= flagIndir | 1075 fl |= flagIndir |
1076 } | 1076 } |
1077 | 1077 |
1078 m := v.iword() | 1078 m := v.iword() |
1079 mlen := int(0) | 1079 mlen := int(0) |
1080 if m != nil { | 1080 if m != nil { |
1081 mlen = maplen(m) | 1081 mlen = maplen(m) |
1082 } | 1082 } |
1083 » it := mapiterinit(v.typ.runtimeType(), m) | 1083 » it := mapiterinit(v.typ, m) |
1084 a := make([]Value, mlen) | 1084 a := make([]Value, mlen) |
1085 var i int | 1085 var i int |
1086 for i = 0; i < len(a); i++ { | 1086 for i = 0; i < len(a); i++ { |
1087 keyWord, ok := mapiterkey(it) | 1087 keyWord, ok := mapiterkey(it) |
1088 if !ok { | 1088 if !ok { |
1089 break | 1089 break |
1090 } | 1090 } |
1091 a[i] = Value{keyType, unsafe.Pointer(keyWord), fl} | 1091 a[i] = Value{keyType, unsafe.Pointer(keyWord), fl} |
1092 mapiternext(it) | 1092 mapiternext(it) |
1093 } | 1093 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1242 return v.recv(false) | 1242 return v.recv(false) |
1243 } | 1243 } |
1244 | 1244 |
1245 // internal recv, possibly non-blocking (nb). | 1245 // internal recv, possibly non-blocking (nb). |
1246 // v is known to be a channel. | 1246 // v is known to be a channel. |
1247 func (v Value) recv(nb bool) (val Value, ok bool) { | 1247 func (v Value) recv(nb bool) (val Value, ok bool) { |
1248 tt := (*chanType)(unsafe.Pointer(v.typ)) | 1248 tt := (*chanType)(unsafe.Pointer(v.typ)) |
1249 if ChanDir(tt.dir)&RecvDir == 0 { | 1249 if ChanDir(tt.dir)&RecvDir == 0 { |
1250 panic("recv on send-only channel") | 1250 panic("recv on send-only channel") |
1251 } | 1251 } |
1252 » word, selected, ok := chanrecv(v.typ.runtimeType(), v.iword(), nb) | 1252 » word, selected, ok := chanrecv(v.typ, v.iword(), nb) |
1253 if selected { | 1253 if selected { |
1254 » » typ := toCommonType(tt.elem) | 1254 » » typ := tt.elem |
1255 fl := flag(typ.Kind()) << flagKindShift | 1255 fl := flag(typ.Kind()) << flagKindShift |
1256 if typ.size > ptrSize { | 1256 if typ.size > ptrSize { |
1257 fl |= flagIndir | 1257 fl |= flagIndir |
1258 } | 1258 } |
1259 val = Value{typ, unsafe.Pointer(word), fl} | 1259 val = Value{typ, unsafe.Pointer(word), fl} |
1260 } | 1260 } |
1261 return | 1261 return |
1262 } | 1262 } |
1263 | 1263 |
1264 // Send sends x on the channel v. | 1264 // Send sends x on the channel v. |
1265 // It panics if v's kind is not Chan or if x's type is not the same type as v's
element type. | 1265 // It panics if v's kind is not Chan or if x's type is not the same type as v's
element type. |
1266 // As in Go, x's value must be assignable to the channel's element type. | 1266 // As in Go, x's value must be assignable to the channel's element type. |
1267 func (v Value) Send(x Value) { | 1267 func (v Value) Send(x Value) { |
1268 v.mustBe(Chan) | 1268 v.mustBe(Chan) |
1269 v.mustBeExported() | 1269 v.mustBeExported() |
1270 v.send(x, false) | 1270 v.send(x, false) |
1271 } | 1271 } |
1272 | 1272 |
1273 // internal send, possibly non-blocking. | 1273 // internal send, possibly non-blocking. |
1274 // v is known to be a channel. | 1274 // v is known to be a channel. |
1275 func (v Value) send(x Value, nb bool) (selected bool) { | 1275 func (v Value) send(x Value, nb bool) (selected bool) { |
1276 tt := (*chanType)(unsafe.Pointer(v.typ)) | 1276 tt := (*chanType)(unsafe.Pointer(v.typ)) |
1277 if ChanDir(tt.dir)&SendDir == 0 { | 1277 if ChanDir(tt.dir)&SendDir == 0 { |
1278 panic("send on recv-only channel") | 1278 panic("send on recv-only channel") |
1279 } | 1279 } |
1280 x.mustBeExported() | 1280 x.mustBeExported() |
1281 » x = x.assignTo("reflect.Value.Send", toCommonType(tt.elem), nil) | 1281 » x = x.assignTo("reflect.Value.Send", tt.elem, nil) |
1282 » return chansend(v.typ.runtimeType(), v.iword(), x.iword(), nb) | 1282 » return chansend(v.typ, v.iword(), x.iword(), nb) |
1283 } | 1283 } |
1284 | 1284 |
1285 // Set assigns x to the value v. | 1285 // Set assigns x to the value v. |
1286 // It panics if CanSet returns false. | 1286 // It panics if CanSet returns false. |
1287 // As in Go, x's value must be assignable to v's type. | 1287 // As in Go, x's value must be assignable to v's type. |
1288 func (v Value) Set(x Value) { | 1288 func (v Value) Set(x Value) { |
1289 v.mustBeAssignable() | 1289 v.mustBeAssignable() |
1290 x.mustBeExported() // do not let unexported x leak | 1290 x.mustBeExported() // do not let unexported x leak |
1291 var target *interface{} | 1291 var target *interface{} |
1292 if v.kind() == Interface { | 1292 if v.kind() == Interface { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 // SetMapIndex sets the value associated with key in the map v to val. | 1394 // SetMapIndex sets the value associated with key in the map v to val. |
1395 // It panics if v's Kind is not Map. | 1395 // It panics if v's Kind is not Map. |
1396 // If val is the zero Value, SetMapIndex deletes the key from the map. | 1396 // If val is the zero Value, SetMapIndex deletes the key from the map. |
1397 // As in Go, key's value must be assignable to the map's key type, | 1397 // As in Go, key's value must be assignable to the map's key type, |
1398 // and val's value must be assignable to the map's value type. | 1398 // and val's value must be assignable to the map's value type. |
1399 func (v Value) SetMapIndex(key, val Value) { | 1399 func (v Value) SetMapIndex(key, val Value) { |
1400 v.mustBe(Map) | 1400 v.mustBe(Map) |
1401 v.mustBeExported() | 1401 v.mustBeExported() |
1402 key.mustBeExported() | 1402 key.mustBeExported() |
1403 tt := (*mapType)(unsafe.Pointer(v.typ)) | 1403 tt := (*mapType)(unsafe.Pointer(v.typ)) |
1404 » key = key.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.key), ni
l) | 1404 » key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil) |
1405 if val.typ != nil { | 1405 if val.typ != nil { |
1406 val.mustBeExported() | 1406 val.mustBeExported() |
1407 » » val = val.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.
elem), nil) | 1407 » » val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil) |
1408 » } | 1408 » } |
1409 » mapassign(v.typ.runtimeType(), v.iword(), key.iword(), val.iword(), val.
typ != nil) | 1409 » mapassign(v.typ, v.iword(), key.iword(), val.iword(), val.typ != nil) |
1410 } | 1410 } |
1411 | 1411 |
1412 // SetUint sets v's underlying value to x. | 1412 // SetUint sets v's underlying value to x. |
1413 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64,
or if CanSet() is false. | 1413 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64,
or if CanSet() is false. |
1414 func (v Value) SetUint(x uint64) { | 1414 func (v Value) SetUint(x uint64) { |
1415 v.mustBeAssignable() | 1415 v.mustBeAssignable() |
1416 switch k := v.kind(); k { | 1416 switch k := v.kind(); k { |
1417 default: | 1417 default: |
1418 panic(&ValueError{"reflect.Value.SetUint", k}) | 1418 panic(&ValueError{"reflect.Value.SetUint", k}) |
1419 case Uint: | 1419 case Uint: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 switch k := v.kind(); k { | 1458 switch k := v.kind(); k { |
1459 default: | 1459 default: |
1460 panic(&ValueError{"reflect.Value.Slice", k}) | 1460 panic(&ValueError{"reflect.Value.Slice", k}) |
1461 | 1461 |
1462 case Array: | 1462 case Array: |
1463 if v.flag&flagAddr == 0 { | 1463 if v.flag&flagAddr == 0 { |
1464 panic("reflect.Value.Slice: slice of unaddressable array
") | 1464 panic("reflect.Value.Slice: slice of unaddressable array
") |
1465 } | 1465 } |
1466 tt := (*arrayType)(unsafe.Pointer(v.typ)) | 1466 tt := (*arrayType)(unsafe.Pointer(v.typ)) |
1467 cap = int(tt.len) | 1467 cap = int(tt.len) |
1468 » » typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice))) | 1468 » » typ = (*sliceType)(unsafe.Pointer(tt.slice)) |
1469 base = v.val | 1469 base = v.val |
1470 | 1470 |
1471 case Slice: | 1471 case Slice: |
1472 typ = (*sliceType)(unsafe.Pointer(v.typ)) | 1472 typ = (*sliceType)(unsafe.Pointer(v.typ)) |
1473 s := (*SliceHeader)(v.val) | 1473 s := (*SliceHeader)(v.val) |
1474 base = unsafe.Pointer(s.Data) | 1474 base = unsafe.Pointer(s.Data) |
1475 cap = s.Cap | 1475 cap = s.Cap |
1476 | 1476 |
1477 case String: | 1477 case String: |
1478 s := (*StringHeader)(v.val) | 1478 s := (*StringHeader)(v.val) |
1479 if beg < 0 || end < beg || end > s.Len { | 1479 if beg < 0 || end < beg || end > s.Len { |
1480 panic("reflect.Value.Slice: string slice index out of bo
unds") | 1480 panic("reflect.Value.Slice: string slice index out of bo
unds") |
1481 } | 1481 } |
1482 var x string | 1482 var x string |
1483 val := (*StringHeader)(unsafe.Pointer(&x)) | 1483 val := (*StringHeader)(unsafe.Pointer(&x)) |
1484 val.Data = s.Data + uintptr(beg) | 1484 val.Data = s.Data + uintptr(beg) |
1485 val.Len = end - beg | 1485 val.Len = end - beg |
1486 return Value{v.typ, unsafe.Pointer(&x), v.flag} | 1486 return Value{v.typ, unsafe.Pointer(&x), v.flag} |
1487 } | 1487 } |
1488 | 1488 |
1489 if beg < 0 || end < beg || end > cap { | 1489 if beg < 0 || end < beg || end > cap { |
1490 panic("reflect.Value.Slice: slice index out of bounds") | 1490 panic("reflect.Value.Slice: slice index out of bounds") |
1491 } | 1491 } |
1492 | 1492 |
1493 // Declare slice so that gc can see the base pointer in it. | 1493 // Declare slice so that gc can see the base pointer in it. |
1494 var x []byte | 1494 var x []byte |
1495 | 1495 |
1496 // Reinterpret as *SliceHeader to edit. | 1496 // Reinterpret as *SliceHeader to edit. |
1497 s := (*SliceHeader)(unsafe.Pointer(&x)) | 1497 s := (*SliceHeader)(unsafe.Pointer(&x)) |
1498 » s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size() | 1498 » s.Data = uintptr(base) + uintptr(beg)*typ.elem.Size() |
1499 s.Len = end - beg | 1499 s.Len = end - beg |
1500 s.Cap = cap - beg | 1500 s.Cap = cap - beg |
1501 | 1501 |
1502 fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift | 1502 fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift |
1503 return Value{typ.common(), unsafe.Pointer(&x), fl} | 1503 return Value{typ.common(), unsafe.Pointer(&x), fl} |
1504 } | 1504 } |
1505 | 1505 |
1506 // String returns the string v's underlying value, as a string. | 1506 // String returns the string v's underlying value, as a string. |
1507 // String is a special case because of Go's String method convention. | 1507 // String is a special case because of Go's String method convention. |
1508 // Unlike the other getters, it does not panic if v's Kind is not String. | 1508 // Unlike the other getters, it does not panic if v's Kind is not String. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 // Method value. | 1554 // Method value. |
1555 // v.typ describes the receiver, not the method type. | 1555 // v.typ describes the receiver, not the method type. |
1556 i := int(v.flag) >> flagMethodShift | 1556 i := int(v.flag) >> flagMethodShift |
1557 if v.typ.Kind() == Interface { | 1557 if v.typ.Kind() == Interface { |
1558 // Method on interface. | 1558 // Method on interface. |
1559 tt := (*interfaceType)(unsafe.Pointer(v.typ)) | 1559 tt := (*interfaceType)(unsafe.Pointer(v.typ)) |
1560 if i < 0 || i >= len(tt.methods) { | 1560 if i < 0 || i >= len(tt.methods) { |
1561 panic("reflect: broken Value") | 1561 panic("reflect: broken Value") |
1562 } | 1562 } |
1563 m := &tt.methods[i] | 1563 m := &tt.methods[i] |
1564 » » return toCommonType(m.typ) | 1564 » » return m.typ |
1565 } | 1565 } |
1566 // Method on concrete type. | 1566 // Method on concrete type. |
1567 ut := v.typ.uncommon() | 1567 ut := v.typ.uncommon() |
1568 if ut == nil || i < 0 || i >= len(ut.methods) { | 1568 if ut == nil || i < 0 || i >= len(ut.methods) { |
1569 panic("reflect: broken Value") | 1569 panic("reflect: broken Value") |
1570 } | 1570 } |
1571 m := &ut.methods[i] | 1571 m := &ut.methods[i] |
1572 » return toCommonType(m.mtyp) | 1572 » return m.mtyp |
1573 } | 1573 } |
1574 | 1574 |
1575 // Uint returns v's underlying value, as a uint64. | 1575 // Uint returns v's underlying value, as a uint64. |
1576 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64. | 1576 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64. |
1577 func (v Value) Uint() uint64 { | 1577 func (v Value) Uint() uint64 { |
1578 k := v.kind() | 1578 k := v.kind() |
1579 var p unsafe.Pointer | 1579 var p unsafe.Pointer |
1580 if v.flag&flagIndir != 0 { | 1580 if v.flag&flagIndir != 0 { |
1581 p = v.val | 1581 p = v.val |
1582 } else { | 1582 } else { |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 } else { | 1736 } else { |
1737 sa = unsafe.Pointer((*SliceHeader)(src.val).Data) | 1737 sa = unsafe.Pointer((*SliceHeader)(src.val).Data) |
1738 } | 1738 } |
1739 memmove(da, sa, uintptr(n)*de.Size()) | 1739 memmove(da, sa, uintptr(n)*de.Size()) |
1740 return n | 1740 return n |
1741 } | 1741 } |
1742 | 1742 |
1743 // A runtimeSelect is a single case passed to rselect. | 1743 // A runtimeSelect is a single case passed to rselect. |
1744 // This must match ../runtime/chan.c:/runtimeSelect | 1744 // This must match ../runtime/chan.c:/runtimeSelect |
1745 type runtimeSelect struct { | 1745 type runtimeSelect struct { |
1746 » dir uintptr // 0, SendDir, or RecvDir | 1746 » dir uintptr // 0, SendDir, or RecvDir |
1747 » typ *runtimeType // channel type | 1747 » typ *rtype // channel type |
1748 » ch iword // interface word for channel | 1748 » ch iword // interface word for channel |
1749 » val iword // interface word for value (for SendDir) | 1749 » val iword // interface word for value (for SendDir) |
1750 } | 1750 } |
1751 | 1751 |
1752 // rselect runs a select. It returns the index of the chosen case, | 1752 // rselect runs a select. It returns the index of the chosen case, |
1753 // and if the case was a receive, the interface word of the received | 1753 // and if the case was a receive, the interface word of the received |
1754 // value and the conventional OK bool to indicate whether the receive | 1754 // value and the conventional OK bool to indicate whether the receive |
1755 // corresponds to a sent value. | 1755 // corresponds to a sent value. |
1756 func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool) | 1756 func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool) |
1757 | 1757 |
1758 // A SelectDir describes the communication direction of a select case. | 1758 // A SelectDir describes the communication direction of a select case. |
1759 type SelectDir int | 1759 type SelectDir int |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 if !ch.IsValid() { | 1826 if !ch.IsValid() { |
1827 break | 1827 break |
1828 } | 1828 } |
1829 ch.mustBe(Chan) | 1829 ch.mustBe(Chan) |
1830 ch.mustBeExported() | 1830 ch.mustBeExported() |
1831 tt := (*chanType)(unsafe.Pointer(ch.typ)) | 1831 tt := (*chanType)(unsafe.Pointer(ch.typ)) |
1832 if ChanDir(tt.dir)&SendDir == 0 { | 1832 if ChanDir(tt.dir)&SendDir == 0 { |
1833 panic("reflect.Select: SendDir case using recv-o
nly channel") | 1833 panic("reflect.Select: SendDir case using recv-o
nly channel") |
1834 } | 1834 } |
1835 rc.ch = ch.iword() | 1835 rc.ch = ch.iword() |
1836 » » » rc.typ = tt.runtimeType() | 1836 » » » rc.typ = &tt.rtype |
1837 v := c.Send | 1837 v := c.Send |
1838 if !v.IsValid() { | 1838 if !v.IsValid() { |
1839 panic("reflect.Select: SendDir case missing Send
value") | 1839 panic("reflect.Select: SendDir case missing Send
value") |
1840 } | 1840 } |
1841 v.mustBeExported() | 1841 v.mustBeExported() |
1842 » » » v = v.assignTo("reflect.Select", toCommonType(tt.elem),
nil) | 1842 » » » v = v.assignTo("reflect.Select", tt.elem, nil) |
1843 rc.val = v.iword() | 1843 rc.val = v.iword() |
1844 | 1844 |
1845 case SelectRecv: | 1845 case SelectRecv: |
1846 if c.Send.IsValid() { | 1846 if c.Send.IsValid() { |
1847 panic("reflect.Select: RecvDir case has Send val
ue") | 1847 panic("reflect.Select: RecvDir case has Send val
ue") |
1848 } | 1848 } |
1849 ch := c.Chan | 1849 ch := c.Chan |
1850 if !ch.IsValid() { | 1850 if !ch.IsValid() { |
1851 break | 1851 break |
1852 } | 1852 } |
1853 ch.mustBe(Chan) | 1853 ch.mustBe(Chan) |
1854 ch.mustBeExported() | 1854 ch.mustBeExported() |
1855 tt := (*chanType)(unsafe.Pointer(ch.typ)) | 1855 tt := (*chanType)(unsafe.Pointer(ch.typ)) |
1856 » » » rc.typ = tt.runtimeType() | 1856 » » » rc.typ = &tt.rtype |
1857 if ChanDir(tt.dir)&RecvDir == 0 { | 1857 if ChanDir(tt.dir)&RecvDir == 0 { |
1858 panic("reflect.Select: RecvDir case using send-o
nly channel") | 1858 panic("reflect.Select: RecvDir case using send-o
nly channel") |
1859 } | 1859 } |
1860 rc.ch = ch.iword() | 1860 rc.ch = ch.iword() |
1861 } | 1861 } |
1862 } | 1862 } |
1863 | 1863 |
1864 chosen, word, recvOK := rselect(runcases) | 1864 chosen, word, recvOK := rselect(runcases) |
1865 if runcases[chosen].dir == uintptr(SelectRecv) { | 1865 if runcases[chosen].dir == uintptr(SelectRecv) { |
1866 » » tt := (*chanType)(unsafe.Pointer(toCommonType(runcases[chosen].t
yp))) | 1866 » » tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ)) |
1867 » » typ := toCommonType(tt.elem) | 1867 » » typ := tt.elem |
1868 fl := flag(typ.Kind()) << flagKindShift | 1868 fl := flag(typ.Kind()) << flagKindShift |
1869 if typ.size > ptrSize { | 1869 if typ.size > ptrSize { |
1870 fl |= flagIndir | 1870 fl |= flagIndir |
1871 } | 1871 } |
1872 recv = Value{typ, unsafe.Pointer(word), fl} | 1872 recv = Value{typ, unsafe.Pointer(word), fl} |
1873 } | 1873 } |
1874 return chosen, recv, recvOK | 1874 return chosen, recv, recvOK |
1875 } | 1875 } |
1876 | 1876 |
1877 /* | 1877 /* |
1878 * constructors | 1878 * constructors |
1879 */ | 1879 */ |
1880 | 1880 |
1881 // implemented in package runtime | 1881 // implemented in package runtime |
1882 func unsafe_New(Type) unsafe.Pointer | 1882 func unsafe_New(*rtype) unsafe.Pointer |
1883 func unsafe_NewArray(Type, int) unsafe.Pointer | 1883 func unsafe_NewArray(*rtype, int) unsafe.Pointer |
1884 | 1884 |
1885 // MakeSlice creates a new zero-initialized slice value | 1885 // MakeSlice creates a new zero-initialized slice value |
1886 // for the specified slice type, length, and capacity. | 1886 // for the specified slice type, length, and capacity. |
1887 func MakeSlice(typ Type, len, cap int) Value { | 1887 func MakeSlice(typ Type, len, cap int) Value { |
1888 if typ.Kind() != Slice { | 1888 if typ.Kind() != Slice { |
1889 panic("reflect.MakeSlice of non-slice type") | 1889 panic("reflect.MakeSlice of non-slice type") |
1890 } | 1890 } |
1891 if len < 0 { | 1891 if len < 0 { |
1892 panic("reflect.MakeSlice: negative len") | 1892 panic("reflect.MakeSlice: negative len") |
1893 } | 1893 } |
1894 if cap < 0 { | 1894 if cap < 0 { |
1895 panic("reflect.MakeSlice: negative cap") | 1895 panic("reflect.MakeSlice: negative cap") |
1896 } | 1896 } |
1897 if len > cap { | 1897 if len > cap { |
1898 panic("reflect.MakeSlice: len > cap") | 1898 panic("reflect.MakeSlice: len > cap") |
1899 } | 1899 } |
1900 | 1900 |
1901 // Declare slice so that gc can see the base pointer in it. | 1901 // Declare slice so that gc can see the base pointer in it. |
1902 var x []byte | 1902 var x []byte |
1903 | 1903 |
1904 // Reinterpret as *SliceHeader to edit. | 1904 // Reinterpret as *SliceHeader to edit. |
1905 s := (*SliceHeader)(unsafe.Pointer(&x)) | 1905 s := (*SliceHeader)(unsafe.Pointer(&x)) |
1906 » s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap)) | 1906 » s.Data = uintptr(unsafe_NewArray(typ.Elem().(*rtype), cap)) |
1907 s.Len = len | 1907 s.Len = len |
1908 s.Cap = cap | 1908 s.Cap = cap |
1909 | 1909 |
1910 return Value{typ.common(), unsafe.Pointer(&x), flagIndir | flag(Slice)<<
flagKindShift} | 1910 return Value{typ.common(), unsafe.Pointer(&x), flagIndir | flag(Slice)<<
flagKindShift} |
1911 } | 1911 } |
1912 | 1912 |
1913 // MakeChan creates a new channel with the specified type and buffer size. | 1913 // MakeChan creates a new channel with the specified type and buffer size. |
1914 func MakeChan(typ Type, buffer int) Value { | 1914 func MakeChan(typ Type, buffer int) Value { |
1915 if typ.Kind() != Chan { | 1915 if typ.Kind() != Chan { |
1916 panic("reflect.MakeChan of non-chan type") | 1916 panic("reflect.MakeChan of non-chan type") |
1917 } | 1917 } |
1918 if buffer < 0 { | 1918 if buffer < 0 { |
1919 panic("reflect.MakeChan: negative buffer size") | 1919 panic("reflect.MakeChan: negative buffer size") |
1920 } | 1920 } |
1921 if typ.ChanDir() != BothDir { | 1921 if typ.ChanDir() != BothDir { |
1922 panic("reflect.MakeChan: unidirectional channel type") | 1922 panic("reflect.MakeChan: unidirectional channel type") |
1923 } | 1923 } |
1924 » ch := makechan(typ.runtimeType(), uint64(buffer)) | 1924 » ch := makechan(typ.(*rtype), uint64(buffer)) |
1925 return Value{typ.common(), unsafe.Pointer(ch), flag(Chan) << flagKindShi
ft} | 1925 return Value{typ.common(), unsafe.Pointer(ch), flag(Chan) << flagKindShi
ft} |
1926 } | 1926 } |
1927 | 1927 |
1928 // MakeMap creates a new map of the specified type. | 1928 // MakeMap creates a new map of the specified type. |
1929 func MakeMap(typ Type) Value { | 1929 func MakeMap(typ Type) Value { |
1930 if typ.Kind() != Map { | 1930 if typ.Kind() != Map { |
1931 panic("reflect.MakeMap of non-map type") | 1931 panic("reflect.MakeMap of non-map type") |
1932 } | 1932 } |
1933 » m := makemap(typ.runtimeType()) | 1933 » m := makemap(typ.(*rtype)) |
1934 return Value{typ.common(), unsafe.Pointer(m), flag(Map) << flagKindShift
} | 1934 return Value{typ.common(), unsafe.Pointer(m), flag(Map) << flagKindShift
} |
1935 } | 1935 } |
1936 | 1936 |
1937 // Indirect returns the value that v points to. | 1937 // Indirect returns the value that v points to. |
1938 // If v is a nil pointer, Indirect returns a zero Value. | 1938 // If v is a nil pointer, Indirect returns a zero Value. |
1939 // If v is not a pointer, Indirect returns v. | 1939 // If v is not a pointer, Indirect returns v. |
1940 func Indirect(v Value) Value { | 1940 func Indirect(v Value) Value { |
1941 if v.Kind() != Ptr { | 1941 if v.Kind() != Ptr { |
1942 return v | 1942 return v |
1943 } | 1943 } |
(...skipping 10 matching lines...) Expand all Loading... |
1954 // TODO(rsc): Eliminate this terrible hack. | 1954 // TODO(rsc): Eliminate this terrible hack. |
1955 // In the call to packValue, eface.typ doesn't escape, | 1955 // In the call to packValue, eface.typ doesn't escape, |
1956 // and eface.word is an integer. So it looks like | 1956 // and eface.word is an integer. So it looks like |
1957 // i (= eface) doesn't escape. But really it does, | 1957 // i (= eface) doesn't escape. But really it does, |
1958 // because eface.word is actually a pointer. | 1958 // because eface.word is actually a pointer. |
1959 escapes(i) | 1959 escapes(i) |
1960 | 1960 |
1961 // For an interface value with the noAddr bit set, | 1961 // For an interface value with the noAddr bit set, |
1962 // the representation is identical to an empty interface. | 1962 // the representation is identical to an empty interface. |
1963 eface := *(*emptyInterface)(unsafe.Pointer(&i)) | 1963 eface := *(*emptyInterface)(unsafe.Pointer(&i)) |
1964 » typ := toCommonType(eface.typ) | 1964 » typ := eface.typ |
1965 fl := flag(typ.Kind()) << flagKindShift | 1965 fl := flag(typ.Kind()) << flagKindShift |
1966 if typ.size > ptrSize { | 1966 if typ.size > ptrSize { |
1967 fl |= flagIndir | 1967 fl |= flagIndir |
1968 } | 1968 } |
1969 return Value{typ, unsafe.Pointer(eface.word), fl} | 1969 return Value{typ, unsafe.Pointer(eface.word), fl} |
1970 } | 1970 } |
1971 | 1971 |
1972 // Zero returns a Value representing the zero value for the specified type. | 1972 // Zero returns a Value representing the zero value for the specified type. |
1973 // The result is different from the zero value of the Value struct, | 1973 // The result is different from the zero value of the Value struct, |
1974 // which represents no value at all. | 1974 // which represents no value at all. |
1975 // For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0. | 1975 // For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0. |
1976 // The returned value is neither addressable nor settable. | 1976 // The returned value is neither addressable nor settable. |
1977 func Zero(typ Type) Value { | 1977 func Zero(typ Type) Value { |
1978 if typ == nil { | 1978 if typ == nil { |
1979 panic("reflect: Zero(nil)") | 1979 panic("reflect: Zero(nil)") |
1980 } | 1980 } |
1981 t := typ.common() | 1981 t := typ.common() |
1982 fl := flag(t.Kind()) << flagKindShift | 1982 fl := flag(t.Kind()) << flagKindShift |
1983 if t.size <= ptrSize { | 1983 if t.size <= ptrSize { |
1984 return Value{t, nil, fl} | 1984 return Value{t, nil, fl} |
1985 } | 1985 } |
1986 » return Value{t, unsafe_New(typ), fl | flagIndir} | 1986 » return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir} |
1987 } | 1987 } |
1988 | 1988 |
1989 // New returns a Value representing a pointer to a new zero value | 1989 // New returns a Value representing a pointer to a new zero value |
1990 // for the specified type. That is, the returned Value's Type is PtrTo(t). | 1990 // for the specified type. That is, the returned Value's Type is PtrTo(t). |
1991 func New(typ Type) Value { | 1991 func New(typ Type) Value { |
1992 if typ == nil { | 1992 if typ == nil { |
1993 panic("reflect: New(nil)") | 1993 panic("reflect: New(nil)") |
1994 } | 1994 } |
1995 » ptr := unsafe_New(typ) | 1995 » ptr := unsafe_New(typ.(*rtype)) |
1996 fl := flag(Ptr) << flagKindShift | 1996 fl := flag(Ptr) << flagKindShift |
1997 return Value{typ.common().ptrTo(), ptr, fl} | 1997 return Value{typ.common().ptrTo(), ptr, fl} |
1998 } | 1998 } |
1999 | 1999 |
2000 // NewAt returns a Value representing a pointer to a value of the | 2000 // NewAt returns a Value representing a pointer to a value of the |
2001 // specified type, using p as that pointer. | 2001 // specified type, using p as that pointer. |
2002 func NewAt(typ Type, p unsafe.Pointer) Value { | 2002 func NewAt(typ Type, p unsafe.Pointer) Value { |
2003 fl := flag(Ptr) << flagKindShift | 2003 fl := flag(Ptr) << flagKindShift |
2004 return Value{typ.common().ptrTo(), p, fl} | 2004 return Value{typ.common().ptrTo(), p, fl} |
2005 } | 2005 } |
2006 | 2006 |
2007 // assignTo returns a value v that can be assigned directly to typ. | 2007 // assignTo returns a value v that can be assigned directly to typ. |
2008 // It panics if v is not assignable to typ. | 2008 // It panics if v is not assignable to typ. |
2009 // For a conversion to an interface type, target is a suggested scratch space to
use. | 2009 // For a conversion to an interface type, target is a suggested scratch space to
use. |
2010 func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
lue { | 2010 func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value { |
2011 if v.flag&flagMethod != 0 { | 2011 if v.flag&flagMethod != 0 { |
2012 panic(context + ": cannot assign method value to type " + dst.St
ring()) | 2012 panic(context + ": cannot assign method value to type " + dst.St
ring()) |
2013 } | 2013 } |
2014 | 2014 |
2015 switch { | 2015 switch { |
2016 case directlyAssignable(dst, v.typ): | 2016 case directlyAssignable(dst, v.typ): |
2017 // Overwrite type so that they match. | 2017 // Overwrite type so that they match. |
2018 // Same memory layout, so no harm done. | 2018 // Same memory layout, so no harm done. |
2019 v.typ = dst | 2019 v.typ = dst |
2020 fl := v.flag & (flagRO | flagAddr | flagIndir) | 2020 fl := v.flag & (flagRO | flagAddr | flagIndir) |
2021 fl |= flag(dst.Kind()) << flagKindShift | 2021 fl |= flag(dst.Kind()) << flagKindShift |
2022 return Value{dst, v.val, fl} | 2022 return Value{dst, v.val, fl} |
2023 | 2023 |
2024 case implements(dst, v.typ): | 2024 case implements(dst, v.typ): |
2025 if target == nil { | 2025 if target == nil { |
2026 target = new(interface{}) | 2026 target = new(interface{}) |
2027 } | 2027 } |
2028 x := valueInterface(v, false) | 2028 x := valueInterface(v, false) |
2029 if dst.NumMethod() == 0 { | 2029 if dst.NumMethod() == 0 { |
2030 *target = x | 2030 *target = x |
2031 } else { | 2031 } else { |
2032 » » » ifaceE2I(dst.runtimeType(), x, unsafe.Pointer(target)) | 2032 » » » ifaceE2I(dst, x, unsafe.Pointer(target)) |
2033 } | 2033 } |
2034 return Value{dst, unsafe.Pointer(target), flagIndir | flag(Inter
face)<<flagKindShift} | 2034 return Value{dst, unsafe.Pointer(target), flagIndir | flag(Inter
face)<<flagKindShift} |
2035 } | 2035 } |
2036 | 2036 |
2037 // Failed. | 2037 // Failed. |
2038 panic(context + ": value of type " + v.typ.String() + " is not assignabl
e to type " + dst.String()) | 2038 panic(context + ": value of type " + v.typ.String() + " is not assignabl
e to type " + dst.String()) |
2039 } | 2039 } |
2040 | 2040 |
2041 // Convert returns the value v converted to type t. | 2041 // Convert returns the value v converted to type t. |
2042 // If the usual Go conversion rules do not allow conversion | 2042 // If the usual Go conversion rules do not allow conversion |
2043 // of the value v to type t, Convert panics. | 2043 // of the value v to type t, Convert panics. |
2044 func (v Value) Convert(t Type) Value { | 2044 func (v Value) Convert(t Type) Value { |
2045 if v.flag&flagMethod != 0 { | 2045 if v.flag&flagMethod != 0 { |
2046 panic("reflect.Value.Convert: cannot convert method values") | 2046 panic("reflect.Value.Convert: cannot convert method values") |
2047 } | 2047 } |
2048 op := convertOp(t.common(), v.typ) | 2048 op := convertOp(t.common(), v.typ) |
2049 if op == nil { | 2049 if op == nil { |
2050 panic("reflect.Value.Convert: value of type " + v.typ.String() +
" cannot be converted to type " + t.String()) | 2050 panic("reflect.Value.Convert: value of type " + v.typ.String() +
" cannot be converted to type " + t.String()) |
2051 } | 2051 } |
2052 return op(v, t) | 2052 return op(v, t) |
2053 } | 2053 } |
2054 | 2054 |
2055 // convertOp returns the function to convert a value of type src | 2055 // convertOp returns the function to convert a value of type src |
2056 // to a value of type dst. If the conversion is illegal, convertOp returns nil. | 2056 // to a value of type dst. If the conversion is illegal, convertOp returns nil. |
2057 func convertOp(dst, src *commonType) func(Value, Type) Value { | 2057 func convertOp(dst, src *rtype) func(Value, Type) Value { |
2058 switch src.Kind() { | 2058 switch src.Kind() { |
2059 case Int, Int8, Int16, Int32, Int64: | 2059 case Int, Int8, Int16, Int32, Int64: |
2060 switch dst.Kind() { | 2060 switch dst.Kind() { |
2061 case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32
, Uint64, Uintptr: | 2061 case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32
, Uint64, Uintptr: |
2062 return cvtInt | 2062 return cvtInt |
2063 case Float32, Float64: | 2063 case Float32, Float64: |
2064 return cvtIntFloat | 2064 return cvtIntFloat |
2065 case String: | 2065 case String: |
2066 return cvtIntString | 2066 return cvtIntString |
2067 } | 2067 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2134 | 2134 |
2135 return nil | 2135 return nil |
2136 } | 2136 } |
2137 | 2137 |
2138 // makeInt returns a Value of type t equal to bits (possibly truncated), | 2138 // makeInt returns a Value of type t equal to bits (possibly truncated), |
2139 // where t is a signed or unsigned int type. | 2139 // where t is a signed or unsigned int type. |
2140 func makeInt(f flag, bits uint64, t Type) Value { | 2140 func makeInt(f flag, bits uint64, t Type) Value { |
2141 typ := t.common() | 2141 typ := t.common() |
2142 if typ.size > ptrSize { | 2142 if typ.size > ptrSize { |
2143 // Assume ptrSize >= 4, so this must be uint64. | 2143 // Assume ptrSize >= 4, so this must be uint64. |
2144 » » ptr := unsafe_New(t) | 2144 » » ptr := unsafe_New(typ) |
2145 *(*uint64)(unsafe.Pointer(ptr)) = bits | 2145 *(*uint64)(unsafe.Pointer(ptr)) = bits |
2146 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} | 2146 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} |
2147 } | 2147 } |
2148 var w iword | 2148 var w iword |
2149 switch typ.size { | 2149 switch typ.size { |
2150 case 1: | 2150 case 1: |
2151 *(*uint8)(unsafe.Pointer(&w)) = uint8(bits) | 2151 *(*uint8)(unsafe.Pointer(&w)) = uint8(bits) |
2152 case 2: | 2152 case 2: |
2153 *(*uint16)(unsafe.Pointer(&w)) = uint16(bits) | 2153 *(*uint16)(unsafe.Pointer(&w)) = uint16(bits) |
2154 case 4: | 2154 case 4: |
2155 *(*uint32)(unsafe.Pointer(&w)) = uint32(bits) | 2155 *(*uint32)(unsafe.Pointer(&w)) = uint32(bits) |
2156 case 8: | 2156 case 8: |
2157 *(*uint64)(unsafe.Pointer(&w)) = uint64(bits) | 2157 *(*uint64)(unsafe.Pointer(&w)) = uint64(bits) |
2158 } | 2158 } |
2159 return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift
} | 2159 return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift
} |
2160 } | 2160 } |
2161 | 2161 |
2162 // makeFloat returns a Value of type t equal to v (possibly truncated to float32
), | 2162 // makeFloat returns a Value of type t equal to v (possibly truncated to float32
), |
2163 // where t is a float32 or float64 type. | 2163 // where t is a float32 or float64 type. |
2164 func makeFloat(f flag, v float64, t Type) Value { | 2164 func makeFloat(f flag, v float64, t Type) Value { |
2165 typ := t.common() | 2165 typ := t.common() |
2166 if typ.size > ptrSize { | 2166 if typ.size > ptrSize { |
2167 // Assume ptrSize >= 4, so this must be float64. | 2167 // Assume ptrSize >= 4, so this must be float64. |
2168 » » ptr := unsafe_New(t) | 2168 » » ptr := unsafe_New(typ) |
2169 *(*float64)(unsafe.Pointer(ptr)) = v | 2169 *(*float64)(unsafe.Pointer(ptr)) = v |
2170 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} | 2170 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} |
2171 } | 2171 } |
2172 | 2172 |
2173 var w iword | 2173 var w iword |
2174 switch typ.size { | 2174 switch typ.size { |
2175 case 4: | 2175 case 4: |
2176 *(*float32)(unsafe.Pointer(&w)) = float32(v) | 2176 *(*float32)(unsafe.Pointer(&w)) = float32(v) |
2177 case 8: | 2177 case 8: |
2178 *(*float64)(unsafe.Pointer(&w)) = v | 2178 *(*float64)(unsafe.Pointer(&w)) = v |
2179 } | 2179 } |
2180 return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift
} | 2180 return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift
} |
2181 } | 2181 } |
2182 | 2182 |
2183 // makeComplex returns a Value of type t equal to v (possibly truncated to compl
ex64), | 2183 // makeComplex returns a Value of type t equal to v (possibly truncated to compl
ex64), |
2184 // where t is a complex64 or complex128 type. | 2184 // where t is a complex64 or complex128 type. |
2185 func makeComplex(f flag, v complex128, t Type) Value { | 2185 func makeComplex(f flag, v complex128, t Type) Value { |
2186 typ := t.common() | 2186 typ := t.common() |
2187 if typ.size > ptrSize { | 2187 if typ.size > ptrSize { |
2188 » » ptr := unsafe_New(t) | 2188 » » ptr := unsafe_New(typ) |
2189 switch typ.size { | 2189 switch typ.size { |
2190 case 8: | 2190 case 8: |
2191 *(*complex64)(unsafe.Pointer(ptr)) = complex64(v) | 2191 *(*complex64)(unsafe.Pointer(ptr)) = complex64(v) |
2192 case 16: | 2192 case 16: |
2193 *(*complex128)(unsafe.Pointer(ptr)) = v | 2193 *(*complex128)(unsafe.Pointer(ptr)) = v |
2194 } | 2194 } |
2195 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} | 2195 return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift} |
2196 } | 2196 } |
2197 | 2197 |
2198 // Assume ptrSize <= 8 so this must be complex64. | 2198 // Assume ptrSize <= 8 so this must be complex64. |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 return Value{t, val, v.flag&flagRO | f} | 2312 return Value{t, val, v.flag&flagRO | f} |
2313 } | 2313 } |
2314 | 2314 |
2315 // convertOp: concrete -> interface | 2315 // convertOp: concrete -> interface |
2316 func cvtT2I(v Value, typ Type) Value { | 2316 func cvtT2I(v Value, typ Type) Value { |
2317 target := new(interface{}) | 2317 target := new(interface{}) |
2318 x := valueInterface(v, false) | 2318 x := valueInterface(v, false) |
2319 if typ.NumMethod() == 0 { | 2319 if typ.NumMethod() == 0 { |
2320 *target = x | 2320 *target = x |
2321 } else { | 2321 } else { |
2322 » » ifaceE2I(typ.runtimeType(), x, unsafe.Pointer(target)) | 2322 » » ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target)) |
2323 } | 2323 } |
2324 return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagI
ndir | flag(Interface)<<flagKindShift} | 2324 return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagI
ndir | flag(Interface)<<flagKindShift} |
2325 } | 2325 } |
2326 | 2326 |
2327 // convertOp: interface -> interface | 2327 // convertOp: interface -> interface |
2328 func cvtI2I(v Value, typ Type) Value { | 2328 func cvtI2I(v Value, typ Type) Value { |
2329 if v.IsNil() { | 2329 if v.IsNil() { |
2330 ret := Zero(typ) | 2330 ret := Zero(typ) |
2331 ret.flag |= v.flag & flagRO | 2331 ret.flag |= v.flag & flagRO |
2332 return ret | 2332 return ret |
2333 } | 2333 } |
2334 return cvtT2I(v.Elem(), typ) | 2334 return cvtT2I(v.Elem(), typ) |
2335 } | 2335 } |
2336 | 2336 |
2337 // implemented in ../pkg/runtime | 2337 // implemented in ../pkg/runtime |
2338 func chancap(ch iword) int | 2338 func chancap(ch iword) int |
2339 func chanclose(ch iword) | 2339 func chanclose(ch iword) |
2340 func chanlen(ch iword) int | 2340 func chanlen(ch iword) int |
2341 func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received
bool) | 2341 func chanrecv(t *rtype, ch iword, nb bool) (val iword, selected, received bool) |
2342 func chansend(t *runtimeType, ch iword, val iword, nb bool) bool | 2342 func chansend(t *rtype, ch iword, val iword, nb bool) bool |
2343 | 2343 |
2344 func makechan(typ *runtimeType, size uint64) (ch iword) | 2344 func makechan(typ *rtype, size uint64) (ch iword) |
2345 func makemap(t *runtimeType) (m iword) | 2345 func makemap(t *rtype) (m iword) |
2346 func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool) | 2346 func mapaccess(t *rtype, m iword, key iword) (val iword, ok bool) |
2347 func mapassign(t *runtimeType, m iword, key, val iword, ok bool) | 2347 func mapassign(t *rtype, m iword, key, val iword, ok bool) |
2348 func mapiterinit(t *runtimeType, m iword) *byte | 2348 func mapiterinit(t *rtype, m iword) *byte |
2349 func mapiterkey(it *byte) (key iword, ok bool) | 2349 func mapiterkey(it *byte) (key iword, ok bool) |
2350 func mapiternext(it *byte) | 2350 func mapiternext(it *byte) |
2351 func maplen(m iword) int | 2351 func maplen(m iword) int |
2352 | 2352 |
2353 func call(fn, arg unsafe.Pointer, n uint32) | 2353 func call(fn, arg unsafe.Pointer, n uint32) |
2354 func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer) | 2354 func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer) |
2355 | 2355 |
2356 // Dummy annotation marking that the value x escapes, | 2356 // Dummy annotation marking that the value x escapes, |
2357 // for use in cases where the reflect code is so clever that | 2357 // for use in cases where the reflect code is so clever that |
2358 // the compiler cannot follow. | 2358 // the compiler cannot follow. |
2359 func escapes(x interface{}) { | 2359 func escapes(x interface{}) { |
2360 if dummy.b { | 2360 if dummy.b { |
2361 dummy.x = x | 2361 dummy.x = x |
2362 } | 2362 } |
2363 } | 2363 } |
2364 | 2364 |
2365 var dummy struct { | 2365 var dummy struct { |
2366 b bool | 2366 b bool |
2367 x interface{} | 2367 x interface{} |
2368 } | 2368 } |
LEFT | RIGHT |