mirror of
https://github.com/golang/go
synced 2024-11-26 04:17:59 -07:00
cmd/compile: use existing instructions instead of nops for inline marks
Instead of always inserting a nop to use as the target of an inline mark, see if we can instead find an instruction we're issuing anyway with the correct line number, and use that instruction. That way, we don't need to issue a nop. Makes cmd/go 0.3% smaller. Update #29571 Change-Id: If6cfc93ab3352ec2c6e0878f8074a3bf0786b2f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/158021 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
88adc33827
commit
2034fbab5b
@ -199,7 +199,7 @@ func testCallbackCallers(t *testing.T) {
|
|||||||
t.Errorf("expected %d frames, got %d", len(name), n)
|
t.Errorf("expected %d frames, got %d", len(name), n)
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
f := runtime.FuncForPC(pc[i])
|
f := runtime.FuncForPC(pc[i] - 1) // TODO: use runtime.CallersFrames
|
||||||
if f == nil {
|
if f == nil {
|
||||||
t.Fatalf("expected non-nil Func for pc %d", pc[i])
|
t.Fatalf("expected non-nil Func for pc %d", pc[i])
|
||||||
}
|
}
|
||||||
|
@ -147,8 +147,8 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
|||||||
|
|
||||||
// Make a second pass through the progs to compute PC ranges for
|
// Make a second pass through the progs to compute PC ranges for
|
||||||
// the various inlined calls.
|
// the various inlined calls.
|
||||||
|
start := int64(-1)
|
||||||
curii := -1
|
curii := -1
|
||||||
var crange *dwarf.Range
|
|
||||||
var prevp *obj.Prog
|
var prevp *obj.Prog
|
||||||
for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
|
for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
|
||||||
if prevp != nil && p.Pos == prevp.Pos {
|
if prevp != nil && p.Pos == prevp.Pos {
|
||||||
@ -157,17 +157,17 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
|||||||
ii := posInlIndex(p.Pos)
|
ii := posInlIndex(p.Pos)
|
||||||
if ii == curii {
|
if ii == curii {
|
||||||
continue
|
continue
|
||||||
} else {
|
|
||||||
// Close out the current range
|
|
||||||
endRange(crange, p)
|
|
||||||
|
|
||||||
// Begin new range
|
|
||||||
crange = beginRange(inlcalls.Calls, p, ii, imap)
|
|
||||||
curii = ii
|
|
||||||
}
|
}
|
||||||
|
// Close out the current range
|
||||||
|
if start != -1 {
|
||||||
|
addRange(inlcalls.Calls, start, p.Pc, curii, imap)
|
||||||
|
}
|
||||||
|
// Begin new range
|
||||||
|
start = p.Pc
|
||||||
|
curii = ii
|
||||||
}
|
}
|
||||||
if crange != nil {
|
if start != -1 {
|
||||||
crange.End = fnsym.Size
|
addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
@ -287,26 +287,26 @@ func posInlIndex(xpos src.XPos) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func endRange(crange *dwarf.Range, p *obj.Prog) {
|
func addRange(calls []dwarf.InlCall, start, end int64, ii int, imap map[int]int) {
|
||||||
if crange == nil {
|
if start == -1 {
|
||||||
|
panic("bad range start")
|
||||||
|
}
|
||||||
|
if end == -1 {
|
||||||
|
panic("bad range end")
|
||||||
|
}
|
||||||
|
if ii == -1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
crange.End = p.Pc
|
if start == end {
|
||||||
}
|
return
|
||||||
|
|
||||||
func beginRange(calls []dwarf.InlCall, p *obj.Prog, ii int, imap map[int]int) *dwarf.Range {
|
|
||||||
if ii == -1 {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
// Append range to correct inlined call
|
||||||
callIdx, found := imap[ii]
|
callIdx, found := imap[ii]
|
||||||
if !found {
|
if !found {
|
||||||
Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, p.Pc)
|
Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, start)
|
||||||
}
|
}
|
||||||
call := &calls[callIdx]
|
call := &calls[callIdx]
|
||||||
|
call.Ranges = append(call.Ranges, dwarf.Range{Start: start, End: end})
|
||||||
// Set up range and append to correct inlined call
|
|
||||||
call.Ranges = append(call.Ranges, dwarf.Range{Start: p.Pc, End: -1})
|
|
||||||
return &call.Ranges[len(call.Ranges)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
|
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
|
||||||
|
@ -5239,6 +5239,16 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inlMarks has an entry for each Prog that implements an inline mark.
|
||||||
|
// It maps from that Prog to the global inlining id of the inlined body
|
||||||
|
// which should unwind to this Prog's location.
|
||||||
|
var inlMarks map[*obj.Prog]int32
|
||||||
|
var inlMarkList []*obj.Prog
|
||||||
|
|
||||||
|
// inlMarksByPos maps from a (column 1) source position to the set of
|
||||||
|
// Progs that are in the set above and have that source position.
|
||||||
|
var inlMarksByPos map[src.XPos][]*obj.Prog
|
||||||
|
|
||||||
// Emit basic blocks
|
// Emit basic blocks
|
||||||
for i, b := range f.Blocks {
|
for i, b := range f.Blocks {
|
||||||
s.bstart[b.ID] = s.pp.next
|
s.bstart[b.ID] = s.pp.next
|
||||||
@ -5276,8 +5286,14 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||||||
}
|
}
|
||||||
case ssa.OpInlMark:
|
case ssa.OpInlMark:
|
||||||
p := thearch.Ginsnop(s.pp)
|
p := thearch.Ginsnop(s.pp)
|
||||||
pp.curfn.Func.lsym.Func.AddInlMark(p, v.AuxInt32())
|
if inlMarks == nil {
|
||||||
// TODO: if matching line number, merge somehow with previous instruction?
|
inlMarks = map[*obj.Prog]int32{}
|
||||||
|
inlMarksByPos = map[src.XPos][]*obj.Prog{}
|
||||||
|
}
|
||||||
|
inlMarks[p] = v.AuxInt32()
|
||||||
|
inlMarkList = append(inlMarkList, p)
|
||||||
|
pos := v.Pos.AtColumn1()
|
||||||
|
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// let the backend handle it
|
// let the backend handle it
|
||||||
@ -5318,6 +5334,50 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if inlMarks != nil {
|
||||||
|
// We have some inline marks. Try to find other instructions we're
|
||||||
|
// going to emit anyway, and use those instructions instead of the
|
||||||
|
// inline marks.
|
||||||
|
for p := pp.Text; p != nil; p = p.Link {
|
||||||
|
if p.As == obj.ANOP || p.As == obj.AFUNCDATA || p.As == obj.APCDATA || p.As == obj.ATEXT || p.As == obj.APCALIGN || thearch.LinkArch.Family == sys.Wasm {
|
||||||
|
// Don't use 0-sized instructions as inline marks, because we need
|
||||||
|
// to identify inline mark instructions by pc offset.
|
||||||
|
// (Some of these instructions are sometimes zero-sized, sometimes not.
|
||||||
|
// We must not use anything that even might be zero-sized.)
|
||||||
|
// TODO: are there others?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := inlMarks[p]; ok {
|
||||||
|
// Don't use inline marks themselves. We don't know
|
||||||
|
// whether they will be zero-sized or not yet.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pos := p.Pos.AtColumn1()
|
||||||
|
s := inlMarksByPos[pos]
|
||||||
|
if len(s) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, m := range s {
|
||||||
|
// We found an instruction with the same source position as
|
||||||
|
// some of the inline marks.
|
||||||
|
// Use this instruction instead.
|
||||||
|
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[m])
|
||||||
|
// Make the inline mark a real nop, so it doesn't generate any code.
|
||||||
|
m.As = obj.ANOP
|
||||||
|
m.Pos = src.NoXPos
|
||||||
|
m.From = obj.Addr{}
|
||||||
|
m.To = obj.Addr{}
|
||||||
|
}
|
||||||
|
delete(inlMarksByPos, pos)
|
||||||
|
}
|
||||||
|
// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
|
||||||
|
for _, p := range inlMarkList {
|
||||||
|
if p.As != obj.ANOP {
|
||||||
|
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[p])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if Ctxt.Flag_locationlists {
|
if Ctxt.Flag_locationlists {
|
||||||
e.curfn.Func.DebugInfo = ssa.BuildFuncDebug(Ctxt, f, Debug_locationlist > 1, stackOffset)
|
e.curfn.Func.DebugInfo = ssa.BuildFuncDebug(Ctxt, f, Debug_locationlist > 1, stackOffset)
|
||||||
bstart := s.bstart
|
bstart := s.bstart
|
||||||
|
@ -430,3 +430,7 @@ func (x lico) lineNumberHTML() string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("<%s>%s%d</%s>", style, pfx, x.Line(), style)
|
return fmt.Sprintf("<%s>%s%d</%s>", style, pfx, x.Line(), style)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x lico) atColumn1() lico {
|
||||||
|
return makeLico(x.Line(), 1)
|
||||||
|
}
|
||||||
|
@ -80,6 +80,12 @@ func (p XPos) LineNumberHTML() string {
|
|||||||
return p.lico.lineNumberHTML()
|
return p.lico.lineNumberHTML()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AtColumn1 returns the same location but shifted to column 1.
|
||||||
|
func (p XPos) AtColumn1() XPos {
|
||||||
|
p.lico = p.lico.atColumn1()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
// A PosTable tracks Pos -> XPos conversions and vice versa.
|
// A PosTable tracks Pos -> XPos conversions and vice versa.
|
||||||
// Its zero value is a ready-to-use PosTable.
|
// Its zero value is a ready-to-use PosTable.
|
||||||
type PosTable struct {
|
type PosTable struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user