88 lines
3.4 KiB
Diff
88 lines
3.4 KiB
Diff
From f75ab2d5a61f1a5aabaffe7752110e2dcd581236 Mon Sep 17 00:00:00 2001
|
|
From: Matthew Dempsky <mdempsky@google.com>
|
|
Date: Sat, 27 Feb 2021 09:41:19 -0800
|
|
Subject: [PATCH 18/44] [release-branch.go1.15] cmd/compile: fix escape
|
|
analysis of heap-allocated results
|
|
|
|
One of escape analysis's responsibilities is to summarize whether/how
|
|
each function parameter flows to the heap so we can correctly
|
|
incorporate those flows into callers' escape analysis data flow
|
|
graphs.
|
|
|
|
As an optimization, we separately record when parameters flow to
|
|
result parameters, so that we can more precisely analyze parameter
|
|
flows based on how the results are used at the call site. However, if
|
|
a named result parameter itself needs to be heap allocated, this
|
|
optimization isn't safe and the parameter needs to be recorded as
|
|
flowing to heap rather than flowing to result.
|
|
|
|
Escape analysis used to get this correct because it conservatively
|
|
rewalked the data-flow graph multiple times. So even though it would
|
|
incorrectly record the result parameter flow, it would separately find
|
|
a flow to the heap. However, CL 196811 (specifically, case 3)
|
|
optimized the walking logic to reduce unnecessary rewalks causing us
|
|
to stop finding the extra heap flow.
|
|
|
|
This CL fixes the issue by correcting location.leakTo to be sensitive
|
|
to sink.escapes and not record result-flows when the result parameter
|
|
escapes to the heap.
|
|
|
|
Fixes #44658.
|
|
|
|
Change-Id: I48742ed35a6cab591094e2d23a439e205bd65c50
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/297289
|
|
Trust: Matthew Dempsky <mdempsky@google.com>
|
|
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
|
|
TryBot-Result: Go Bot <gobot@golang.org>
|
|
Reviewed-by: Keith Randall <khr@golang.org>
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/297291
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/golang/go/commit/f75ab2d5a61f1a5aabaffe7752110e2dcd581236
|
|
|
|
---
|
|
src/cmd/compile/internal/gc/escape.go | 7 ++++---
|
|
test/escape5.go | 11 +++++++++++
|
|
2 files changed, 15 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go
|
|
index 08000dd374..2c55163100 100644
|
|
--- a/src/cmd/compile/internal/gc/escape.go
|
|
+++ b/src/cmd/compile/internal/gc/escape.go
|
|
@@ -1379,9 +1379,10 @@ func containsClosure(f, c *Node) bool {
|
|
|
|
// leak records that parameter l leaks to sink.
|
|
func (l *EscLocation) leakTo(sink *EscLocation, derefs int) {
|
|
- // If sink is a result parameter and we can fit return bits
|
|
- // into the escape analysis tag, then record a return leak.
|
|
- if sink.isName(PPARAMOUT) && sink.curfn == l.curfn {
|
|
+ // If sink is a result parameter that doesn't escape (#44614)
|
|
+ // and we can fit return bits into the escape analysis tag,
|
|
+ // then record as a result leak.
|
|
+ if !sink.escapes && sink.isName(PPARAMOUT) && sink.curfn == l.curfn {
|
|
// TODO(mdempsky): Eliminate dependency on Vargen here.
|
|
ri := int(sink.n.Name.Vargen) - 1
|
|
if ri < numEscResults {
|
|
diff --git a/test/escape5.go b/test/escape5.go
|
|
index 061e57a069..145c5dd900 100644
|
|
--- a/test/escape5.go
|
|
+++ b/test/escape5.go
|
|
@@ -262,3 +262,14 @@ func f28369(n int) int {
|
|
|
|
return 1 + f28369(n-1)
|
|
}
|
|
+
|
|
+// Issue 44614: parameters that flow to a heap-allocated result
|
|
+// parameter must be recorded as a heap-flow rather than a
|
|
+// result-flow.
|
|
+
|
|
+// N.B., must match "leaking param: p",
|
|
+// but *not* "leaking param: p to result r level=0".
|
|
+func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r"
|
|
+ sink4 = &r
|
|
+ return p
|
|
+}
|
|
--
|
|
2.27.0
|
|
|