Skip to content

Commit 7015ed8

Browse files
mauri870gopherbot
authored andcommitted
sync: prevent (*Map).Range from always escaping
After the change from CL 426074 the Range method on Map always escape the read variable, leading to an allocation. Since the compiler doesn't do live-range splitting for local variables we need to use some hints to only escape in that particular branch. Fixes #62404 Change-Id: I938a5e593647455fa827e3dd3ed8ea22c7365df1 GitHub-Last-Rev: fcbedb4 GitHub-Pull-Request: #62408 Reviewed-on: https://go-review.googlesource.com/c/go/+/524976 Auto-Submit: Bryan Mills <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Run-TryBot: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 227ec02 commit 7015ed8

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

src/sync/map.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ func (m *Map) Range(f func(key, value any) bool) {
461461
read = m.loadReadOnly()
462462
if read.amended {
463463
read = readOnly{m: m.dirty}
464-
m.read.Store(&read)
464+
copyRead := read
465+
m.read.Store(&copyRead)
465466
m.dirty = nil
466467
m.misses = 0
467468
}

src/sync/map_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package sync_test
66

77
import (
8+
"internal/testenv"
89
"math/rand"
910
"reflect"
1011
"runtime"
@@ -280,3 +281,16 @@ func TestCompareAndSwap_NonExistingKey(t *testing.T) {
280281
t.Fatalf("CompareAndSwap on an non-existing key succeeded")
281282
}
282283
}
284+
285+
func TestMapRangeNoAllocations(t *testing.T) { // Issue 62404
286+
testenv.SkipIfOptimizationOff(t)
287+
var m sync.Map
288+
allocs := testing.AllocsPerRun(10, func() {
289+
m.Range(func(key, value any) bool {
290+
return true
291+
})
292+
})
293+
if allocs > 0 {
294+
t.Errorf("AllocsPerRun of m.Range = %v; want 0", allocs)
295+
}
296+
}

0 commit comments

Comments
 (0)