diff options
author | David Chase <drchase@google.com> | 2019-05-02 13:35:07 -0400 |
---|---|---|
committer | David Chase <drchase@google.com> | 2019-05-16 03:26:42 +0000 |
commit | fba60669751a5362c43e3bdee8455bed3fa275b2 (patch) | |
tree | 8984a0981070c2ccd4bfa20a3cfeae2aa1f2b63d /src/cmd/compile/internal/ssa/numberlines.go | |
parent | f2694534cf3591191a125815bae24cd12ea07022 (diff) | |
download | go-fba60669751a5362c43e3bdee8455bed3fa275b2.tar.gz go-fba60669751a5362c43e3bdee8455bed3fa275b2.zip |
cmd/compile: add debugging and stats output to numberlines
This is useful for debugging line number assignment and
also for making sense of pathological line number inputs.
Activated with
-gcflags=-d=ssa/number_lines/stats=1 (the bit matters)
-gcflags=-d=ssa/number_lines/debug
Stats:
"SUM_LINE_RANGE",
SUM for f in files {MAX line in f {line}-MIN line in f {line}}
"MAXMIN_LINE_RANGE",
MAX for f in files {MAX line in f {line}} -
MIN for f in files {MIN line in f {line}}
"MAXFILE", maxfile,
MAX for f in files {f}
"NFILES", len(entries)
| files |
Change-Id: I8a7336e6370452fe2e3a62de17606db9bd6a6fd3
Reviewed-on: https://go-review.googlesource.com/c/go/+/174947
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/numberlines.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/numberlines.go | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/ssa/numberlines.go b/src/cmd/compile/internal/ssa/numberlines.go index 6ff337ce6f..4807da731c 100644 --- a/src/cmd/compile/internal/ssa/numberlines.go +++ b/src/cmd/compile/internal/ssa/numberlines.go @@ -7,6 +7,8 @@ package ssa import ( "cmd/internal/obj" "cmd/internal/src" + "fmt" + "sort" ) func isPoorStatementOp(op Op) bool { @@ -82,6 +84,32 @@ func (b *Block) FirstPossibleStmtValue() *Value { return nil } +func flc(p src.XPos) string { + if p == src.NoXPos { + return "none" + } + return fmt.Sprintf("(%d):%d:%d", p.FileIndex(), p.Line(), p.Col()) +} + +type fileAndPair struct { + f int32 + lp lineRange +} + +type fileAndPairs []fileAndPair + +func (fap fileAndPairs) Len() int { + return len(fap) +} +func (fap fileAndPairs) Less(i, j int) bool { + return fap[i].f < fap[j].f +} +func (fap fileAndPairs) Swap(i, j int) { + fap[i], fap[j] = fap[j], fap[i] +} + +// -d=ssa/number_lines/stats=1 (that bit) for line and file distribution statistics +// -d=ssa/number_lines/debug for information about why particular values are marked as statements. func numberLines(f *Func) { po := f.Postorder() endlines := make(map[ID]src.XPos) @@ -131,6 +159,9 @@ func numberLines(f *Func) { if b.Pos.IsStmt() != src.PosNotStmt { b.Pos = b.Pos.WithIsStmt() endlines[b.ID] = b.Pos + if f.pass.debug > 0 { + fmt.Printf("Mark stmt effectively-empty-block %s %s %s\n", f.Name, b, flc(b.Pos)) + } continue } line := src.NoXPos @@ -153,11 +184,18 @@ func numberLines(f *Func) { // check predecessors for any difference; if firstPos differs, then it is a boundary. if len(b.Preds) == 0 { // Don't forget the entry block b.Values[firstPosIndex].Pos = firstPos.WithIsStmt() - } else { + if f.pass.debug > 0 { + fmt.Printf("Mark stmt entry-block %s %s %s %s\n", f.Name, b, b.Values[firstPosIndex], flc(firstPos)) + } + } else { // differing pred for _, p := range b.Preds { pbi := p.Block().ID if endlines[pbi].Line() != firstPos.Line() || !endlines[pbi].SameFile(firstPos) { b.Values[firstPosIndex].Pos = firstPos.WithIsStmt() + if f.pass.debug > 0 { + fmt.Printf("Mark stmt differing-pred %s %s %s %s, different=%s ending %s\n", + f.Name, b, b.Values[firstPosIndex], flc(firstPos), p.Block(), flc(endlines[pbi])) + } break } } @@ -173,6 +211,9 @@ func numberLines(f *Func) { i = nextGoodStatementIndex(v, i, b) v = b.Values[i] if v.Pos.Line() != firstPos.Line() || !v.Pos.SameFile(firstPos) { + if f.pass.debug > 0 { + fmt.Printf("Mark stmt new line %s %s %s %s prev pos = %s\n", f.Name, b, v, flc(v.Pos), flc(firstPos)) + } firstPos = v.Pos v.Pos = v.Pos.WithIsStmt() } else { @@ -180,11 +221,43 @@ func numberLines(f *Func) { } } if b.Pos.IsStmt() != src.PosNotStmt && (b.Pos.Line() != firstPos.Line() || !b.Pos.SameFile(firstPos)) { + if f.pass.debug > 0 { + fmt.Printf("Mark stmt end of block differs %s %s %s prev pos = %s\n", f.Name, b, flc(b.Pos), flc(firstPos)) + } b.Pos = b.Pos.WithIsStmt() firstPos = b.Pos } endlines[b.ID] = firstPos } + if f.pass.stats&1 != 0 { + // Report summary statistics on the shape of the sparse map about to be constructed + // TODO use this information to make sparse maps faster. + var entries fileAndPairs + for k, v := range ranges { + entries = append(entries, fileAndPair{int32(k), v}) + } + sort.Sort(entries) + total := uint64(0) // sum over files of maxline(file) - minline(file) + maxfile := int32(0) // max(file indices) + minline := uint32(0xffffffff) // min over files of minline(file) + maxline := uint32(0) // max over files of maxline(file) + for _, v := range entries { + if f.pass.stats > 1 { + f.LogStat("file", v.f, "low", v.lp.first, "high", v.lp.last) + } + total += uint64(v.lp.last - v.lp.first) + if maxfile < v.f { + maxfile = v.f + } + if minline > v.lp.first { + minline = v.lp.first + } + if maxline < v.lp.last { + maxline = v.lp.last + } + } + f.LogStat("SUM_LINE_RANGE", total, "MAXMIN_LINE_RANGE", maxline-minline, "MAXFILE", maxfile, "NFILES", len(entries)) + } // cachedLineStarts is an empty sparse map for values that are included within ranges. f.cachedLineStarts = newXposmap(ranges) } |