mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: add register ABI support for makeFuncStub and methodValueCall
This change finishes off functionality register ABI for the reflect package. Specifically, it implements a call on a MakeFunc'd value by performing the reverse process that reflect.Value.Call does, using the same ABI steps. It implements a call on a method value created by reflect by translating between the method value's ABI to the method's ABI. Tests are added for both cases. For #40724. Change-Id: I302820b61fc0a8f94c5525a002bc02776aef41af Reviewed-on: https://go-review.googlesource.com/c/go/+/298670 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
6996bae5d1
commit
28c5fed557
18 changed files with 991 additions and 207 deletions
|
|
@ -5,6 +5,7 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"internal/abi"
|
||||
"internal/cpu"
|
||||
"runtime/internal/atomic"
|
||||
"runtime/internal/sys"
|
||||
|
|
@ -1312,23 +1313,42 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args
|
|||
}
|
||||
|
||||
// stack objects.
|
||||
p := funcdata(f, _FUNCDATA_StackObjects)
|
||||
if p != nil {
|
||||
n := *(*uintptr)(p)
|
||||
p = add(p, sys.PtrSize)
|
||||
*(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)}
|
||||
// Note: the noescape above is needed to keep
|
||||
// getStackMap from "leaking param content:
|
||||
// frame". That leak propagates up to getgcmask, then
|
||||
// GCMask, then verifyGCInfo, which converts the stack
|
||||
// gcinfo tests into heap gcinfo tests :(
|
||||
if GOARCH == "amd64" && unsafe.Sizeof(abi.RegArgs{}) > 0 && frame.argmap != nil {
|
||||
// argmap is set when the function is reflect.makeFuncStub or reflect.methodValueCall.
|
||||
// We don't actually use argmap in this case, but we need to fake the stack object
|
||||
// record for these frames which contain an internal/abi.RegArgs at a hard-coded offset
|
||||
// on amd64.
|
||||
objs = methodValueCallFrameObjs
|
||||
} else {
|
||||
p := funcdata(f, _FUNCDATA_StackObjects)
|
||||
if p != nil {
|
||||
n := *(*uintptr)(p)
|
||||
p = add(p, sys.PtrSize)
|
||||
*(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)}
|
||||
// Note: the noescape above is needed to keep
|
||||
// getStackMap from "leaking param content:
|
||||
// frame". That leak propagates up to getgcmask, then
|
||||
// GCMask, then verifyGCInfo, which converts the stack
|
||||
// gcinfo tests into heap gcinfo tests :(
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
abiRegArgsEface interface{} = abi.RegArgs{}
|
||||
abiRegArgsType *_type = efaceOf(&abiRegArgsEface)._type
|
||||
methodValueCallFrameObjs = []stackObjectRecord{
|
||||
{
|
||||
off: -int(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local.
|
||||
typ: abiRegArgsType,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// A stackObjectRecord is generated by the compiler for each stack object in a stack frame.
|
||||
// This record must match the generator code in cmd/compile/internal/gc/ssa.go:emitStackObjects.
|
||||
// This record must match the generator code in cmd/compile/internal/liveness/plive.go:emitStackObjects.
|
||||
type stackObjectRecord struct {
|
||||
// offset in frame
|
||||
// if negative, offset from varp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue