mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: consolidate stkframe and its methods into stkframe.go
The stkframe struct and its methods are strewn across different source files. Since they actually have a pretty coherent theme at this point, migrate it all into a new file, stkframe.go. There are no code changes in this CL. For #54466, albeit rather indirectly. Change-Id: Ibe53fc4b1106d131005e1c9d491be838a8f14211 Reviewed-on: https://go-review.googlesource.com/c/go/+/424516 Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Austin Clements <austin@google.com> Auto-Submit: Austin Clements <austin@google.com>
This commit is contained in:
parent
b91e373729
commit
35026f3732
4 changed files with 288 additions and 276 deletions
|
|
@ -1247,142 +1247,6 @@ func freeStackSpans() {
|
|||
unlock(&stackLarge.lock)
|
||||
}
|
||||
|
||||
// getStackMap returns the locals and arguments live pointer maps, and
|
||||
// stack object list for frame.
|
||||
func (frame *stkframe) getStackMap(cache *pcvalueCache, debug bool) (locals, args bitvector, objs []stackObjectRecord) {
|
||||
targetpc := frame.continpc
|
||||
if targetpc == 0 {
|
||||
// Frame is dead. Return empty bitvectors.
|
||||
return
|
||||
}
|
||||
|
||||
f := frame.fn
|
||||
pcdata := int32(-1)
|
||||
if targetpc != f.entry() {
|
||||
// Back up to the CALL. If we're at the function entry
|
||||
// point, we want to use the entry map (-1), even if
|
||||
// the first instruction of the function changes the
|
||||
// stack map.
|
||||
targetpc--
|
||||
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
|
||||
}
|
||||
if pcdata == -1 {
|
||||
// We do not have a valid pcdata value but there might be a
|
||||
// stackmap for this function. It is likely that we are looking
|
||||
// at the function prologue, assume so and hope for the best.
|
||||
pcdata = 0
|
||||
}
|
||||
|
||||
// Local variables.
|
||||
size := frame.varp - frame.sp
|
||||
var minsize uintptr
|
||||
switch goarch.ArchFamily {
|
||||
case goarch.ARM64:
|
||||
minsize = sys.StackAlign
|
||||
default:
|
||||
minsize = sys.MinFrameSize
|
||||
}
|
||||
if size > minsize {
|
||||
stackid := pcdata
|
||||
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
|
||||
if stkmap == nil || stkmap.n <= 0 {
|
||||
print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
|
||||
throw("missing stackmap")
|
||||
}
|
||||
// If nbit == 0, there's no work to do.
|
||||
if stkmap.nbit > 0 {
|
||||
if stackid < 0 || stackid >= stkmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", stackid, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
|
||||
throw("bad symbol table")
|
||||
}
|
||||
locals = stackmapdata(stkmap, stackid)
|
||||
if stackDebug >= 3 && debug {
|
||||
print(" locals ", stackid, "/", stkmap.n, " ", locals.n, " words ", locals.bytedata, "\n")
|
||||
}
|
||||
} else if stackDebug >= 3 && debug {
|
||||
print(" no locals to adjust\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Arguments. First fetch frame size and special-case argument maps.
|
||||
var isReflect bool
|
||||
args, isReflect = frame.argMapInternal()
|
||||
if args.n > 0 && args.bytedata == nil {
|
||||
// Non-empty argument frame, but not a special map.
|
||||
// Fetch the argument map at pcdata.
|
||||
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
|
||||
if stackmap == nil || stackmap.n <= 0 {
|
||||
print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(args.n*goarch.PtrSize), "\n")
|
||||
throw("missing stackmap")
|
||||
}
|
||||
if pcdata < 0 || pcdata >= stackmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
|
||||
throw("bad symbol table")
|
||||
}
|
||||
if stackmap.nbit == 0 {
|
||||
args.n = 0
|
||||
} else {
|
||||
args = stackmapdata(stackmap, pcdata)
|
||||
}
|
||||
}
|
||||
|
||||
// stack objects.
|
||||
if (GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le" || GOARCH == "riscv64") &&
|
||||
unsafe.Sizeof(abi.RegArgs{}) > 0 && isReflect {
|
||||
// For reflect.makeFuncStub and reflect.methodValueCall,
|
||||
// we need to fake the stack object record.
|
||||
// These frames contain an internal/abi.RegArgs at a hard-coded offset.
|
||||
// This offset matches the assembly code on amd64 and arm64.
|
||||
objs = methodValueCallFrameObjs[:]
|
||||
} else {
|
||||
p := funcdata(f, _FUNCDATA_StackObjects)
|
||||
if p != nil {
|
||||
n := *(*uintptr)(p)
|
||||
p = add(p, goarch.PtrSize)
|
||||
r0 := (*stackObjectRecord)(noescape(p))
|
||||
objs = unsafe.Slice(r0, 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 methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit
|
||||
|
||||
func stkobjinit() {
|
||||
var abiRegArgsEface any = abi.RegArgs{}
|
||||
abiRegArgsType := efaceOf(&abiRegArgsEface)._type
|
||||
if abiRegArgsType.kind&kindGCProg != 0 {
|
||||
throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs")
|
||||
}
|
||||
// Set methodValueCallFrameObjs[0].gcdataoff so that
|
||||
// stackObjectRecord.gcdata() will work correctly with it.
|
||||
ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0]))
|
||||
var mod *moduledata
|
||||
for datap := &firstmoduledata; datap != nil; datap = datap.next {
|
||||
if datap.gofunc <= ptr && ptr < datap.end {
|
||||
mod = datap
|
||||
break
|
||||
}
|
||||
}
|
||||
if mod == nil {
|
||||
throw("methodValueCallFrameObjs is not in a module")
|
||||
}
|
||||
methodValueCallFrameObjs[0] = stackObjectRecord{
|
||||
off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local.
|
||||
size: int32(abiRegArgsType.size),
|
||||
_ptrdata: int32(abiRegArgsType.ptrdata),
|
||||
gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.gcdata)) - mod.rodata),
|
||||
}
|
||||
}
|
||||
|
||||
// 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/liveness/plive.go:emitStackObjects.
|
||||
type stackObjectRecord struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue