mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: keep pointer register results alive in callMethod
When callMethod calls the underlying method, after reflectcall it gets the result registers in "Ints" slots but not in "Ptrs" slots. If the GC runs at this point, it may lose track of those pointers and free the memory they point to. To make sure the GC sees the pointer results, copy "Ints" to "Ptrs", and keep them alive until we return to the caller. This fixes test/fixedbugs/issue27695.go with register ABI. Change-Id: I4092c91bcbd6954683740a12d91d689900446875 Reviewed-on: https://go-review.googlesource.com/c/go/+/309909 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
ad44dfb0fd
commit
ef36e4fd0e
2 changed files with 24 additions and 0 deletions
|
|
@ -366,6 +366,22 @@ func (a *abiDesc) dump() {
|
||||||
println("stackCallArgsSize", a.stackCallArgsSize)
|
println("stackCallArgsSize", a.stackCallArgsSize)
|
||||||
println("retOffset", a.retOffset)
|
println("retOffset", a.retOffset)
|
||||||
println("spill", a.spill)
|
println("spill", a.spill)
|
||||||
|
print("inRegPtrs:")
|
||||||
|
dumpPtrBitMap(a.inRegPtrs)
|
||||||
|
println()
|
||||||
|
print("outRegPtrs:")
|
||||||
|
dumpPtrBitMap(a.outRegPtrs)
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
func dumpPtrBitMap(b abi.IntArgRegBitmap) {
|
||||||
|
for i := 0; i < intArgRegs; i++ {
|
||||||
|
x := 0
|
||||||
|
if b.Get(i) {
|
||||||
|
x = 1
|
||||||
|
}
|
||||||
|
print(" ", x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAbiDesc(t *funcType, rcvr *rtype) abiDesc {
|
func newAbiDesc(t *funcType, rcvr *rtype) abiDesc {
|
||||||
|
|
|
||||||
|
|
@ -1023,6 +1023,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a
|
||||||
methodFrameSize = align(methodFrameSize, ptrSize)
|
methodFrameSize = align(methodFrameSize, ptrSize)
|
||||||
methodFrameSize += methodABI.spill
|
methodFrameSize += methodABI.spill
|
||||||
|
|
||||||
|
// Mark pointers in registers for the return path.
|
||||||
|
methodRegs.ReturnIsPtr = methodABI.outRegPtrs
|
||||||
|
|
||||||
// Call.
|
// Call.
|
||||||
// Call copies the arguments from scratch to the stack, calls fn,
|
// Call copies the arguments from scratch to the stack, calls fn,
|
||||||
// and then copies the results back into scratch.
|
// and then copies the results back into scratch.
|
||||||
|
|
@ -1059,6 +1062,11 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a
|
||||||
|
|
||||||
// See the comment in callReflect.
|
// See the comment in callReflect.
|
||||||
runtime.KeepAlive(ctxt)
|
runtime.KeepAlive(ctxt)
|
||||||
|
|
||||||
|
// Keep valueRegs alive because it may hold live pointer results.
|
||||||
|
// The caller (methodValueCall) has it as a stack object, which is only
|
||||||
|
// scanned when there is a reference to it.
|
||||||
|
runtime.KeepAlive(valueRegs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcName returns the name of f, for use in error messages.
|
// funcName returns the name of f, for use in error messages.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue