aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-06-29 12:49:25 -0400
committerRuss Cox <rsc@golang.org>2015-07-07 21:51:57 +0000
commit9f90f31c3a3ac8fc306bb63c0fd80299afcddbc2 (patch)
treec2ff9f6933d085a388bc5b78ccbdabcd65db02dd
parentd6e6baa702269ea6d2e61d4fa726bff48560c82c (diff)
downloadgo-9f90f31c3a3ac8fc306bb63c0fd80299afcddbc2.tar.gz
go-9f90f31c3a3ac8fc306bb63c0fd80299afcddbc2.zip
cmd/compile: allow static init for unsafe.Pointer(&x) where x is global
This avoids both a write barrier and then dynamic initialization globals of the form var x something var xp = unsafe.Pointer(&x) Using static initialization avoids emitting a relocation for &x, which helps cgo. Fixes #9411. Change-Id: I0dbf480859cce6ab57ab805d1b8609c45b48f156 Reviewed-on: https://go-review.googlesource.com/11693 Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Russ Cox <rsc@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/sinit.go8
-rw-r--r--src/cmd/compile/internal/gc/walk.go15
-rw-r--r--test/sinit.go5
3 files changed, 24 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index e1a99d4ca0..0ced4ef3b0 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -302,6 +302,10 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
orig := r
r = r.Name.Defn.Right
+ for r.Op == OCONVNOP {
+ r = r.Left
+ }
+
switch r.Op {
case ONAME:
if staticcopy(l, r, out) {
@@ -395,6 +399,10 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
func staticassign(l *Node, r *Node, out **NodeList) bool {
var n1 Node
+ for r.Op == OCONVNOP {
+ r = r.Left
+ }
+
switch r.Op {
//dump("not static", r);
default:
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 626b26fec7..d89d25efdd 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -2194,13 +2194,20 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
- // No write barrier for implicit or explicit zeroing.
- if r == nil || iszero(r) {
+ // No write barrier for implicit zeroing.
+ if r == nil {
return false
}
- // No write barrier for initialization to constant.
- if r.Op == OLITERAL {
+ // Ignore no-op conversions when making decision.
+ // Ensures that xp = unsafe.Pointer(&x) is treated
+ // the same as xp = &x.
+ for r.Op == OCONVNOP {
+ r = r.Left
+ }
+
+ // No write barrier for zeroing or initialization to constant.
+ if iszero(r) || r.Op == OLITERAL {
return false
}
diff --git a/test/sinit.go b/test/sinit.go
index df1a4cc930..188a5301a2 100644
--- a/test/sinit.go
+++ b/test/sinit.go
@@ -10,6 +10,8 @@
package p
+import "unsafe"
+
// Should be no init func in the assembly.
// All these initializations should be done at link time.
@@ -284,3 +286,6 @@ type Mer interface {
}
var _ Mer = (*T1)(nil)
+
+var Byte byte
+var PtrByte unsafe.Pointer = unsafe.Pointer(&Byte)