From 4cde749f633753cf59d0cfc912351e1b1def2b4f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 7 Nov 2019 12:32:30 -0800 Subject: [PATCH] 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 Reviewed-by: David Chase TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/esc.go | 27 +++++++++++++++---- src/cmd/compile/internal/gc/escape.go | 37 +++++++++++++++++---------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 725e7410c49..8e781a7997c 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -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 diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index dc078c54c4b..bd4df1d84f1 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -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 {