diff options
| author | Keith Randall <khr@golang.org> | 2024-11-23 17:35:02 -0800 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2025-02-13 14:08:14 -0800 |
| commit | 187fd2698d2f9fc2fc52aa7d4c0922552f848e98 (patch) | |
| tree | 5d0e7f24d705e201037a919179c2af61933aa77f /src | |
| parent | a0029e95e5d6f15cab70e533d447c75aa4211636 (diff) | |
| download | go-187fd2698d2f9fc2fc52aa7d4c0922552f848e98.tar.xz | |
cmd/compile: make write barrier code amenable to paired loads/stores
It currently isn't because it does load/store/load/store/...
Rework to do overwrite processing in pairs so it is instead
load/load/store/store/...
Change-Id: If7be629bc4048da5f2386dafb8f05759b79e9e2b
Reviewed-on: https://go-review.googlesource.com/c/go/+/631495
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/ssa/writebarrier.go | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 71acefbf8a..bf04f1b5c2 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -376,21 +376,6 @@ func writebarrier(f *Func) { // For each write barrier store, append write barrier code to bThen. memThen := mem - var curCall *Value - var curPtr *Value - addEntry := func(pos src.XPos, v *Value) { - if curCall == nil || curCall.AuxInt == maxEntries { - t := types.NewTuple(types.Types[types.TUINTPTR].PtrTo(), types.TypeMem) - curCall = bThen.NewValue1(pos, OpWB, t, memThen) - curPtr = bThen.NewValue1(pos, OpSelect0, types.Types[types.TUINTPTR].PtrTo(), curCall) - memThen = bThen.NewValue1(pos, OpSelect1, types.TypeMem, curCall) - } - // Store value in write buffer - num := curCall.AuxInt - curCall.AuxInt = num + 1 - wbuf := bThen.NewValue1I(pos, OpOffPtr, types.Types[types.TUINTPTR].PtrTo(), num*f.Config.PtrSize, curPtr) - memThen = bThen.NewValue3A(pos, OpStore, types.TypeMem, types.Types[types.TUINTPTR], wbuf, v, memThen) - } // Note: we can issue the write barrier code in any order. In particular, // it doesn't matter if they are in a different order *even if* they end @@ -410,6 +395,38 @@ func writebarrier(f *Func) { dsts := sset2 dsts.clear() + // Buffer up entries that we need to put in the write barrier buffer. + type write struct { + ptr *Value // value to put in write barrier buffer + pos src.XPos // location to use for the write + } + var writeStore [maxEntries]write + writes := writeStore[:0] + + flush := func() { + if len(writes) == 0 { + return + } + // Issue a call to get a write barrier buffer. + t := types.NewTuple(types.Types[types.TUINTPTR].PtrTo(), types.TypeMem) + call := bThen.NewValue1I(pos, OpWB, t, int64(len(writes)), memThen) + curPtr := bThen.NewValue1(pos, OpSelect0, types.Types[types.TUINTPTR].PtrTo(), call) + memThen = bThen.NewValue1(pos, OpSelect1, types.TypeMem, call) + // Write each pending pointer to a slot in the buffer. + for i, write := range writes { + wbuf := bThen.NewValue1I(write.pos, OpOffPtr, types.Types[types.TUINTPTR].PtrTo(), int64(i)*f.Config.PtrSize, curPtr) + memThen = bThen.NewValue3A(write.pos, OpStore, types.TypeMem, types.Types[types.TUINTPTR], wbuf, write.ptr, memThen) + } + writes = writes[:0] + } + addEntry := func(pos src.XPos, ptr *Value) { + writes = append(writes, write{ptr: ptr, pos: pos}) + if len(writes) == maxEntries { + flush() + } + } + + // Find all the pointers we need to write to the buffer. for _, w := range stores { if w.Op != OpStoreWB { continue @@ -437,7 +454,9 @@ func writebarrier(f *Func) { f.fe.Func().SetWBPos(pos) nWBops-- } + flush() + // Now do the rare cases, Zeros and Moves. for _, w := range stores { pos := w.Pos switch w.Op { |
