Skip to content

Commit

Permalink
cmd/compile: restore more missing -m=2 escape analysis details
Browse files Browse the repository at this point in the history
This CL also restores analysis details for (1) expressions that are
directly heap allocated because of being too large for the stack or
non-constant in size, and (2) for assignments that we short circuit
because we flow their address to another escaping object.

No change to normal compilation behavior. Only adds additional Printfs
guarded by -m=2.

Updates #31489.

Change-Id: I43682195d389398d75ced2054e29d9907bb966e7
Reviewed-on: https://go-review.googlesource.com/c/go/+/205917
Run-TryBot: Matthew Dempsky <[email protected]>
Reviewed-by: David Chase <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
mdempsky committed Nov 7, 2019
1 parent a930fed commit 4cde749
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 18 deletions.
27 changes: 22 additions & 5 deletions src/cmd/compile/internal/gc/esc.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,28 @@ func mayAffectMemory(n *Node) bool {
}

func mustHeapAlloc(n *Node) bool {
// TODO(mdempsky): Cleanup this mess.
return n.Type != nil &&
(n.Type.Width > maxStackVarSize ||
(n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize ||
n.Op == OMAKESLICE && !isSmallMakeSlice(n))
if n.Type == nil {
return false
}

// Parameters are always passed via the stack.
if n.Op == ONAME && (n.Class() == PPARAM || n.Class() == PPARAMOUT) {
return false
}

if n.Type.Width > maxStackVarSize {
return true
}

if (n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize {
return true
}

if n.Op == OMAKESLICE && !isSmallMakeSlice(n) {
return true
}

return false
}

// addrescapes tags node n as having had its address taken
Expand Down
37 changes: 24 additions & 13 deletions src/cmd/compile/internal/gc/escape.go
Original file line number Diff line number Diff line change
Expand Up @@ -1062,8 +1062,12 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation {
}
n.SetOpt(loc)

if mustHeapAlloc(n) && !loc.isName(PPARAM) && !loc.isName(PPARAMOUT) {
loc.escapes = true
if mustHeapAlloc(n) {
why := "too large for stack"
if n.Op == OMAKESLICE && (!Isconst(n.Left, CTINT) || !Isconst(n.Right, CTINT)) {
why = "non-constant size"
}
e.flow(e.heapHole().addr(n, why), loc)
}
}
return loc
Expand All @@ -1087,6 +1091,11 @@ func (e *Escape) flow(k EscHole, src *EscLocation) {
return
}
if dst.escapes && k.derefs < 0 { // dst = &src
if Debug['m'] >= 2 {
pos := linestr(src.n.Pos)
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
e.explainFlow(pos, dst, src, k.derefs, k.notes)
}
src.escapes = true
return
}
Expand Down Expand Up @@ -1224,15 +1233,7 @@ func (e *Escape) explainPath(root, src *EscLocation) {
Fatalf("path inconsistency: %v != %v", edge.src, src)
}

derefs := "&"
if edge.derefs >= 0 {
derefs = strings.Repeat("*", edge.derefs)
}

fmt.Printf("%s: flow: %s = %s%v:\n", pos, e.explainLoc(dst), derefs, e.explainLoc(src))
for notes := edge.notes; notes != nil; notes = notes.next {
fmt.Printf("%s: from %v (%v) at %s\n", pos, notes.where, notes.why, linestr(notes.where.Pos))
}
e.explainFlow(pos, dst, src, edge.derefs, edge.notes)

if dst == root {
break
Expand All @@ -1241,6 +1242,18 @@ func (e *Escape) explainPath(root, src *EscLocation) {
}
}

func (e *Escape) explainFlow(pos string, dst, src *EscLocation, derefs int, notes *EscNote) {
ops := "&"
if derefs >= 0 {
ops = strings.Repeat("*", derefs)
}

fmt.Printf("%s: flow: %s = %s%v:\n", pos, e.explainLoc(dst), ops, e.explainLoc(src))
for note := notes; note != nil; note = note.next {
fmt.Printf("%s: from %v (%v) at %s\n", pos, note.where, note.why, linestr(note.where.Pos))
}
}

func (e *Escape) explainLoc(l *EscLocation) string {
if l == &e.heapLoc {
return "{heap}"
Expand Down Expand Up @@ -1364,8 +1377,6 @@ func (e *Escape) finish(fns []*Node) {
n.SetOpt(nil)

// Update n.Esc based on escape analysis results.
//
// TODO(mdempsky): Describe path when Debug['m'] >= 2.

if loc.escapes {
if Debug['m'] != 0 && n.Op != ONAME {
Expand Down

0 comments on commit 4cde749

Please sign in to comment.