aboutsummaryrefslogtreecommitdiff
path: root/test/escape_param.go
diff options
context:
space:
mode:
authorIskander Sharipov <iskander.sharipov@intel.com>2018-07-27 19:32:17 +0300
committerIskander Sharipov <iskander.sharipov@intel.com>2018-09-03 14:28:51 +0000
commitff468a43be1740890a0f3b64a6ab920ea92c2c17 (patch)
tree2675b9edeecf9bb8180fb3b67761fe098e83930d /test/escape_param.go
parentb794ca64d29f3e584cbdf49bde7141d3c12dd2ab (diff)
downloadgo-ff468a43be1740890a0f3b64a6ab920ea92c2c17.tar.gz
go-ff468a43be1740890a0f3b64a6ab920ea92c2c17.zip
cmd/compile/internal/gc: better handling of self-assignments in esc.go
Teach escape analysis to recognize these assignment patterns as not causing the src to leak: val.x = val.y val.x[i] = val.y[j] val.x1.x2 = val.x1.y2 ... etc Helps to avoid "leaking param" with assignments showed above. The implementation is based on somewhat similiar xs=xs[a:b] special case that is ignored by the escape analysis. We may figure out more generalized version of this, but this one looks like a safe step into that direction. Updates #14858 Change-Id: I6fe5bfedec9c03bdc1d7624883324a523bd11fde Reviewed-on: https://go-review.googlesource.com/126395 Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'test/escape_param.go')
-rw-r--r--test/escape_param.go75
1 files changed, 70 insertions, 5 deletions
diff --git a/test/escape_param.go b/test/escape_param.go
index 2c43b96ba0..4eb96dff9b 100644
--- a/test/escape_param.go
+++ b/test/escape_param.go
@@ -58,20 +58,85 @@ func caller2b() {
sink = p // ERROR "p escapes to heap$"
}
+func paramArraySelfAssign(p *PairOfPairs) { // ERROR "p does not escape"
+ p.pairs[0] = p.pairs[1] // ERROR "ignoring self-assignment in p.pairs\[0\] = p.pairs\[1\]"
+}
+
+type PairOfPairs struct {
+ pairs [2]*Pair
+}
+
+type BoxedPair struct {
+ pair *Pair
+}
+
+type WrappedPair struct {
+ pair Pair
+}
+
+func leakParam(x interface{}) { // ERROR "leaking param: x"
+ sink = x
+}
+
+func sinkAfterSelfAssignment1(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ sink = box.pair.p2 // ERROR "box.pair.p2 escapes to heap"
+}
+
+func sinkAfterSelfAssignment2(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ sink = box.pair // ERROR "box.pair escapes to heap"
+}
+
+func sinkAfterSelfAssignment3(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ leakParam(box.pair.p2) // ERROR "box.pair.p2 escapes to heap"
+}
+
+func sinkAfterSelfAssignment4(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ leakParam(box.pair) // ERROR "box.pair escapes to heap"
+}
+
+func selfAssignmentAndUnrelated(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
+ box1.pair.p1 = box1.pair.p2 // ERROR "ignoring self-assignment in box1.pair.p1 = box1.pair.p2"
+ leakParam(box2.pair.p2) // ERROR "box2.pair.p2 escapes to heap"
+}
+
+func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
+ box1.pair.p1 = box2.pair.p1
+}
+
+func notSelfAssignment2(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
+ p1.pairs[0] = p2.pairs[1]
+}
+
+func notSelfAssignment3(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
+ p1.pairs[0].p1 = p2.pairs[1].p1
+}
+
+func boxedPairSelfAssign(box *BoxedPair) { // ERROR "box does not escape"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+}
+
+func wrappedPairSelfAssign(w *WrappedPair) { // ERROR "w does not escape"
+ w.pair.p1 = w.pair.p2 // ERROR "ignoring self-assignment in w.pair.p1 = w.pair.p2"
+}
+
// in -> in
type Pair struct {
p1 *int
p2 *int
}
-func param3(p *Pair) { // ERROR "leaking param content: p$"
- p.p1 = p.p2
+func param3(p *Pair) { // ERROR "param3 p does not escape"
+ p.p1 = p.p2 // ERROR "param3 ignoring self-assignment in p.p1 = p.p2"
}
func caller3a() {
- i := 0 // ERROR "moved to heap: i$"
- j := 0 // ERROR "moved to heap: j$"
- p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
+ i := 0
+ j := 0
+ p := Pair{&i, &j} // ERROR "caller3a &i does not escape" "caller3a &j does not escape"
param3(&p) // ERROR "caller3a &p does not escape"
_ = p
}