aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2021-11-11 19:58:23 -0500
committerCherry Mui <cherryyz@google.com>2021-11-12 14:56:58 +0000
commit23adc139bf1c0c099dd075da076f5a1f3ac700d4 (patch)
tree83e02a244a5ad49eb1461ec1a5d9a6a9806a54f3 /src/reflect/value.go
parente9f0381a807d1797e0b5969a29f4a3666a73c9e3 (diff)
downloadgo-23adc139bf1c0c099dd075da076f5a1f3ac700d4.tar.gz
go-23adc139bf1c0c099dd075da076f5a1f3ac700d4.zip
reflect: keep pointer in aggregate-typed args live in Call
When register ABI is used, reflect.Value.Call prepares the call arguments in a memory representation of the argument registers. It has special handling to keep the pointers in arguments live. Currently, this handles pointer-typed arguments. But when an argument is an aggregate-type that contains pointers and passed in registers, it currently doesn't keep the pointers live. Do so in this CL. May fix #49363. Change-Id: Ic6a0c5fdf9375ef02f7c03fbe9345e2e98c9353d Reviewed-on: https://go-review.googlesource.com/c/go/+/363358 Trust: Cherry Mui <cherryyz@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index ecf9dd7bc8..02354f2736 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -352,7 +352,7 @@ func (v Value) CallSlice(in []Value) []Value {
return v.call("CallSlice", in)
}
-var callGC bool // for testing; see TestCallMethodJump
+var callGC bool // for testing; see TestCallMethodJump and TestCallArgLive
const debugReflectCall = false
@@ -509,12 +509,16 @@ func (v Value) call(op string, in []Value) []Value {
// Copy values to "integer registers."
if v.flag&flagIndir != 0 {
offset := add(v.ptr, st.offset, "precomputed value offset")
- intToReg(&regArgs, st.ireg, st.size, offset)
- } 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] = *(*unsafe.Pointer)(offset)
+ }
+ intToReg(&regArgs, st.ireg, st.size, offset)
+ } else {
+ if st.kind == abiStepPointer {
+ // See the comment in abiStepPointer case above.
regArgs.Ptrs[st.ireg] = v.ptr
}
regArgs.Ints[st.ireg] = uintptr(v.ptr)
@@ -539,6 +543,15 @@ func (v Value) call(op string, in []Value) []Value {
// Mark pointers in registers for the return path.
regArgs.ReturnIsPtr = abi.outRegPtrs
+ if debugReflectCall {
+ regArgs.Dump()
+ }
+
+ // For testing; see TestCallArgLive.
+ if callGC {
+ runtime.GC()
+ }
+
// Call.
call(frametype, fn, stackArgs, uint32(frametype.size), uint32(abi.retOffset), uint32(frameSize), &regArgs)