]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: restore more missing -m=2 escape analysis details
authorMatthew Dempsky <mdempsky@google.com>
Thu, 7 Nov 2019 20:32:30 +0000 (12:32 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 7 Nov 2019 21:59:16 +0000 (21:59 +0000)
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>

src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/escape.go

index 725e7410c4990b6de441dd242270f09dae7935aa..8e781a7997c82f4958ecc94c6c0dc5e88cff55ff 100644 (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
index dc078c54c4b1aadcdd23a5e8cf6cd2be4644729f..bd4df1d84f1063476cfd667090e60a34430826a2 100644 (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 {