aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2016-03-16 18:22:58 -0400
committerAustin Clements <austin@google.com>2016-03-16 22:42:45 +0000
commit3e54ca9a4624fda0bcd76192aa529e826ef12b4f (patch)
tree6a36221aef31071d3b57f24c5832c9d4e94fc170
parent4e75932cf7148c6ed10f93bbc07a79a7f89e8bd2 (diff)
downloadgo-3e54ca9a4624fda0bcd76192aa529e826ef12b4f.tar.xz
cmd/compile: omit write barrier when assigning global function
Currently we generate write barriers when the right side of an assignment is a global function. This doesn't fall into the existing case of storing an address of a global because we haven't lowered the function to a pointer yet. This write barrier is unnecessary, so eliminate it. Fixes #13901. Change-Id: Ibc10e00a8803db0fd75224b66ab94c3737842a79 Reviewed-on: https://go-review.googlesource.com/20772 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/walk.go6
-rw-r--r--test/writebarrier.go10
2 files changed, 16 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index b4c38ec12b..69c8390fe0 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -2140,6 +2140,12 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
+ // No write barrier for storing global function, which is live
+ // no matter what.
+ if r.Op == ONAME && r.Class == PFUNC {
+ return false
+ }
+
// Otherwise, be conservative and use write barrier.
return true
}
diff --git a/test/writebarrier.go b/test/writebarrier.go
index dcd20a0225..e591eaab32 100644
--- a/test/writebarrier.go
+++ b/test/writebarrier.go
@@ -158,3 +158,13 @@ func t1(i interface{}) **int {
}
return nil
}
+
+type T17 struct {
+ f func(*T17)
+}
+
+func f17(x *T17) {
+ // See golang.org/issue/13901
+ x.f = f17 // no barrier
+ x.f = func(y *T17) { *y = *x } // ERROR "write barrier"
+}