1
0
mirror of https://github.com/golang/go synced 2024-11-13 18:50:24 -07:00

runtime: use entry stack map at function entry

Currently, when the runtime looks up the stack map for a frame, it
uses frame.continpc - 1 unless continpc is the function entry PC, in
which case it uses frame.continpc. As a result, if continpc is the
function entry point (which happens for deferred frames), it will
actually look up the stack map *following* the first instruction.

I think, though I am not positive, that this is always okay today
because the first instruction of a function can never change the stack
map. It's usually not a CALL, so it doesn't have PCDATA. Or, if it is
a CALL, it has to have the entry stack map.

But we're about to start emitting stack maps at every instruction that
changes them, which means the first instruction can have PCDATA
(notably, in leaf functions that don't have a prologue).

To prepare for this, tweak how the runtime looks up stack map indexes
so that if continpc is the function entry point, it directly uses the
entry stack map.

For #24543.

Change-Id: I85aa818041cd26aff416f7b1fba186e9c8ca6568
Reviewed-on: https://go-review.googlesource.com/109349
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2018-04-25 16:53:04 -04:00
parent 3c65bb5b90
commit 0fd427fda7
4 changed files with 12 additions and 4 deletions

View File

@ -248,10 +248,11 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
// Figure out what we can about our stack map // Figure out what we can about our stack map
pc := s.pc pc := s.pc
pcdata := int32(-1) // Use the entry map at function entry
if pc != f.entry { if pc != f.entry {
pc-- pc--
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, pc, nil)
} }
pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc, nil)
if pcdata == -1 { if pcdata == -1 {
// We do not have a valid pcdata value but there might be a // We do not have a valid pcdata value but there might be a
// stackmap for this function. It is likely that we are looking // stackmap for this function. It is likely that we are looking

View File

@ -2004,10 +2004,11 @@ func getgcmask(ep interface{}) (mask []byte) {
if targetpc == 0 { if targetpc == 0 {
return return
} }
pcdata := int32(-1) // Use the entry map at function entry
if targetpc != f.entry { if targetpc != f.entry {
targetpc-- targetpc--
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
} }
pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
if pcdata == -1 { if pcdata == -1 {
return return
} }

View File

@ -801,10 +801,15 @@ func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
if _DebugGC > 1 { if _DebugGC > 1 {
print("scanframe ", funcname(f), "\n") print("scanframe ", funcname(f), "\n")
} }
pcdata := int32(-1)
if targetpc != f.entry { 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-- targetpc--
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
} }
pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
if pcdata == -1 { if pcdata == -1 {
// We do not have a valid pcdata value but there might be a // We do not have a valid pcdata value but there might be a
// stackmap for this function. It is likely that we are looking // stackmap for this function. It is likely that we are looking

View File

@ -625,10 +625,11 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
// have full GC info for it (because it is written in asm). // have full GC info for it (because it is written in asm).
return true return true
} }
pcdata := int32(-1) // Use the entry map at function entry
if targetpc != f.entry { if targetpc != f.entry {
targetpc-- targetpc--
pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
} }
pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
if pcdata == -1 { if pcdata == -1 {
pcdata = 0 // in prologue pcdata = 0 // in prologue
} }