Commit 94ff311d authored by Rémy Oudompheng's avatar Rémy Oudompheng Committed by Luuk van Dijk

gc: avoid false positives when using scalar struct fields.

The escape analysis code does not make a distinction between
scalar and pointers fields in structs. Non-pointer fields
that escape should not make the whole struct escape.

R=lvd, rsc
CC=golang-dev, remy
https://golang.org/cl/5489128
parent e955a3cc
...@@ -469,10 +469,14 @@ escassign(Node *dst, Node *src) ...@@ -469,10 +469,14 @@ escassign(Node *dst, Node *src)
escflows(dst, src); escflows(dst, src);
break; break;
case ODOT:
// A non-pointer escaping from a struct does not concern us.
if(src->type && !haspointers(src->type))
break;
// fallthrough
case OCONV: case OCONV:
case OCONVIFACE: case OCONVIFACE:
case OCONVNOP: case OCONVNOP:
case ODOT:
case ODOTMETH: // treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC case ODOTMETH: // treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
// iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here // iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
case ODOTTYPE: case ODOTTYPE:
......
...@@ -126,10 +126,36 @@ func (b *Bar) NoLeak() int { // ERROR "b does not escape" ...@@ -126,10 +126,36 @@ func (b *Bar) NoLeak() int { // ERROR "b does not escape"
return *(b.ii) return *(b.ii)
} }
func (b *Bar) Leak() *int { // ERROR "leaking param: b"
return &b.i // ERROR "&b.i escapes to heap"
}
func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape" func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape"
return b.ii return b.ii
} }
func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
return b.ii
}
func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
v := 0 // ERROR "moved to heap: v"
b.ii = &v // ERROR "&v escapes"
return b.ii
}
func (b *Bar) LeaksABit() *int { // ERROR "b does not escape"
v := 0 // ERROR "moved to heap: v"
b.ii = &v // ERROR "&v escapes"
return b.ii
}
func (b Bar) StillNoLeak() int { // ERROR "b does not escape"
v := 0
b.ii = &v // ERROR "&v does not escape"
return b.i
}
func goLeak(b *Bar) { // ERROR "leaking param: b" func goLeak(b *Bar) { // ERROR "leaking param: b"
go b.NoLeak() go b.NoLeak()
} }
...@@ -148,20 +174,24 @@ func (b *Bar2) NoLeak() int { // ERROR "b does not escape" ...@@ -148,20 +174,24 @@ func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
} }
func (b *Bar2) Leak() []int { // ERROR "leaking param: b" func (b *Bar2) Leak() []int { // ERROR "leaking param: b"
return b.i[:] // ERROR "b.i escapes to heap" return b.i[:] // ERROR "b.i escapes to heap"
} }
func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape" func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape"
return b.ii[0:1] return b.ii[0:1]
} }
func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape"
return b.i
}
func (b *Bar2) LeakSelf() { // ERROR "leaking param: b" func (b *Bar2) LeakSelf() { // ERROR "leaking param: b"
b.ii = b.i[0:4] // ERROR "b.i escapes to heap" b.ii = b.i[0:4] // ERROR "b.i escapes to heap"
} }
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b" func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b"
var buf []int var buf []int
buf = b.i[0:] // ERROR "b.i escapes to heap" buf = b.i[0:] // ERROR "b.i escapes to heap"
b.ii = buf b.ii = buf
} }
...@@ -1018,7 +1048,7 @@ func foo122() { ...@@ -1018,7 +1048,7 @@ func foo122() {
goto L1 goto L1
L1: L1:
i = new(int) // ERROR "does not escape" i = new(int) // ERROR "does not escape"
_ = i _ = i
} }
...@@ -1027,8 +1057,8 @@ func foo123() { ...@@ -1027,8 +1057,8 @@ func foo123() {
var i *int var i *int
L1: L1:
i = new(int) // ERROR "escapes" i = new(int) // ERROR "escapes"
goto L1 goto L1
_ = i _ = i
} }
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment