]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: enforce nowritebarrier in SSA compiler
authorKeith Randall <khr@golang.org>
Thu, 17 Mar 2016 04:51:17 +0000 (21:51 -0700)
committerKeith Randall <khr@golang.org>
Thu, 17 Mar 2016 20:13:24 +0000 (20:13 +0000)
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>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/walk.go
test/writebarrier.go

index b0c7c5f5b3c9fcd52de6a8f3a66f3e451598ffe7..1d3c1f6dffa80e9fb30b37933f256c7540d5bd24 100644 (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)
index 6d136f6272df113d6647372efbac82dfd603bc89..3b3645784fe12dfc8b43aa04ebbe437748282273 100644 (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
 }
index e591eaab32b642eaadafef8ac00b0f0d961ac5e3..75107287b49ee70a8e51f524f146447bc619cee9 100644 (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
+}