reflect: mark mapassign as noescape

The lack of this annotation causes Value.SetMapIndex to allocate
when it doesn't need to.

Add comments about why it's safe to do so.

Add a test to make sure we stay allocation-free.

Change-Id: I00826e0d73e317a31bdeae5c7e46bf95b0c6ae6a
Reviewed-on: https://go-review.googlesource.com/17060
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2015-11-18 11:13:19 -08:00
parent 476aa95015
commit 8d31a86a1e
2 changed files with 44 additions and 7 deletions

View file

@ -4965,3 +4965,32 @@ func TestPtrToMethods(t *testing.T) {
t.Fatal("does not implement Stringer, but should")
}
}
func TestMapAlloc(t *testing.T) {
m := ValueOf(make(map[int]int, 10))
k := ValueOf(5)
v := ValueOf(7)
allocs := testing.AllocsPerRun(100, func() {
m.SetMapIndex(k, v)
})
if allocs > 0.5 {
t.Errorf("allocs per map assignment: want 0 got %f", allocs)
}
}
func TestChanAlloc(t *testing.T) {
// Note: for a chan int, the return Value must be allocated, so we
// use a chan *int instead.
c := ValueOf(make(chan *int, 1))
v := ValueOf(new(int))
allocs := testing.AllocsPerRun(100, func() {
c.Send(v)
_, _ = c.Recv()
})
if allocs < 0.5 || allocs > 1.5 {
t.Errorf("allocs per chan send/recv: want 1 got %f", allocs)
}
// Note: there is one allocation in reflect.recv which seems to be
// a limitation of escape analysis. If that is ever fixed the
// allocs < 0.5 condition will trigger and this test should be fixed.
}