]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: store receiver in pointer slot for reflect call
authorCherry Mui <cherryyz@google.com>
Fri, 20 May 2022 23:35:44 +0000 (19:35 -0400)
committerCherry Mui <cherryyz@google.com>
Mon, 23 May 2022 18:40:59 +0000 (18:40 +0000)
The code comment says that the receiver doesn't need to go into
the pointer slot as it will be kept alive in this frame. But it
doesn't. There is no direct reference of rcvr or v (the receiver)
after storing the arguments. Also, it is clearer to explicitly
keep it alive.

Fixes #52800.

Change-Id: Ie3fa8e83f6ecc69d62e8bfab767314d5181f5dc0
Reviewed-on: https://go-review.googlesource.com/c/go/+/407508
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/reflect/value.go

index 0fc19ef101f324db910a8bc826d9e737704cd67c..400f24f9bac92a357a4fac1299e4faf1e92f7fbb 100644 (file)
@@ -499,11 +499,10 @@ func (v Value) call(op string, in []Value) []Value {
                switch st := abid.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.
+               case abiStepPointer:
+                       storeRcvr(rcvr, unsafe.Pointer(&regArgs.Ptrs[st.ireg]))
+                       fallthrough
+               case abiStepIntReg:
                        storeRcvr(rcvr, unsafe.Pointer(&regArgs.Ints[st.ireg]))
                case abiStepFloatReg:
                        storeRcvr(rcvr, unsafe.Pointer(&regArgs.Floats[st.freg]))
@@ -972,13 +971,21 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a
        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 {
+       switch st := methodABI.call.steps[0]; st.kind {
+       case 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 {
+       case abiStepPointer:
                // Put the receiver in a register.
-               storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ints))
+               storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ptrs[st.ireg]))
+               fallthrough
+       case abiStepIntReg:
+               storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ints[st.ireg]))
+       case abiStepFloatReg:
+               storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Floats[st.freg]))
+       default:
+               panic("unknown ABI parameter kind")
        }
 
        // Translate the rest of the arguments.