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/all_test.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/all_test.go')
-rw-r--r-- | src/reflect/all_test.go | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index acc09962a0..8c51d8ec26 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -6478,6 +6478,29 @@ func TestCallMethodJump(t *testing.T) { *CallGC = false } +func TestCallArgLive(t *testing.T) { + type T struct{ X, Y *string } // pointerful aggregate + + F := func(t T) { *t.X = "ok" } + + // In reflect.Value.Call, trigger a garbage collection in reflect.call + // between marshaling argument and the actual call. + *CallGC = true + + x := new(string) + runtime.SetFinalizer(x, func(p *string) { + if *p != "ok" { + t.Errorf("x dead prematurely") + } + }) + v := T{x, nil} + + ValueOf(F).Call([]Value{ValueOf(v)}) + + // Stop garbage collecting during reflect.call. + *CallGC = false +} + func TestMakeFuncStackCopy(t *testing.T) { target := func(in []Value) []Value { runtime.GC() |