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

cmd/compile: print accurate escape reason for non-const-length slices

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>
This commit is contained in:
Alberto Donizetti 2018-03-28 12:19:46 +02:00
parent f8b28e28f8
commit 360c19157a
3 changed files with 29 additions and 4 deletions

View File

@ -665,18 +665,29 @@ func (e *EscState) esc(n *Node, parent *Node) {
} }
} }
// Big stuff escapes unconditionally // Big stuff and non-constant-sized stuff escapes unconditionally.
// "Big" conditions that were scattered around in walk have been gathered here // "Big" conditions that were scattered around in walk have been
// gathered here.
if n.Esc != EscHeap && n.Type != nil && if n.Esc != EscHeap && n.Type != nil &&
(n.Type.Width > maxStackVarSize || (n.Type.Width > maxStackVarSize ||
(n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= 1<<16 || (n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= 1<<16 ||
n.Op == OMAKESLICE && !isSmallMakeSlice(n)) { 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 { if Debug['m'] > 2 {
Warnl(n.Pos, "%v is too large for stack", n) Warnl(n.Pos, "%v "+msgVerb+escapeMsg, n)
} }
n.Esc = EscHeap n.Esc = EscHeap
addrescapes(n) 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) e.esc(n.Left, n)

View 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 := make([]*string, 65537) // ERROR "make\(\[\]\*string, 65537\) escapes to heap"
b[0] = y 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
}

View File

@ -118,6 +118,13 @@ func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because
return b 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. // 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 for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done