Skip to content

Commit 2034fba

Browse files
committed
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>
1 parent 88adc33 commit 2034fba

File tree

5 files changed

+96
-26
lines changed

5 files changed

+96
-26
lines changed

misc/cgo/test/callback.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func testCallbackCallers(t *testing.T) {
199199
t.Errorf("expected %d frames, got %d", len(name), n)
200200
}
201201
for i := 0; i < n; i++ {
202-
f := runtime.FuncForPC(pc[i])
202+
f := runtime.FuncForPC(pc[i] - 1) // TODO: use runtime.CallersFrames
203203
if f == nil {
204204
t.Fatalf("expected non-nil Func for pc %d", pc[i])
205205
}

src/cmd/compile/internal/gc/dwinl.go

+23-23
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
147147

148148
// Make a second pass through the progs to compute PC ranges for
149149
// the various inlined calls.
150+
start := int64(-1)
150151
curii := -1
151-
var crange *dwarf.Range
152152
var prevp *obj.Prog
153153
for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
154154
if prevp != nil && p.Pos == prevp.Pos {
@@ -157,17 +157,17 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
157157
ii := posInlIndex(p.Pos)
158158
if ii == curii {
159159
continue
160-
} else {
161-
// Close out the current range
162-
endRange(crange, p)
163-
164-
// Begin new range
165-
crange = beginRange(inlcalls.Calls, p, ii, imap)
166-
curii = ii
167160
}
161+
// Close out the current range
162+
if start != -1 {
163+
addRange(inlcalls.Calls, start, p.Pc, curii, imap)
164+
}
165+
// Begin new range
166+
start = p.Pc
167+
curii = ii
168168
}
169-
if crange != nil {
170-
crange.End = fnsym.Size
169+
if start != -1 {
170+
addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
171171
}
172172

173173
// Debugging
@@ -287,26 +287,26 @@ func posInlIndex(xpos src.XPos) int {
287287
return -1
288288
}
289289

290-
func endRange(crange *dwarf.Range, p *obj.Prog) {
291-
if crange == nil {
292-
return
290+
func addRange(calls []dwarf.InlCall, start, end int64, ii int, imap map[int]int) {
291+
if start == -1 {
292+
panic("bad range start")
293+
}
294+
if end == -1 {
295+
panic("bad range end")
293296
}
294-
crange.End = p.Pc
295-
}
296-
297-
func beginRange(calls []dwarf.InlCall, p *obj.Prog, ii int, imap map[int]int) *dwarf.Range {
298297
if ii == -1 {
299-
return nil
298+
return
300299
}
300+
if start == end {
301+
return
302+
}
303+
// Append range to correct inlined call
301304
callIdx, found := imap[ii]
302305
if !found {
303-
Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, p.Pc)
306+
Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, start)
304307
}
305308
call := &calls[callIdx]
306-
307-
// Set up range and append to correct inlined call
308-
call.Ranges = append(call.Ranges, dwarf.Range{Start: p.Pc, End: -1})
309-
return &call.Ranges[len(call.Ranges)-1]
309+
call.Ranges = append(call.Ranges, dwarf.Range{Start: start, End: end})
310310
}
311311

312312
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {

src/cmd/compile/internal/gc/ssa.go

+62-2
Original file line numberDiff line numberDiff line change
@@ -5239,6 +5239,16 @@ func genssa(f *ssa.Func, pp *Progs) {
52395239
}
52405240
}
52415241

5242+
// inlMarks has an entry for each Prog that implements an inline mark.
5243+
// It maps from that Prog to the global inlining id of the inlined body
5244+
// which should unwind to this Prog's location.
5245+
var inlMarks map[*obj.Prog]int32
5246+
var inlMarkList []*obj.Prog
5247+
5248+
// inlMarksByPos maps from a (column 1) source position to the set of
5249+
// Progs that are in the set above and have that source position.
5250+
var inlMarksByPos map[src.XPos][]*obj.Prog
5251+
52425252
// Emit basic blocks
52435253
for i, b := range f.Blocks {
52445254
s.bstart[b.ID] = s.pp.next
@@ -5276,8 +5286,14 @@ func genssa(f *ssa.Func, pp *Progs) {
52765286
}
52775287
case ssa.OpInlMark:
52785288
p := thearch.Ginsnop(s.pp)
5279-
pp.curfn.Func.lsym.Func.AddInlMark(p, v.AuxInt32())
5280-
// TODO: if matching line number, merge somehow with previous instruction?
5289+
if inlMarks == nil {
5290+
inlMarks = map[*obj.Prog]int32{}
5291+
inlMarksByPos = map[src.XPos][]*obj.Prog{}
5292+
}
5293+
inlMarks[p] = v.AuxInt32()
5294+
inlMarkList = append(inlMarkList, p)
5295+
pos := v.Pos.AtColumn1()
5296+
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
52815297

52825298
default:
52835299
// let the backend handle it
@@ -5318,6 +5334,50 @@ func genssa(f *ssa.Func, pp *Progs) {
53185334
}
53195335
}
53205336

5337+
if inlMarks != nil {
5338+
// We have some inline marks. Try to find other instructions we're
5339+
// going to emit anyway, and use those instructions instead of the
5340+
// inline marks.
5341+
for p := pp.Text; p != nil; p = p.Link {
5342+
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 {
5343+
// Don't use 0-sized instructions as inline marks, because we need
5344+
// to identify inline mark instructions by pc offset.
5345+
// (Some of these instructions are sometimes zero-sized, sometimes not.
5346+
// We must not use anything that even might be zero-sized.)
5347+
// TODO: are there others?
5348+
continue
5349+
}
5350+
if _, ok := inlMarks[p]; ok {
5351+
// Don't use inline marks themselves. We don't know
5352+
// whether they will be zero-sized or not yet.
5353+
continue
5354+
}
5355+
pos := p.Pos.AtColumn1()
5356+
s := inlMarksByPos[pos]
5357+
if len(s) == 0 {
5358+
continue
5359+
}
5360+
for _, m := range s {
5361+
// We found an instruction with the same source position as
5362+
// some of the inline marks.
5363+
// Use this instruction instead.
5364+
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[m])
5365+
// Make the inline mark a real nop, so it doesn't generate any code.
5366+
m.As = obj.ANOP
5367+
m.Pos = src.NoXPos
5368+
m.From = obj.Addr{}
5369+
m.To = obj.Addr{}
5370+
}
5371+
delete(inlMarksByPos, pos)
5372+
}
5373+
// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
5374+
for _, p := range inlMarkList {
5375+
if p.As != obj.ANOP {
5376+
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[p])
5377+
}
5378+
}
5379+
}
5380+
53215381
if Ctxt.Flag_locationlists {
53225382
e.curfn.Func.DebugInfo = ssa.BuildFuncDebug(Ctxt, f, Debug_locationlist > 1, stackOffset)
53235383
bstart := s.bstart

src/cmd/internal/src/pos.go

+4
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,7 @@ func (x lico) lineNumberHTML() string {
430430
}
431431
return fmt.Sprintf("<%s>%s%d</%s>", style, pfx, x.Line(), style)
432432
}
433+
434+
func (x lico) atColumn1() lico {
435+
return makeLico(x.Line(), 1)
436+
}

src/cmd/internal/src/xpos.go

+6
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ func (p XPos) LineNumberHTML() string {
8080
return p.lico.lineNumberHTML()
8181
}
8282

83+
// AtColumn1 returns the same location but shifted to column 1.
84+
func (p XPos) AtColumn1() XPos {
85+
p.lico = p.lico.atColumn1()
86+
return p
87+
}
88+
8389
// A PosTable tracks Pos -> XPos conversions and vice versa.
8490
// Its zero value is a ready-to-use PosTable.
8591
type PosTable struct {

0 commit comments

Comments
 (0)