1
0
mirror of https://github.com/golang/go synced 2024-11-22 13:54:45 -07:00

cmd/compile: enforce nowritebarrier in SSA compiler

Make sure we don't generate write barriers in runtime
code that is marked to forbid write barriers.

Implement the optimization that if we're writing a sliced
slice back to the location it came from, we don't need a
write barrier.

Fixes #14784

Change-Id: I04b6a3b2ac303c19817e932a36a3b006de103aaa
Reviewed-on: https://go-review.googlesource.com/20791
Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
Keith Randall 2016-03-16 21:51:17 -07:00
parent 16029babe2
commit 15ed37d7b7
3 changed files with 43 additions and 0 deletions

View File

@ -96,6 +96,14 @@ func buildssa(fn *Node) *ssa.Func {
if fn.Func.Pragma&CgoUnsafeArgs != 0 {
s.cgoUnsafeArgs = true
}
if fn.Func.Pragma&Nowritebarrier != 0 {
s.noWB = true
}
defer func() {
if s.WBLineno != 0 {
fn.Func.WBLineno = s.WBLineno
}
}()
// TODO(khr): build config just once at the start of the compiler binary
ssaExp.log = printssa
@ -271,6 +279,8 @@ type state struct {
returns []*Node
cgoUnsafeArgs bool
noWB bool
WBLineno int32 // line number of first write barrier. 0=no write barriers
}
type funcLine struct {
@ -2780,6 +2790,13 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32) {
// } else {
// *left = *right
// }
if s.noWB {
s.Fatalf("write barrier prohibited")
}
if s.WBLineno == 0 {
s.WBLineno = left.Line
}
bThen := s.f.NewBlock(ssa.BlockPlain)
bElse := s.f.NewBlock(ssa.BlockPlain)
bEnd := s.f.NewBlock(ssa.BlockPlain)
@ -2823,6 +2840,12 @@ func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line int32) {
// store pointer fields
// }
if s.noWB {
s.Fatalf("write barrier prohibited")
}
if s.WBLineno == 0 {
s.WBLineno = left.Line
}
s.storeTypeScalars(t, left, right)
bThen := s.f.NewBlock(ssa.BlockPlain)

View File

@ -2146,6 +2146,13 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
// No write barrier for writing a sliced slice back to its
// original location.
if (r.Op == OSLICE || r.Op == OSLICE3 || r.Op == OSLICESTR) &&
samesafeexpr(r.Left, l) {
return false
}
// Otherwise, be conservative and use write barrier.
return true
}

View File

@ -168,3 +168,16 @@ func f17(x *T17) {
x.f = f17 // no barrier
x.f = func(y *T17) { *y = *x } // ERROR "write barrier"
}
type T18 struct {
a []int
s string
}
func f18(p *T18, x *[]int) {
p.a = p.a[:5] // no barrier
p.a = p.a[3:5] // no barrier
p.a = p.a[1:2:3] // no barrier
p.s = p.s[8:9] // no barrier
*x = (*x)[3:5] // no barrier
}