From: Matthew Dempsky Date: Thu, 7 Nov 2019 20:32:30 +0000 (-0800) Subject: cmd/compile: restore more missing -m=2 escape analysis details X-Git-Tag: go1.14beta1~332 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4cde749f633753cf59d0cfc912351e1b1def2b4f;p=gostls13.git 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 --- diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 725e7410c4..8e781a7997 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 dc078c54c4..bd4df1d84f 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 {