Commit b78b54ff authored by Austin Clements's avatar Austin Clements

cmd/compile: elide write barriers for copy of notinheap pointers

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: default avatarMatthew Dempsky <mdempsky@google.com>
parent 316e3036
...@@ -2949,7 +2949,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2949,7 +2949,7 @@ func appendslice(n *Node, init *Nodes) *Node {
nt.Etype = 1 nt.Etype = 1
l = append(l, nod(OAS, s, nt)) l = append(l, nod(OAS, s, nt))
if types.Haspointers(l1.Type.Elem()) { if l1.Type.Elem().HasHeapPointer() {
// copy(s[len(l1):], l2) // copy(s[len(l1):], l2)
nptr1 := nod(OSLICE, s, nil) nptr1 := nod(OSLICE, s, nil)
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
...@@ -3117,7 +3117,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { ...@@ -3117,7 +3117,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
// Also works if b is a string. // Also works if b is a string.
// //
func copyany(n *Node, init *Nodes, runtimecall bool) *Node { 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) Curfn.Func.setWBPos(n.Pos)
fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type) fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), n.Left, n.Right) return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), n.Left, n.Right)
......
...@@ -30,6 +30,9 @@ type ih struct { // In-heap type ...@@ -30,6 +30,9 @@ type ih struct { // In-heap type
var ( var (
v1 t1 v1 t1
v2 t2 v2 t2
v1s []t1
v2s []t2
) )
func f() { func f() {
...@@ -43,3 +46,11 @@ func g() { ...@@ -43,3 +46,11 @@ func g() {
v1 = t1{x: nil} // no barrier v1 = t1{x: nil} // no barrier
v2 = t2{x: nil} // ERROR "write 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"
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment