diff options
author | Cherry Mui <cherryyz@google.com> | 2021-11-11 19:58:23 -0500 |
---|---|---|
committer | Cherry Mui <cherryyz@google.com> | 2021-11-12 14:56:58 +0000 |
commit | 23adc139bf1c0c099dd075da076f5a1f3ac700d4 (patch) | |
tree | 83e02a244a5ad49eb1461ec1a5d9a6a9806a54f3 /src/reflect/value.go | |
parent | e9f0381a807d1797e0b5969a29f4a3666a73c9e3 (diff) | |
download | go-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.go | 19 |
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(®Args, 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(®Args, 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), ®Args) |