]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add debugging and stats output to numberlines
authorDavid Chase <drchase@google.com>
Thu, 2 May 2019 17:35:07 +0000 (13:35 -0400)
committerDavid Chase <drchase@google.com>
Thu, 16 May 2019 03:26:42 +0000 (03:26 +0000)
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>
src/cmd/compile/internal/ssa/numberlines.go

index 6ff337ce6f14c0514fd6910946d863469cc3bc87..4807da731c3687d255c54b797a3b3384d025c18b 100644 (file)
@@ -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)
 }