mirror of https://github.com/golang/go.git
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>
This commit is contained in:
parent
f2694534cf
commit
fba6066975
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue