-
Notifications
You must be signed in to change notification settings - Fork 17.7k
/
value.go
3307 lines (3017 loc) · 98.6 KB
/
value.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package reflect
import (
"internal/abi"
"internal/goarch"
"internal/itoa"
"internal/unsafeheader"
"math"
"runtime"
"unsafe"
)
// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
// if any, are noted in the documentation for each method.
// Use the Kind method to find out the kind of value before
// calling kind-specific methods. Calling a method
// inappropriate to the kind of type causes a run time panic.
//
// The zero Value represents no value.
// Its IsValid method returns false, its Kind method returns Invalid,
// its String method returns "<invalid Value>", and all other methods panic.
// Most functions and methods never return an invalid value.
// If one does, its documentation states the conditions explicitly.
//
// A Value can be used concurrently by multiple goroutines provided that
// the underlying Go value can be used concurrently for the equivalent
// direct operations.
//
// To compare two Values, compare the results of the Interface method.
// Using == on two Values does not compare the underlying values
// they represent.
type Value struct {
// typ holds the type of the value represented by a Value.
typ *rtype
// Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true.
ptr unsafe.Pointer
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagStickyRO: obtained via unexported not embedded field, so read-only
// - flagEmbedRO: obtained via unexported embedded field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
// The next five bits give the Kind of the value.
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
// If ifaceIndir(typ), code can assume that flagIndir is set.
flag
// A method value represents a curried method invocation
// like r.Read for some receiver r. The typ+val+flag bits describe
// the receiver r, but the flag's Kind bits say Func (methods are
// functions), and the top bits of the flag give the method number
// in r's type's method table.
}
type flag uintptr
const (
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
flagStickyRO flag = 1 << 5
flagEmbedRO flag = 1 << 6
flagIndir flag = 1 << 7
flagAddr flag = 1 << 8
flagMethod flag = 1 << 9
flagMethodShift = 10
flagRO flag = flagStickyRO | flagEmbedRO
)
func (f flag) kind() Kind {
return Kind(f & flagKindMask)
}
func (f flag) ro() flag {
if f&flagRO != 0 {
return flagStickyRO
}
return 0
}
// pointer returns the underlying pointer represented by v.
// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
// if v.Kind() == Ptr, the base type must not be go:notinheap.
func (v Value) pointer() unsafe.Pointer {
if v.typ.size != goarch.PtrSize || !v.typ.pointers() {
panic("can't call pointer on a non-pointer Value")
}
if v.flag&flagIndir != 0 {
return *(*unsafe.Pointer)(v.ptr)
}
return v.ptr
}
// packEface converts v to the empty interface.
func packEface(v Value) interface{} {
t := v.typ
var i interface{}
e := (*emptyInterface)(unsafe.Pointer(&i))
// First, fill in the data portion of the interface.
switch {
case ifaceIndir(t):
if v.flag&flagIndir == 0 {
panic("bad indir")
}
// Value is indirect, and so is the interface we're making.
ptr := v.ptr
if v.flag&flagAddr != 0 {
// TODO: pass safe boolean from valueInterface so
// we don't need to copy if safe==true?
c := unsafe_New(t)
typedmemmove(t, c, ptr)
ptr = c
}
e.word = ptr
case v.flag&flagIndir != 0:
// Value is indirect, but interface is direct. We need
// to load the data at v.ptr into the interface data word.
e.word = *(*unsafe.Pointer)(v.ptr)
default:
// Value is direct, and so is the interface.
e.word = v.ptr
}
// Now, fill in the type portion. We're very careful here not
// to have any operation between the e.word and e.typ assignments
// that would let the garbage collector observe the partially-built
// interface value.
e.typ = t
return i
}
// unpackEface converts the empty interface i to a Value.
func unpackEface(i interface{}) Value {
e := (*emptyInterface)(unsafe.Pointer(&i))
// NOTE: don't read e.word until we know whether it is really a pointer or not.
t := e.typ
if t == nil {
return Value{}
}
f := flag(t.Kind())
if ifaceIndir(t) {
f |= flagIndir
}
return Value{t, e.word, f}
}
// A ValueError occurs when a Value method is invoked on
// a Value that does not support it. Such cases are documented
// in the description of each method.
type ValueError struct {
Method string
Kind Kind
}
func (e *ValueError) Error() string {
if e.Kind == 0 {
return "reflect: call of " + e.Method + " on zero Value"
}
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
}
// methodName returns the name of the calling method,
// assumed to be two stack frames above.
func methodName() string {
pc, _, _, _ := runtime.Caller(2)
f := runtime.FuncForPC(pc)
if f == nil {
return "unknown method"
}
return f.Name()
}
// methodNameSkip is like methodName, but skips another stack frame.
// This is a separate function so that reflect.flag.mustBe will be inlined.
func methodNameSkip() string {
pc, _, _, _ := runtime.Caller(3)
f := runtime.FuncForPC(pc)
if f == nil {
return "unknown method"
}
return f.Name()
}
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}
// nonEmptyInterface is the header for an interface value with methods.
type nonEmptyInterface struct {
// see ../runtime/iface.go:/Itab
itab *struct {
ityp *rtype // static interface type
typ *rtype // dynamic concrete type
hash uint32 // copy of typ.hash
_ [4]byte
fun [100000]unsafe.Pointer // method table
}
word unsafe.Pointer
}
// mustBe panics if f's kind is not expected.
// Making this a method on flag instead of on Value
// (and embedding flag in Value) means that we can write
// the very clear v.mustBe(Bool) and have it compile into
// v.flag.mustBe(Bool), which will only bother to copy the
// single important word for the receiver.
func (f flag) mustBe(expected Kind) {
// TODO(mvdan): use f.kind() again once mid-stack inlining gets better
if Kind(f&flagKindMask) != expected {
panic(&ValueError{methodName(), f.kind()})
}
}
// mustBeExported panics if f records that the value was obtained using
// an unexported field.
func (f flag) mustBeExported() {
if f == 0 || f&flagRO != 0 {
f.mustBeExportedSlow()
}
}
func (f flag) mustBeExportedSlow() {
if f == 0 {
panic(&ValueError{methodNameSkip(), Invalid})
}
if f&flagRO != 0 {
panic("reflect: " + methodNameSkip() + " using value obtained using unexported field")
}
}
// mustBeAssignable panics if f records that the value is not assignable,
// which is to say that either it was obtained using an unexported field
// or it is not addressable.
func (f flag) mustBeAssignable() {
if f&flagRO != 0 || f&flagAddr == 0 {
f.mustBeAssignableSlow()
}
}
func (f flag) mustBeAssignableSlow() {
if f == 0 {
panic(&ValueError{methodNameSkip(), Invalid})
}
// Assignable if addressable and not read-only.
if f&flagRO != 0 {
panic("reflect: " + methodNameSkip() + " using value obtained using unexported field")
}
if f&flagAddr == 0 {
panic("reflect: " + methodNameSkip() + " using unaddressable value")
}
}
// Addr returns a pointer value representing the address of v.
// It panics if CanAddr() returns false.
// Addr is typically used to obtain a pointer to a struct field
// or slice element in order to call a method that requires a
// pointer receiver.
func (v Value) Addr() Value {
if v.flag&flagAddr == 0 {
panic("reflect.Value.Addr of unaddressable value")
}
// Preserve flagRO instead of using v.flag.ro() so that
// v.Addr().Elem() is equivalent to v (#32772)
fl := v.flag & flagRO
return Value{v.typ.ptrTo(), v.ptr, fl | flag(Ptr)}
}
// Bool returns v's underlying value.
// It panics if v's kind is not Bool.
func (v Value) Bool() bool {
v.mustBe(Bool)
return *(*bool)(v.ptr)
}
// Bytes returns v's underlying value.
// It panics if v's underlying value is not a slice of bytes.
func (v Value) Bytes() []byte {
v.mustBe(Slice)
if v.typ.Elem().Kind() != Uint8 {
panic("reflect.Value.Bytes of non-byte slice")
}
// Slice is always bigger than a word; assume flagIndir.
return *(*[]byte)(v.ptr)
}
// runes returns v's underlying value.
// It panics if v's underlying value is not a slice of runes (int32s).
func (v Value) runes() []rune {
v.mustBe(Slice)
if v.typ.Elem().Kind() != Int32 {
panic("reflect.Value.Bytes of non-rune slice")
}
// Slice is always bigger than a word; assume flagIndir.
return *(*[]rune)(v.ptr)
}
// CanAddr reports whether the value's address can be obtained with Addr.
// Such values are called addressable. A value is addressable if it is
// an element of a slice, an element of an addressable array,
// a field of an addressable struct, or the result of dereferencing a pointer.
// If CanAddr returns false, calling Addr will panic.
func (v Value) CanAddr() bool {
return v.flag&flagAddr != 0
}
// CanSet reports whether the value of v can be changed.
// A Value can be changed only if it is addressable and was not
// obtained by the use of unexported struct fields.
// If CanSet returns false, calling Set or any type-specific
// setter (e.g., SetBool, SetInt) will panic.
func (v Value) CanSet() bool {
return v.flag&(flagAddr|flagRO) == flagAddr
}
// Call calls the function v with the input arguments in.
// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
// Call panics if v's Kind is not Func.
// It returns the output results as Values.
// As in Go, each input argument must be assignable to the
// type of the function's corresponding input parameter.
// If v is a variadic function, Call creates the variadic slice parameter
// itself, copying in the corresponding values.
func (v Value) Call(in []Value) []Value {
v.mustBe(Func)
v.mustBeExported()
return v.call("Call", in)
}
// CallSlice calls the variadic function v with the input arguments in,
// assigning the slice in[len(in)-1] to v's final variadic argument.
// For example, if len(in) == 3, v.CallSlice(in) represents the Go call v(in[0], in[1], in[2]...).
// CallSlice panics if v's Kind is not Func or if v is not variadic.
// It returns the output results as Values.
// As in Go, each input argument must be assignable to the
// type of the function's corresponding input parameter.
func (v Value) CallSlice(in []Value) []Value {
v.mustBe(Func)
v.mustBeExported()
return v.call("CallSlice", in)
}
var callGC bool // for testing; see TestCallMethodJump
const debugReflectCall = false
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
t := (*funcType)(unsafe.Pointer(v.typ))
var (
fn unsafe.Pointer
rcvr Value
rcvrtype *rtype
)
if v.flag&flagMethod != 0 {
rcvr = v
rcvrtype, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
} else if v.flag&flagIndir != 0 {
fn = *(*unsafe.Pointer)(v.ptr)
} else {
fn = v.ptr
}
if fn == nil {
panic("reflect.Value.Call: call of nil function")
}
isSlice := op == "CallSlice"
n := t.NumIn()
isVariadic := t.IsVariadic()
if isSlice {
if !isVariadic {
panic("reflect: CallSlice of non-variadic function")
}
if len(in) < n {
panic("reflect: CallSlice with too few input arguments")
}
if len(in) > n {
panic("reflect: CallSlice with too many input arguments")
}
} else {
if isVariadic {
n--
}
if len(in) < n {
panic("reflect: Call with too few input arguments")
}
if !isVariadic && len(in) > n {
panic("reflect: Call with too many input arguments")
}
}
for _, x := range in {
if x.Kind() == Invalid {
panic("reflect: " + op + " using zero Value argument")
}
}
for i := 0; i < n; i++ {
if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
}
}
if !isSlice && isVariadic {
// prepare slice for remaining values
m := len(in) - n
slice := MakeSlice(t.In(n), m, m)
elem := t.In(n).Elem()
for i := 0; i < m; i++ {
x := in[n+i]
if xt := x.Type(); !xt.AssignableTo(elem) {
panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
}
slice.Index(i).Set(x)
}
origIn := in
in = make([]Value, n+1)
copy(in[:n], origIn)
in[n] = slice
}
nin := len(in)
if nin != t.NumIn() {
panic("reflect.Value.Call: wrong argument count")
}
nout := t.NumOut()
// Register argument space.
var regArgs abi.RegArgs
// Compute frame type.
frametype, framePool, abi := funcLayout(t, rcvrtype)
// Allocate a chunk of memory for frame if needed.
var stackArgs unsafe.Pointer
if frametype.size != 0 {
if nout == 0 {
stackArgs = framePool.Get().(unsafe.Pointer)
} else {
// Can't use pool if the function has return values.
// We will leak pointer to args in ret, so its lifetime is not scoped.
stackArgs = unsafe_New(frametype)
}
}
frameSize := frametype.size
if debugReflectCall {
println("reflect.call", t.String())
abi.dump()
}
// Copy inputs into args.
// Handle receiver.
inStart := 0
if rcvrtype != nil {
// Guaranteed to only be one word in size,
// so it will only take up exactly 1 abiStep (either
// in a register or on the stack).
switch st := abi.call.steps[0]; st.kind {
case abiStepStack:
storeRcvr(rcvr, stackArgs)
case abiStepIntReg, abiStepPointer:
// Even pointers can go into the uintptr slot because
// they'll be kept alive by the Values referenced by
// this frame. Reflection forces these to be heap-allocated,
// so we don't need to worry about stack copying.
storeRcvr(rcvr, unsafe.Pointer(®Args.Ints[st.ireg]))
case abiStepFloatReg:
storeRcvr(rcvr, unsafe.Pointer(®Args.Floats[st.freg]))
default:
panic("unknown ABI parameter kind")
}
inStart = 1
}
// Handle arguments.
for i, v := range in {
v.mustBeExported()
targ := t.In(i).(*rtype)
// TODO(mknyszek): Figure out if it's possible to get some
// scratch space for this assignment check. Previously, it
// was possible to use space in the argument frame.
v = v.assignTo("reflect.Value.Call", targ, nil)
stepsLoop:
for _, st := range abi.call.stepsForValue(i + inStart) {
switch st.kind {
case abiStepStack:
// Copy values to the "stack."
addr := add(stackArgs, st.stkOff, "precomputed stack arg offset")
if v.flag&flagIndir != 0 {
typedmemmove(targ, addr, v.ptr)
} else {
*(*unsafe.Pointer)(addr) = v.ptr
}
// There's only one step for a stack-allocated value.
break stepsLoop
case abiStepIntReg, abiStepPointer:
// Copy values to "integer registers."
if v.flag&flagIndir != 0 {
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(regArgs.IntRegArgAddr(st.ireg, st.size), offset, st.size)
} else {
if st.kind == abiStepPointer {
// Duplicate this pointer in the pointer area of the
// register space. Otherwise, there's the potential for
// this to be the last reference to v.ptr.
regArgs.Ptrs[st.ireg] = v.ptr
}
regArgs.Ints[st.ireg] = uintptr(v.ptr)
}
case abiStepFloatReg:
// Copy values to "float registers."
if v.flag&flagIndir == 0 {
panic("attempted to copy pointer to FP register")
}
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(regArgs.FloatRegArgAddr(st.freg, st.size), offset, st.size)
default:
panic("unknown ABI part kind")
}
}
}
// TODO(mknyszek): Remove this when we no longer have
// caller reserved spill space.
frameSize = align(frameSize, goarch.PtrSize)
frameSize += abi.spill
// Mark pointers in registers for the return path.
regArgs.ReturnIsPtr = abi.outRegPtrs
// Call.
call(frametype, fn, stackArgs, uint32(frametype.size), uint32(abi.retOffset), uint32(frameSize), ®Args)
// For testing; see TestCallMethodJump.
if callGC {
runtime.GC()
}
var ret []Value
if nout == 0 {
if stackArgs != nil {
typedmemclr(frametype, stackArgs)
framePool.Put(stackArgs)
}
} else {
if stackArgs != nil {
// Zero the now unused input area of args,
// because the Values returned by this function contain pointers to the args object,
// and will thus keep the args object alive indefinitely.
typedmemclrpartial(frametype, stackArgs, 0, abi.retOffset)
}
// Wrap Values around return values in args.
ret = make([]Value, nout)
for i := 0; i < nout; i++ {
tv := t.Out(i)
if tv.Size() == 0 {
// For zero-sized return value, args+off may point to the next object.
// In this case, return the zero value instead.
ret[i] = Zero(tv)
continue
}
steps := abi.ret.stepsForValue(i)
if st := steps[0]; st.kind == abiStepStack {
// This value is on the stack. If part of a value is stack
// allocated, the entire value is according to the ABI. So
// just make an indirection into the allocated frame.
fl := flagIndir | flag(tv.Kind())
ret[i] = Value{tv.common(), add(stackArgs, st.stkOff, "tv.Size() != 0"), fl}
// Note: this does introduce false sharing between results -
// if any result is live, they are all live.
// (And the space for the args is live as well, but as we've
// cleared that space it isn't as big a deal.)
continue
}
// Handle pointers passed in registers.
if !ifaceIndir(tv.common()) {
// Pointer-valued data gets put directly
// into v.ptr.
if steps[0].kind != abiStepPointer {
print("kind=", steps[0].kind, ", type=", tv.String(), "\n")
panic("mismatch between ABI description and types")
}
ret[i] = Value{tv.common(), regArgs.Ptrs[steps[0].ireg], flag(tv.Kind())}
continue
}
// All that's left is values passed in registers that we need to
// create space for and copy values back into.
//
// TODO(mknyszek): We make a new allocation for each register-allocated
// value, but previously we could always point into the heap-allocated
// stack frame. This is a regression that could be fixed by adding
// additional space to the allocated stack frame and storing the
// register-allocated return values into the allocated stack frame and
// referring there in the resulting Value.
s := unsafe_New(tv.common())
for _, st := range steps {
switch st.kind {
case abiStepIntReg:
offset := add(s, st.offset, "precomputed value offset")
memmove(offset, regArgs.IntRegArgAddr(st.ireg, st.size), st.size)
case abiStepPointer:
s := add(s, st.offset, "precomputed value offset")
*((*unsafe.Pointer)(s)) = regArgs.Ptrs[st.ireg]
case abiStepFloatReg:
offset := add(s, st.offset, "precomputed value offset")
memmove(offset, regArgs.FloatRegArgAddr(st.freg, st.size), st.size)
case abiStepStack:
panic("register-based return value has stack component")
default:
panic("unknown ABI part kind")
}
}
ret[i] = Value{tv.common(), s, flagIndir | flag(tv.Kind())}
}
}
return ret
}
// callReflect is the call implementation used by a function
// returned by MakeFunc. In many ways it is the opposite of the
// method Value.call above. The method above converts a call using Values
// into a call of a function with a concrete argument frame, while
// callReflect converts a call of a function with a concrete argument
// frame into a call using Values.
// It is in this file so that it can be next to the call method above.
// The remainder of the MakeFunc implementation is in makefunc.go.
//
// NOTE: This function must be marked as a "wrapper" in the generated code,
// so that the linker can make it work correctly for panic and recover.
// The gc compilers know to do that for the name "reflect.callReflect".
//
// ctxt is the "closure" generated by MakeFunc.
// frame is a pointer to the arguments to that closure on the stack.
// retValid points to a boolean which should be set when the results
// section of frame is set.
//
// regs contains the argument values passed in registers and will contain
// the values returned from ctxt.fn in registers.
func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs *abi.RegArgs) {
if callGC {
// Call GC upon entry during testing.
// Getting our stack scanned here is the biggest hazard, because
// our caller (makeFuncStub) could have failed to place the last
// pointer to a value in regs' pointer space, in which case it
// won't be visible to the GC.
runtime.GC()
}
ftyp := ctxt.ftyp
f := ctxt.fn
_, _, abi := funcLayout(ftyp, nil)
// Copy arguments into Values.
ptr := frame
in := make([]Value, 0, int(ftyp.inCount))
for i, typ := range ftyp.in() {
if typ.Size() == 0 {
in = append(in, Zero(typ))
continue
}
v := Value{typ, nil, flag(typ.Kind())}
steps := abi.call.stepsForValue(i)
if st := steps[0]; st.kind == abiStepStack {
if ifaceIndir(typ) {
// value cannot be inlined in interface data.
// Must make a copy, because f might keep a reference to it,
// and we cannot let f keep a reference to the stack frame
// after this function returns, not even a read-only reference.
v.ptr = unsafe_New(typ)
if typ.size > 0 {
typedmemmove(typ, v.ptr, add(ptr, st.stkOff, "typ.size > 0"))
}
v.flag |= flagIndir
} else {
v.ptr = *(*unsafe.Pointer)(add(ptr, st.stkOff, "1-ptr"))
}
} else {
if ifaceIndir(typ) {
// All that's left is values passed in registers that we need to
// create space for the values.
v.flag |= flagIndir
v.ptr = unsafe_New(typ)
for _, st := range steps {
switch st.kind {
case abiStepIntReg:
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(offset, regs.IntRegArgAddr(st.ireg, st.size), st.size)
case abiStepPointer:
s := add(v.ptr, st.offset, "precomputed value offset")
*((*unsafe.Pointer)(s)) = regs.Ptrs[st.ireg]
case abiStepFloatReg:
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(offset, regs.FloatRegArgAddr(st.freg, st.size), st.size)
case abiStepStack:
panic("register-based return value has stack component")
default:
panic("unknown ABI part kind")
}
}
} else {
// Pointer-valued data gets put directly
// into v.ptr.
if steps[0].kind != abiStepPointer {
print("kind=", steps[0].kind, ", type=", typ.String(), "\n")
panic("mismatch between ABI description and types")
}
v.ptr = regs.Ptrs[steps[0].ireg]
}
}
in = append(in, v)
}
// Call underlying function.
out := f(in)
numOut := ftyp.NumOut()
if len(out) != numOut {
panic("reflect: wrong return count from function created by MakeFunc")
}
// Copy results back into argument frame and register space.
if numOut > 0 {
for i, typ := range ftyp.out() {
v := out[i]
if v.typ == nil {
panic("reflect: function created by MakeFunc using " + funcName(f) +
" returned zero Value")
}
if v.flag&flagRO != 0 {
panic("reflect: function created by MakeFunc using " + funcName(f) +
" returned value obtained from unexported field")
}
if typ.size == 0 {
continue
}
// Convert v to type typ if v is assignable to a variable
// of type t in the language spec.
// See issue 28761.
//
//
// TODO(mknyszek): In the switch to the register ABI we lost
// the scratch space here for the register cases (and
// temporarily for all the cases).
//
// If/when this happens, take note of the following:
//
// We must clear the destination before calling assignTo,
// in case assignTo writes (with memory barriers) to the
// target location used as scratch space. See issue 39541.
v = v.assignTo("reflect.MakeFunc", typ, nil)
stepsLoop:
for _, st := range abi.ret.stepsForValue(i) {
switch st.kind {
case abiStepStack:
// Copy values to the "stack."
addr := add(ptr, st.stkOff, "precomputed stack arg offset")
// Do not use write barriers. The stack space used
// for this call is not adequately zeroed, and we
// are careful to keep the arguments alive until we
// return to makeFuncStub's caller.
if v.flag&flagIndir != 0 {
memmove(addr, v.ptr, st.size)
} else {
// This case must be a pointer type.
*(*uintptr)(addr) = uintptr(v.ptr)
}
// There's only one step for a stack-allocated value.
break stepsLoop
case abiStepIntReg, abiStepPointer:
// Copy values to "integer registers."
if v.flag&flagIndir != 0 {
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(regs.IntRegArgAddr(st.ireg, st.size), offset, st.size)
} else {
// Only populate the Ints space on the return path.
// This is safe because out is kept alive until the
// end of this function, and the return path through
// makeFuncStub has no preemption, so these pointers
// are always visible to the GC.
regs.Ints[st.ireg] = uintptr(v.ptr)
}
case abiStepFloatReg:
// Copy values to "float registers."
if v.flag&flagIndir == 0 {
panic("attempted to copy pointer to FP register")
}
offset := add(v.ptr, st.offset, "precomputed value offset")
memmove(regs.FloatRegArgAddr(st.freg, st.size), offset, st.size)
default:
panic("unknown ABI part kind")
}
}
}
}
// Announce that the return values are valid.
// After this point the runtime can depend on the return values being valid.
*retValid = true
// We have to make sure that the out slice lives at least until
// the runtime knows the return values are valid. Otherwise, the
// return values might not be scanned by anyone during a GC.
// (out would be dead, and the return slots not yet alive.)
runtime.KeepAlive(out)
// runtime.getArgInfo expects to be able to find ctxt on the
// stack when it finds our caller, makeFuncStub. Make sure it
// doesn't get garbage collected.
runtime.KeepAlive(ctxt)
}
// methodReceiver returns information about the receiver
// described by v. The Value v may or may not have the
// flagMethod bit set, so the kind cached in v.flag should
// not be used.
// The return value rcvrtype gives the method's actual receiver type.
// The return value t gives the method type signature (without the receiver).
// The return value fn is a pointer to the method code.
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *funcType, fn unsafe.Pointer) {
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
if !tt.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
iface := (*nonEmptyInterface)(v.ptr)
if iface.itab == nil {
panic("reflect: " + op + " of method on nil interface value")
}
rcvrtype = iface.itab.typ
fn = unsafe.Pointer(&iface.itab.fun[i])
t = (*funcType)(unsafe.Pointer(tt.typeOff(m.typ)))
} else {
rcvrtype = v.typ
ms := v.typ.exportedMethods()
if uint(i) >= uint(len(ms)) {
panic("reflect: internal error: invalid method index")
}
m := ms[i]
if !v.typ.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
ifn := v.typ.textOff(m.ifn)
fn = unsafe.Pointer(&ifn)
t = (*funcType)(unsafe.Pointer(v.typ.typeOff(m.mtyp)))
}
return
}
// v is a method receiver. Store at p the word which is used to
// encode that receiver at the start of the argument list.
// Reflect uses the "interface" calling convention for
// methods, which always uses one word to record the receiver.
func storeRcvr(v Value, p unsafe.Pointer) {
t := v.typ
if t.Kind() == Interface {
// the interface data word becomes the receiver word
iface := (*nonEmptyInterface)(v.ptr)
*(*unsafe.Pointer)(p) = iface.word
} else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
} else {
*(*unsafe.Pointer)(p) = v.ptr
}
}
// align returns the result of rounding x up to a multiple of n.
// n must be a power of two.
func align(x, n uintptr) uintptr {
return (x + n - 1) &^ (n - 1)
}
// callMethod is the call implementation used by a function returned
// by makeMethodValue (used by v.Method(i).Interface()).
// It is a streamlined version of the usual reflect call: the caller has
// already laid out the argument frame for us, so we don't have
// to deal with individual Values for each argument.
// It is in this file so that it can be next to the two similar functions above.
// The remainder of the makeMethodValue implementation is in makefunc.go.
//
// NOTE: This function must be marked as a "wrapper" in the generated code,
// so that the linker can make it work correctly for panic and recover.
// The gc compilers know to do that for the name "reflect.callMethod".
//
// ctxt is the "closure" generated by makeVethodValue.
// frame is a pointer to the arguments to that closure on the stack.
// retValid points to a boolean which should be set when the results
// section of frame is set.
//
// regs contains the argument values passed in registers and will contain
// the values returned from ctxt.fn in registers.
func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *abi.RegArgs) {
rcvr := ctxt.rcvr
rcvrType, valueFuncType, methodFn := methodReceiver("call", rcvr, ctxt.method)
// There are two ABIs at play here.
//
// methodValueCall was invoked with the ABI assuming there was no
// receiver ("value ABI") and that's what frame and regs are holding.
//
// Meanwhile, we need to actually call the method with a receiver, which
// has its own ABI ("method ABI"). Everything that follows is a translation
// between the two.
_, _, valueABI := funcLayout(valueFuncType, nil)
valueFrame, valueRegs := frame, regs
methodFrameType, methodFramePool, methodABI := funcLayout(valueFuncType, rcvrType)
// Make a new frame that is one word bigger so we can store the receiver.
// This space is used for both arguments and return values.
methodFrame := methodFramePool.Get().(unsafe.Pointer)
var methodRegs abi.RegArgs
// Deal with the receiver. It's guaranteed to only be one word in size.
if st := methodABI.call.steps[0]; st.kind == abiStepStack {
// Only copy the receiver to the stack if the ABI says so.
// Otherwise, it'll be in a register already.
storeRcvr(rcvr, methodFrame)
} else {
// Put the receiver in a register.
storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ints))
}
// Translate the rest of the arguments.
for i, t := range valueFuncType.in() {
valueSteps := valueABI.call.stepsForValue(i)
methodSteps := methodABI.call.stepsForValue(i + 1)
// Zero-sized types are trivial: nothing to do.
if len(valueSteps) == 0 {
if len(methodSteps) != 0 {
panic("method ABI and value ABI do not align")
}
continue
}
// There are four cases to handle in translating each
// argument:
// 1. Stack -> stack translation.
// 2. Stack -> registers translation.
// 3. Registers -> stack translation.
// 4. Registers -> registers translation.
// If the value ABI passes the value on the stack,
// then the method ABI does too, because it has strictly
// fewer arguments. Simply copy between the two.
if vStep := valueSteps[0]; vStep.kind == abiStepStack {
mStep := methodSteps[0]
// Handle stack -> stack translation.
if mStep.kind == abiStepStack {
if vStep.size != mStep.size {
panic("method ABI and value ABI do not align")
}
typedmemmove(t,
add(methodFrame, mStep.stkOff, "precomputed stack offset"),
add(valueFrame, vStep.stkOff, "precomputed stack offset"))
continue
}
// Handle stack -> register translation.
for _, mStep := range methodSteps {
from := add(valueFrame, vStep.stkOff+mStep.offset, "precomputed stack offset")
switch mStep.kind {
case abiStepPointer:
// Do the pointer copy directly so we get a write barrier.
methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from)
fallthrough // We need to make sure this ends up in Ints, too.
case abiStepIntReg:
memmove(methodRegs.IntRegArgAddr(mStep.ireg, mStep.size), from, mStep.size)
case abiStepFloatReg:
memmove(methodRegs.FloatRegArgAddr(mStep.freg, mStep.size), from, mStep.size)
default:
panic("unexpected method step")
}
}
continue
}
// Handle register -> stack translation.
if mStep := methodSteps[0]; mStep.kind == abiStepStack {
for _, vStep := range valueSteps {
to := add(methodFrame, mStep.stkOff+vStep.offset, "precomputed stack offset")
switch vStep.kind {
case abiStepPointer:
// Do the pointer copy directly so we get a write barrier.