Skip to content

Commit 35026f3

Browse files
aclementsgopherbot
authored andcommitted
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 <[email protected]> Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Austin Clements <[email protected]> Auto-Submit: Austin Clements <[email protected]>
1 parent b91e373 commit 35026f3

File tree

4 files changed

+288
-276
lines changed

4 files changed

+288
-276
lines changed

src/runtime/runtime2.go

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -985,55 +985,6 @@ type _panic struct {
985985
goexit bool
986986
}
987987

988-
// A stkframe holds information about a single physical stack frame.
989-
type stkframe struct {
990-
// fn is the function being run in this frame. If there is
991-
// inlining, this is the outermost function.
992-
fn funcInfo
993-
994-
// pc is the program counter within fn.
995-
//
996-
// The meaning of this is subtle:
997-
//
998-
// - Typically, this frame performed a regular function call
999-
// and this is the return PC (just after the CALL
1000-
// instruction). In this case, pc-1 reflects the CALL
1001-
// instruction itself and is the correct source of symbolic
1002-
// information.
1003-
//
1004-
// - If this frame "called" sigpanic, then pc is the
1005-
// instruction that panicked, and pc is the correct address
1006-
// to use for symbolic information.
1007-
//
1008-
// - If this is the innermost frame, then PC is where
1009-
// execution will continue, but it may not be the
1010-
// instruction following a CALL. This may be from
1011-
// cooperative preemption, in which case this is the
1012-
// instruction after the call to morestack. Or this may be
1013-
// from a signal or an un-started goroutine, in which case
1014-
// PC could be any instruction, including the first
1015-
// instruction in a function. Conventionally, we use pc-1
1016-
// for symbolic information, unless pc == fn.entry(), in
1017-
// which case we use pc.
1018-
pc uintptr
1019-
1020-
// continpc is the PC where execution will continue in fn, or
1021-
// 0 if execution will not continue in this frame.
1022-
//
1023-
// This is usually the same as pc, unless this frame "called"
1024-
// sigpanic, in which case it's either the address of
1025-
// deferreturn or 0 if this frame will never execute again.
1026-
//
1027-
// This is the PC to use to look up GC liveness for this frame.
1028-
continpc uintptr
1029-
1030-
lr uintptr // program counter at caller aka link register
1031-
sp uintptr // stack pointer at pc
1032-
fp uintptr // stack pointer at caller aka frame pointer
1033-
varp uintptr // top of local variables
1034-
argp uintptr // pointer to function arguments
1035-
}
1036-
1037988
// ancestorInfo records details of where a goroutine was started.
1038989
type ancestorInfo struct {
1039990
pcs []uintptr // pcs from the stack of this goroutine

src/runtime/stack.go

Lines changed: 0 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,142 +1247,6 @@ func freeStackSpans() {
12471247
unlock(&stackLarge.lock)
12481248
}
12491249

1250-
// getStackMap returns the locals and arguments live pointer maps, and
1251-
// stack object list for frame.
1252-
func (frame *stkframe) getStackMap(cache *pcvalueCache, debug bool) (locals, args bitvector, objs []stackObjectRecord) {
1253-
targetpc := frame.continpc
1254-
if targetpc == 0 {
1255-
// Frame is dead. Return empty bitvectors.
1256-
return
1257-
}
1258-
1259-
f := frame.fn
1260-
pcdata := int32(-1)
1261-
if targetpc != f.entry() {
1262-
// Back up to the CALL. If we're at the function entry
1263-
// point, we want to use the entry map (-1), even if
1264-
// the first instruction of the function changes the
1265-
// stack map.
1266-
targetpc--
1267-
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
1268-
}
1269-
if pcdata == -1 {
1270-
// We do not have a valid pcdata value but there might be a
1271-
// stackmap for this function. It is likely that we are looking
1272-
// at the function prologue, assume so and hope for the best.
1273-
pcdata = 0
1274-
}
1275-
1276-
// Local variables.
1277-
size := frame.varp - frame.sp
1278-
var minsize uintptr
1279-
switch goarch.ArchFamily {
1280-
case goarch.ARM64:
1281-
minsize = sys.StackAlign
1282-
default:
1283-
minsize = sys.MinFrameSize
1284-
}
1285-
if size > minsize {
1286-
stackid := pcdata
1287-
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
1288-
if stkmap == nil || stkmap.n <= 0 {
1289-
print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
1290-
throw("missing stackmap")
1291-
}
1292-
// If nbit == 0, there's no work to do.
1293-
if stkmap.nbit > 0 {
1294-
if stackid < 0 || stackid >= stkmap.n {
1295-
// don't know where we are
1296-
print("runtime: pcdata is ", stackid, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
1297-
throw("bad symbol table")
1298-
}
1299-
locals = stackmapdata(stkmap, stackid)
1300-
if stackDebug >= 3 && debug {
1301-
print(" locals ", stackid, "/", stkmap.n, " ", locals.n, " words ", locals.bytedata, "\n")
1302-
}
1303-
} else if stackDebug >= 3 && debug {
1304-
print(" no locals to adjust\n")
1305-
}
1306-
}
1307-
1308-
// Arguments. First fetch frame size and special-case argument maps.
1309-
var isReflect bool
1310-
args, isReflect = frame.argMapInternal()
1311-
if args.n > 0 && args.bytedata == nil {
1312-
// Non-empty argument frame, but not a special map.
1313-
// Fetch the argument map at pcdata.
1314-
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
1315-
if stackmap == nil || stackmap.n <= 0 {
1316-
print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(args.n*goarch.PtrSize), "\n")
1317-
throw("missing stackmap")
1318-
}
1319-
if pcdata < 0 || pcdata >= stackmap.n {
1320-
// don't know where we are
1321-
print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
1322-
throw("bad symbol table")
1323-
}
1324-
if stackmap.nbit == 0 {
1325-
args.n = 0
1326-
} else {
1327-
args = stackmapdata(stackmap, pcdata)
1328-
}
1329-
}
1330-
1331-
// stack objects.
1332-
if (GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le" || GOARCH == "riscv64") &&
1333-
unsafe.Sizeof(abi.RegArgs{}) > 0 && isReflect {
1334-
// For reflect.makeFuncStub and reflect.methodValueCall,
1335-
// we need to fake the stack object record.
1336-
// These frames contain an internal/abi.RegArgs at a hard-coded offset.
1337-
// This offset matches the assembly code on amd64 and arm64.
1338-
objs = methodValueCallFrameObjs[:]
1339-
} else {
1340-
p := funcdata(f, _FUNCDATA_StackObjects)
1341-
if p != nil {
1342-
n := *(*uintptr)(p)
1343-
p = add(p, goarch.PtrSize)
1344-
r0 := (*stackObjectRecord)(noescape(p))
1345-
objs = unsafe.Slice(r0, int(n))
1346-
// Note: the noescape above is needed to keep
1347-
// getStackMap from "leaking param content:
1348-
// frame". That leak propagates up to getgcmask, then
1349-
// GCMask, then verifyGCInfo, which converts the stack
1350-
// gcinfo tests into heap gcinfo tests :(
1351-
}
1352-
}
1353-
1354-
return
1355-
}
1356-
1357-
var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit
1358-
1359-
func stkobjinit() {
1360-
var abiRegArgsEface any = abi.RegArgs{}
1361-
abiRegArgsType := efaceOf(&abiRegArgsEface)._type
1362-
if abiRegArgsType.kind&kindGCProg != 0 {
1363-
throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs")
1364-
}
1365-
// Set methodValueCallFrameObjs[0].gcdataoff so that
1366-
// stackObjectRecord.gcdata() will work correctly with it.
1367-
ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0]))
1368-
var mod *moduledata
1369-
for datap := &firstmoduledata; datap != nil; datap = datap.next {
1370-
if datap.gofunc <= ptr && ptr < datap.end {
1371-
mod = datap
1372-
break
1373-
}
1374-
}
1375-
if mod == nil {
1376-
throw("methodValueCallFrameObjs is not in a module")
1377-
}
1378-
methodValueCallFrameObjs[0] = stackObjectRecord{
1379-
off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local.
1380-
size: int32(abiRegArgsType.size),
1381-
_ptrdata: int32(abiRegArgsType.ptrdata),
1382-
gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.gcdata)) - mod.rodata),
1383-
}
1384-
}
1385-
13861250
// A stackObjectRecord is generated by the compiler for each stack object in a stack frame.
13871251
// This record must match the generator code in cmd/compile/internal/liveness/plive.go:emitStackObjects.
13881252
type stackObjectRecord struct {

0 commit comments

Comments
 (0)