]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: print accurate escape reason for non-const-length slices
authorAlberto Donizetti <alb.donizetti@gmail.com>
Wed, 28 Mar 2018 10:19:46 +0000 (12:19 +0200)
committerAlberto Donizetti <alb.donizetti@gmail.com>
Wed, 28 Mar 2018 16:56:03 +0000 (16:56 +0000)
This change makes `-m -m` print a better explanation for the case
where a slice is marked as escaping and heap-allocated because it
has a non-constant len/cap.

Fixes #24578

Change-Id: I0ebafb77c758a99857d72b365817bdba7b446cc0
Reviewed-on: https://go-review.googlesource.com/102895
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
src/cmd/compile/internal/gc/esc.go
test/escape_array.go
test/escape_because.go

index 6ce2299ba23e260acc216afafe0ab3d0abee5b81..421595057670788720166701aaedad82cd646824 100644 (file)
@@ -665,18 +665,29 @@ func (e *EscState) esc(n *Node, parent *Node) {
                }
        }
 
-       // Big stuff escapes unconditionally
-       // "Big" conditions that were scattered around in walk have been gathered here
+       // Big stuff and non-constant-sized stuff escapes unconditionally.
+       // "Big" conditions that were scattered around in walk have been
+       // gathered here.
        if n.Esc != EscHeap && n.Type != nil &&
                (n.Type.Width > maxStackVarSize ||
                        (n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= 1<<16 ||
                        n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
+
+               // isSmallMakeSlice returns false for non-constant len/cap.
+               // If that's the case, print a more accurate escape reason.
+               var msgVerb, escapeMsg string
+               if n.Op == OMAKESLICE && (!Isconst(n.Left, CTINT) || !Isconst(n.Right, CTINT)) {
+                       msgVerb, escapeMsg = "has ", "non-constant size"
+               } else {
+                       msgVerb, escapeMsg = "is ", "too large for stack"
+               }
+
                if Debug['m'] > 2 {
-                       Warnl(n.Pos, "%v is too large for stack", n)
+                       Warnl(n.Pos, "%v "+msgVerb+escapeMsg, n)
                }
                n.Esc = EscHeap
                addrescapes(n)
-               e.escassignSinkWhy(n, n, "too large for stack") // TODO category: tooLarge
+               e.escassignSinkWhy(n, n, escapeMsg) // TODO category: tooLarge
        }
 
        e.esc(n.Left, n)
index 0204c690cddcccc8ccd89b769b8b6326e2f29958..c2c3e2c8574952006ada340e1236f5e77aa53794 100644 (file)
@@ -120,3 +120,10 @@ func doesMakeSlice(x *string, y *string) { // ERROR "leaking param: x" "leaking
        b := make([]*string, 65537) // ERROR "make\(\[\]\*string, 65537\) escapes to heap"
        b[0] = y
 }
+
+func nonconstArray() {
+       n := 32
+       s1 := make([]int, n)    // ERROR "make\(\[\]int, n\) escapes to heap"
+       s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap"
+       _, _ = s1, s2
+}
index 7d349b7a18d360ac1c9385f6df15feaf886d7948..a8423a59cc2535871fe66f594600538efe7365c5 100644 (file)
@@ -118,6 +118,13 @@ func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because
        return b
 }
 
+func f14() {
+       n := 32
+       s1 := make([]int, n)    // ERROR "make\(\[\]int, n\) escapes to heap" "from make\(\[\]int, n\) \(non-constant size\)"
+       s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap" "from make\(\[\]int, 0, n\) \(non-constant size\)"
+       _, _ = s1, s2
+}
+
 // The list below is all of the why-escapes messages seen building the escape analysis tests.
 /*
    for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done