]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: allow non-pointer writes in the middle of a write barrier
authorKeith Randall <khr@golang.org>
Fri, 18 Aug 2023 19:44:37 +0000 (12:44 -0700)
committerKeith Randall <khr@golang.org>
Wed, 23 Aug 2023 00:16:06 +0000 (00:16 +0000)
This lets us combine more write barriers, getting rid of some of the
test+branch and gcWriteBarrier* calls.
With the new write barriers, it's easy to add a few non-pointer writes
to the set of values written.

We allow up to 2 non-pointer writes between pointer writes. This is enough
for, for example, adjacent slice fields.

Fixes #62126

Change-Id: I872d0fa9cc4eb855e270ffc0223b39fde1723c4b
Reviewed-on: https://go-review.googlesource.com/c/go/+/521498
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/ssa/writebarrier.go
test/codegen/writebarrier.go [new file with mode: 0644]

index 294306d8c268015705cc2b574fad5c82ef0a97e5..010e59ef43e0d9fd9fa96b7205c720229855aeab 100644 (file)
@@ -250,6 +250,7 @@ func writebarrier(f *Func) {
                // to a new block.
                var last *Value
                var start, end int
+               var nonPtrStores int
                values := b.Values
        FindSeq:
                for i := len(values) - 1; i >= 0; i-- {
@@ -261,8 +262,17 @@ func writebarrier(f *Func) {
                                        last = w
                                        end = i + 1
                                }
+                               nonPtrStores = 0
                        case OpVarDef, OpVarLive:
                                continue
+                       case OpStore:
+                               if last == nil {
+                                       continue
+                               }
+                               nonPtrStores++
+                               if nonPtrStores > 2 {
+                                       break FindSeq
+                               }
                        default:
                                if last == nil {
                                        continue
@@ -484,6 +494,10 @@ func writebarrier(f *Func) {
                                mem.Aux = w.Aux
                        case OpVarDef, OpVarLive:
                                mem = bEnd.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, mem)
+                       case OpStore:
+                               ptr := w.Args[0]
+                               val := w.Args[1]
+                               mem = bEnd.NewValue3A(pos, OpStore, types.TypeMem, w.Aux, ptr, val, mem)
                        }
                }
 
diff --git a/test/codegen/writebarrier.go b/test/codegen/writebarrier.go
new file mode 100644 (file)
index 0000000..cfcfe15
--- /dev/null
@@ -0,0 +1,55 @@
+// asmcheck
+
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+func combine2string(p *[2]string, a, b string) {
+       // amd64:`.*runtime[.]gcWriteBarrier4\(SB\)`
+       // arm64:`.*runtime[.]gcWriteBarrier4\(SB\)`
+       p[0] = a
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[1] = b
+}
+
+func combine4string(p *[4]string, a, b, c, d string) {
+       // amd64:`.*runtime[.]gcWriteBarrier8\(SB\)`
+       // arm64:`.*runtime[.]gcWriteBarrier8\(SB\)`
+       p[0] = a
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[1] = b
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[2] = c
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[3] = d
+}
+
+func combine2slice(p *[2][]byte, a, b []byte) {
+       // amd64:`.*runtime[.]gcWriteBarrier4\(SB\)`
+       // arm64:`.*runtime[.]gcWriteBarrier4\(SB\)`
+       p[0] = a
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[1] = b
+}
+
+func combine4slice(p *[4][]byte, a, b, c, d []byte) {
+       // amd64:`.*runtime[.]gcWriteBarrier8\(SB\)`
+       // arm64:`.*runtime[.]gcWriteBarrier8\(SB\)`
+       p[0] = a
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[1] = b
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[2] = c
+       // amd64:-`.*runtime[.]gcWriteBarrier`
+       // arm64:-`.*runtime[.]gcWriteBarrier`
+       p[3] = d
+}