1
0
mirror of https://github.com/golang/go synced 2024-11-06 22:36:15 -07:00

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: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Matthew Dempsky 2019-11-07 12:32:30 -08:00
parent a930fede73
commit 4cde749f63
2 changed files with 46 additions and 18 deletions

View File

@ -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

View File

@ -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 {