diff options
author | Iskander Sharipov <iskander.sharipov@intel.com> | 2018-07-27 19:32:17 +0300 |
---|---|---|
committer | Iskander Sharipov <iskander.sharipov@intel.com> | 2018-09-03 14:28:51 +0000 |
commit | ff468a43be1740890a0f3b64a6ab920ea92c2c17 (patch) | |
tree | 2675b9edeecf9bb8180fb3b67761fe098e83930d /test/escape_param.go | |
parent | b794ca64d29f3e584cbdf49bde7141d3c12dd2ab (diff) | |
download | go-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.go | 75 |
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 } |