mirror of
https://github.com/golang/go
synced 2024-09-29 01:14:29 -06:00
cmd/compile: allow non-pointer writes in the middle of a write barrier
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>
This commit is contained in:
parent
0163b3b32c
commit
556e9c5f3e
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
55
test/codegen/writebarrier.go
Normal file
55
test/codegen/writebarrier.go
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user