]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: elide write barriers for copy of notinheap pointers
authorAustin Clements <austin@google.com>
Tue, 24 Oct 2017 21:11:32 +0000 (17:11 -0400)
committerAustin Clements <austin@google.com>
Sun, 29 Oct 2017 20:21:49 +0000 (20:21 +0000)
Currently copy and append for types containing only scalars and
notinheap pointers still get compiled to have write barriers, even
though those write barriers are unnecessary. Fix these to use
HasHeapPointer instead of just Haspointer so that they elide write
barriers when possible.

This fixes the unnecessary write barrier in runtime.recordspan when it
grows the h.allspans slice. This is important because recordspan gets
called (*very* indirectly) from (*gcWork).tryGet, which is
go:nowritebarrierrec. Unfortunately, the compiler's analysis has no
hope of seeing this because it goes through the indirect call
fixalloc.first, but I saw it happen.

Change-Id: Ieba3abc555a45f573705eab780debcfe5c4f5dd1
Reviewed-on: https://go-review.googlesource.com/73413
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/walk.go
test/notinheap3.go

index 3139404b1ec9cf0f03a66ac46cbb77f6ecb30cfc..0f75473b3f18c9239edea74c9b2a73811faebee7 100644 (file)
@@ -2949,7 +2949,7 @@ func appendslice(n *Node, init *Nodes) *Node {
        nt.Etype = 1
        l = append(l, nod(OAS, s, nt))
 
-       if types.Haspointers(l1.Type.Elem()) {
+       if l1.Type.Elem().HasHeapPointer() {
                // copy(s[len(l1):], l2)
                nptr1 := nod(OSLICE, s, nil)
                nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
@@ -3117,7 +3117,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
 // Also works if b is a string.
 //
 func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
-       if types.Haspointers(n.Left.Type.Elem()) {
+       if n.Left.Type.Elem().HasHeapPointer() {
                Curfn.Func.setWBPos(n.Pos)
                fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
                return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), n.Left, n.Right)
index e01c7a0a82d79ade59759084f21199ec130ad36e..b37d73df6dd9fe0e7e6fd58f7821a759057ea277 100644 (file)
@@ -30,6 +30,9 @@ type ih struct { // In-heap type
 var (
        v1 t1
        v2 t2
+
+       v1s []t1
+       v2s []t2
 )
 
 func f() {
@@ -43,3 +46,11 @@ func g() {
        v1 = t1{x: nil} // no barrier
        v2 = t2{x: nil} // ERROR "write barrier"
 }
+
+func h() {
+       // Test copies and appends.
+       copy(v1s, v1s[1:])      // no barrier
+       copy(v2s, v2s[1:])      // ERROR "write barrier"
+       _ = append(v1s, v1s...) // no barrier
+       _ = append(v2s, v2s...) // ERROR "write barrier"
+}