mirror of
https://github.com/golang/go
synced 2024-11-18 01:04:48 -07:00
runtime: unify fetching of locals and arguments maps
Currently we have two nearly identical copies of the code that fetches the locals and arguments liveness maps for a frame, plus a third that's a poor knock-off. Unify these all into a single function. Change-Id: Ibce7926a0b0e3d23182112da4e25df899579a585 Reviewed-on: https://go-review.googlesource.com/109698 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
66a67ee6b4
commit
3080b7d0af
@ -1999,30 +1999,16 @@ func getgcmask(ep interface{}) (mask []byte) {
|
||||
_g_ := getg()
|
||||
gentraceback(_g_.m.curg.sched.pc, _g_.m.curg.sched.sp, 0, _g_.m.curg, 0, nil, 1000, getgcmaskcb, noescape(unsafe.Pointer(&frame)), 0)
|
||||
if frame.fn.valid() {
|
||||
f := frame.fn
|
||||
targetpc := frame.continpc
|
||||
if targetpc == 0 {
|
||||
locals, _ := getStackMap(&frame, nil, false)
|
||||
if locals.n == 0 {
|
||||
return
|
||||
}
|
||||
pcdata := int32(-1) // Use the entry map at function entry
|
||||
if targetpc != f.entry {
|
||||
targetpc--
|
||||
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
|
||||
}
|
||||
if pcdata == -1 {
|
||||
return
|
||||
}
|
||||
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
|
||||
if stkmap == nil || stkmap.n <= 0 {
|
||||
return
|
||||
}
|
||||
bv := stackmapdata(stkmap, pcdata)
|
||||
size := uintptr(bv.n) * sys.PtrSize
|
||||
size := uintptr(locals.n) * sys.PtrSize
|
||||
n := (*ptrtype)(unsafe.Pointer(t)).elem.size
|
||||
mask = make([]byte, n/sys.PtrSize)
|
||||
for i := uintptr(0); i < n; i += sys.PtrSize {
|
||||
off := (uintptr(p) + i - frame.varp + size) / sys.PtrSize
|
||||
mask[i/sys.PtrSize] = bv.ptrbit(off)
|
||||
mask[i/sys.PtrSize] = locals.ptrbit(off)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -791,82 +791,21 @@ func scanstack(gp *g, gcw *gcWork) {
|
||||
// Scan a stack frame: local variables and function arguments/results.
|
||||
//go:nowritebarrier
|
||||
func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
|
||||
if _DebugGC > 1 && frame.continpc != 0 {
|
||||
print("scanframe ", funcname(frame.fn), "\n")
|
||||
}
|
||||
|
||||
f := frame.fn
|
||||
targetpc := frame.continpc
|
||||
if targetpc == 0 {
|
||||
// Frame is dead.
|
||||
return
|
||||
}
|
||||
if _DebugGC > 1 {
|
||||
print("scanframe ", funcname(f), "\n")
|
||||
}
|
||||
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
|
||||
}
|
||||
locals, args := getStackMap(frame, cache, false)
|
||||
|
||||
// Scan local variables if stack frame has been allocated.
|
||||
size := frame.varp - frame.sp
|
||||
var minsize uintptr
|
||||
switch sys.ArchFamily {
|
||||
case sys.ARM64:
|
||||
minsize = sys.SpAlign
|
||||
default:
|
||||
minsize = sys.MinFrameSize
|
||||
}
|
||||
if size > minsize {
|
||||
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")
|
||||
}
|
||||
|
||||
// Locals bitmap information, scan just the pointers in locals.
|
||||
if pcdata < 0 || pcdata >= stkmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
|
||||
throw("scanframe: bad symbol table")
|
||||
}
|
||||
if stkmap.nbit > 0 {
|
||||
bv := stackmapdata(stkmap, pcdata)
|
||||
size = uintptr(bv.n) * sys.PtrSize
|
||||
scanblock(frame.varp-size, size, bv.bytedata, gcw)
|
||||
}
|
||||
if locals.n > 0 {
|
||||
size := uintptr(locals.n) * sys.PtrSize
|
||||
scanblock(frame.varp-size, size, locals.bytedata, gcw)
|
||||
}
|
||||
|
||||
// Scan arguments.
|
||||
if frame.arglen > 0 {
|
||||
var bv bitvector
|
||||
if frame.argmap != nil {
|
||||
bv = *frame.argmap
|
||||
} else {
|
||||
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
|
||||
if stkmap == nil || stkmap.n <= 0 {
|
||||
print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
|
||||
throw("missing stackmap")
|
||||
}
|
||||
if pcdata < 0 || pcdata >= stkmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
|
||||
throw("scanframe: bad symbol table")
|
||||
}
|
||||
bv = stackmapdata(stkmap, pcdata)
|
||||
}
|
||||
if bv.n > 0 {
|
||||
scanblock(frame.argp, uintptr(bv.n)*sys.PtrSize, bv.bytedata, gcw)
|
||||
}
|
||||
if args.n > 0 {
|
||||
scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,8 +606,7 @@ func adjustpointers(scanp unsafe.Pointer, bv *bitvector, adjinfo *adjustinfo, f
|
||||
// Note: the argument/return area is adjusted by the callee.
|
||||
func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
|
||||
adjinfo := (*adjustinfo)(arg)
|
||||
targetpc := frame.continpc
|
||||
if targetpc == 0 {
|
||||
if frame.continpc == 0 {
|
||||
// Frame is dead.
|
||||
return true
|
||||
}
|
||||
@ -621,47 +620,13 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
|
||||
// have full GC info for it (because it is written in asm).
|
||||
return true
|
||||
}
|
||||
pcdata := int32(-1) // Use the entry map at function entry
|
||||
if targetpc != f.entry {
|
||||
targetpc--
|
||||
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
|
||||
}
|
||||
if pcdata == -1 {
|
||||
pcdata = 0 // in prologue
|
||||
}
|
||||
|
||||
locals, args := getStackMap(frame, &adjinfo.cache, true)
|
||||
|
||||
// Adjust local variables if stack frame has been allocated.
|
||||
size := frame.varp - frame.sp
|
||||
var minsize uintptr
|
||||
switch sys.ArchFamily {
|
||||
case sys.ARM64:
|
||||
minsize = sys.SpAlign
|
||||
default:
|
||||
minsize = sys.MinFrameSize
|
||||
}
|
||||
if size > minsize {
|
||||
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
|
||||
if stackmap == nil || stackmap.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 stackmap.nbit > 0 {
|
||||
// Locals bitmap information, scan just the pointers in locals.
|
||||
if pcdata < 0 || pcdata >= stackmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
|
||||
throw("bad symbol table")
|
||||
}
|
||||
bv := stackmapdata(stackmap, pcdata)
|
||||
size = uintptr(bv.n) * sys.PtrSize
|
||||
if stackDebug >= 3 {
|
||||
print(" locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n")
|
||||
}
|
||||
adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
|
||||
} else if stackDebug >= 3 {
|
||||
print(" no locals to adjust\n")
|
||||
}
|
||||
if locals.n > 0 {
|
||||
size := uintptr(locals.n) * sys.PtrSize
|
||||
adjustpointers(unsafe.Pointer(frame.varp-size), &locals, adjinfo, f)
|
||||
}
|
||||
|
||||
// Adjust saved base pointer if there is one.
|
||||
@ -688,29 +653,11 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
// Adjust arguments.
|
||||
if frame.arglen > 0 {
|
||||
var bv bitvector
|
||||
if frame.argmap != nil {
|
||||
bv = *frame.argmap
|
||||
} else {
|
||||
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
|
||||
if stackmap == nil || stackmap.n <= 0 {
|
||||
print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", frame.arglen, "\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=", targetpc, ")\n")
|
||||
throw("bad symbol table")
|
||||
}
|
||||
bv = stackmapdata(stackmap, pcdata)
|
||||
}
|
||||
if args.n > 0 {
|
||||
if stackDebug >= 3 {
|
||||
print(" args\n")
|
||||
}
|
||||
if bv.n > 0 {
|
||||
adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, funcInfo{})
|
||||
}
|
||||
adjustpointers(unsafe.Pointer(frame.argp), &args, adjinfo, funcInfo{})
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -1186,6 +1133,86 @@ func freeStackSpans() {
|
||||
unlock(&stackLarge.lock)
|
||||
}
|
||||
|
||||
// getStackMap returns the locals and arguments live pointer maps for
|
||||
// frame.
|
||||
func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args bitvector) {
|
||||
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 sys.ArchFamily {
|
||||
case sys.ARM64:
|
||||
minsize = sys.SpAlign
|
||||
default:
|
||||
minsize = sys.MinFrameSize
|
||||
}
|
||||
if size > minsize {
|
||||
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
|
||||
if stackmap == nil || stackmap.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 stackmap.nbit > 0 {
|
||||
if pcdata < 0 || pcdata >= stackmap.n {
|
||||
// don't know where we are
|
||||
print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
|
||||
throw("bad symbol table")
|
||||
}
|
||||
locals = stackmapdata(stackmap, pcdata)
|
||||
if stackDebug >= 3 && debug {
|
||||
print(" locals ", pcdata, "/", stackmap.n, " ", locals.n, " words ", locals.bytedata, "\n")
|
||||
}
|
||||
} else if stackDebug >= 3 && debug {
|
||||
print(" no locals to adjust\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Arguments.
|
||||
if frame.arglen > 0 {
|
||||
if frame.argmap != nil {
|
||||
args = *frame.argmap
|
||||
} else {
|
||||
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
|
||||
if stackmap == nil || stackmap.n <= 0 {
|
||||
print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\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 = stackmapdata(stackmap, pcdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func morestackc() {
|
||||
throw("attempt to execute system stack code on user stack")
|
||||
|
Loading…
Reference in New Issue
Block a user