mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00: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:
parent
f8b28e28f8
commit
360c19157a
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue