Commit 4cde749f authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: restore more missing -m=2 escape analysis details

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 <mdempsky@google.com>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent a930fede
......@@ -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
......
......@@ -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
......@@ -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
}
......@@ -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
......@@ -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}"
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment