mirror of
https://github.com/golang/go
synced 2024-11-07 00:26:18 -07:00
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 <mdempsky@google.com> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
a930fede73
commit
4cde749f63
@ -170,11 +170,28 @@ func mayAffectMemory(n *Node) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mustHeapAlloc(n *Node) bool {
|
func mustHeapAlloc(n *Node) bool {
|
||||||
// TODO(mdempsky): Cleanup this mess.
|
if n.Type == nil {
|
||||||
return n.Type != nil &&
|
return false
|
||||||
(n.Type.Width > maxStackVarSize ||
|
}
|
||||||
(n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize ||
|
|
||||||
n.Op == OMAKESLICE && !isSmallMakeSlice(n))
|
// 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
|
// addrescapes tags node n as having had its address taken
|
||||||
|
@ -1062,8 +1062,12 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation {
|
|||||||
}
|
}
|
||||||
n.SetOpt(loc)
|
n.SetOpt(loc)
|
||||||
|
|
||||||
if mustHeapAlloc(n) && !loc.isName(PPARAM) && !loc.isName(PPARAMOUT) {
|
if mustHeapAlloc(n) {
|
||||||
loc.escapes = true
|
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
|
return loc
|
||||||
@ -1087,6 +1091,11 @@ func (e *Escape) flow(k EscHole, src *EscLocation) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dst.escapes && k.derefs < 0 { // dst = &src
|
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
|
src.escapes = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1224,15 +1233,7 @@ func (e *Escape) explainPath(root, src *EscLocation) {
|
|||||||
Fatalf("path inconsistency: %v != %v", edge.src, src)
|
Fatalf("path inconsistency: %v != %v", edge.src, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
derefs := "&"
|
e.explainFlow(pos, dst, src, edge.derefs, edge.notes)
|
||||||
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
if dst == root {
|
if dst == root {
|
||||||
break
|
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 {
|
func (e *Escape) explainLoc(l *EscLocation) string {
|
||||||
if l == &e.heapLoc {
|
if l == &e.heapLoc {
|
||||||
return "{heap}"
|
return "{heap}"
|
||||||
@ -1364,8 +1377,6 @@ func (e *Escape) finish(fns []*Node) {
|
|||||||
n.SetOpt(nil)
|
n.SetOpt(nil)
|
||||||
|
|
||||||
// Update n.Esc based on escape analysis results.
|
// Update n.Esc based on escape analysis results.
|
||||||
//
|
|
||||||
// TODO(mdempsky): Describe path when Debug['m'] >= 2.
|
|
||||||
|
|
||||||
if loc.escapes {
|
if loc.escapes {
|
||||||
if Debug['m'] != 0 && n.Op != ONAME {
|
if Debug['m'] != 0 && n.Op != ONAME {
|
||||||
|
Loading…
Reference in New Issue
Block a user