1
0
mirror of https://github.com/golang/go synced 2024-11-22 19:05:01 -07:00

cmd/compile: disable various write barrier optimizations

Several of our current write barrier elision optimizations are invalid
with the hybrid barrier. Eliding the hybrid barrier requires that
*both* the current and new pointer be already shaded and, since we
don't have the flow analysis to figure out anything about the slot's
current value, for now we have to just disable several of these
optimizations.

This has a slight impact on binary size. On linux/amd64, the go tool
binary increases by 0.7% and the compile binary increases by 1.5%.

It also has a slight impact on performance, as one would expect. We'll
win some of this back in subsequent commits.

name                      old time/op    new time/op    delta
BinaryTree17-12              2.38s ± 1%     2.40s ± 1%  +0.82%  (p=0.000 n=18+20)
Fannkuch11-12                2.84s ± 1%     2.70s ± 0%  -4.97%  (p=0.000 n=18+18)
FmtFprintfEmpty-12          44.2ns ± 1%    46.4ns ± 2%  +4.89%  (p=0.000 n=16+18)
FmtFprintfString-12          131ns ± 0%     134ns ± 1%  +2.05%  (p=0.000 n=12+19)
FmtFprintfInt-12             114ns ± 1%     117ns ± 1%  +3.26%  (p=0.000 n=19+20)
FmtFprintfIntInt-12          176ns ± 1%     181ns ± 1%  +3.25%  (p=0.000 n=20+20)
FmtFprintfPrefixedInt-12     185ns ± 1%     190ns ± 1%  +2.77%  (p=0.000 n=19+18)
FmtFprintfFloat-12           249ns ± 1%     254ns ± 1%  +1.71%  (p=0.000 n=18+20)
FmtManyArgs-12               747ns ± 1%     743ns ± 1%  -0.58%  (p=0.000 n=19+18)
GobDecode-12                6.57ms ± 1%    6.61ms ± 0%  +0.73%  (p=0.000 n=19+20)
GobEncode-12                5.58ms ± 1%    5.60ms ± 0%  +0.27%  (p=0.001 n=18+18)
Gzip-12                      223ms ± 1%     223ms ± 1%    ~     (p=0.351 n=19+20)
Gunzip-12                   37.9ms ± 0%    37.9ms ± 1%    ~     (p=0.095 n=16+20)
HTTPClientServer-12         77.8µs ± 1%    78.5µs ± 1%  +0.97%  (p=0.000 n=19+20)
JSONEncode-12               14.8ms ± 1%    14.8ms ± 1%    ~     (p=0.079 n=20+19)
JSONDecode-12               53.7ms ± 1%    54.2ms ± 1%  +0.92%  (p=0.000 n=20+19)
Mandelbrot200-12            3.81ms ± 1%    3.81ms ± 0%    ~     (p=0.916 n=19+18)
GoParse-12                  3.19ms ± 1%    3.19ms ± 1%    ~     (p=0.175 n=20+19)
RegexpMatchEasy0_32-12      71.9ns ± 1%    70.6ns ± 1%  -1.87%  (p=0.000 n=19+20)
RegexpMatchEasy0_1K-12       946ns ± 0%     944ns ± 0%  -0.22%  (p=0.000 n=19+16)
RegexpMatchEasy1_32-12      67.3ns ± 2%    66.8ns ± 1%  -0.72%  (p=0.008 n=20+20)
RegexpMatchEasy1_1K-12       374ns ± 1%     384ns ± 1%  +2.69%  (p=0.000 n=18+20)
RegexpMatchMedium_32-12      107ns ± 1%     107ns ± 1%    ~     (p=1.000 n=20+20)
RegexpMatchMedium_1K-12     34.3µs ± 1%    34.6µs ± 1%  +0.90%  (p=0.000 n=20+20)
RegexpMatchHard_32-12       1.78µs ± 1%    1.80µs ± 1%  +1.45%  (p=0.000 n=20+19)
RegexpMatchHard_1K-12       53.6µs ± 0%    54.5µs ± 1%  +1.52%  (p=0.000 n=19+18)
Revcomp-12                   417ms ± 5%     391ms ± 1%  -6.42%  (p=0.000 n=16+19)
Template-12                 61.1ms ± 1%    64.2ms ± 0%  +5.07%  (p=0.000 n=19+20)
TimeParse-12                 302ns ± 1%     305ns ± 1%  +0.90%  (p=0.000 n=18+18)
TimeFormat-12                319ns ± 1%     315ns ± 1%  -1.25%  (p=0.000 n=18+18)
[Geo mean]                  54.0µs         54.3µs       +0.58%

name         old time/op  new time/op  delta
XGarbage-12  2.24ms ± 2%  2.28ms ± 1%  +1.68%  (p=0.000 n=18+17)
XHTTP-12     11.4µs ± 1%  11.6µs ± 2%  +1.63%  (p=0.000 n=18+18)
XJSON-12     11.6ms ± 0%  12.5ms ± 0%  +7.84%  (p=0.000 n=18+17)

Updates #17503.

Change-Id: I1899f8e35662971e24bf692b517dfbe2b533c00c
Reviewed-on: https://go-review.googlesource.com/31572
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Austin Clements 2016-10-18 10:26:28 -04:00
parent c3163d23f0
commit c39918a049
5 changed files with 30 additions and 34 deletions

View File

@ -423,7 +423,7 @@ func ordermapassign(n *Node, order *Order) {
// We call writebarrierfat only for values > 4 pointers long. See walk.go.
// TODO(mdempsky): writebarrierfat doesn't exist anymore, but removing that
// logic causes net/http's tests to become flaky; see CL 21242.
if needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr) && !isaddrokay(n.Right) {
if needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr) && n.Right != nil && !isaddrokay(n.Right) {
m := n.Left
n.Left = ordertemp(m.Type, order, false)
a := nod(OAS, m, n.Left)

View File

@ -750,8 +750,13 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes)
switch kind {
case initKindStatic:
a = walkexpr(a, init) // add any assignments in r to top
if a.Op == OASWB {
// Static initialization never needs
// write barriers.
a.Op = OAS
}
if a.Op != OAS {
Fatalf("fixedlit: not as")
Fatalf("fixedlit: not as, is %v", a)
}
a.IsStatic = true
case initKindDynamic, initKindLocalCode:

View File

@ -721,7 +721,8 @@ opswitch:
break
}
if n.Right == nil || iszero(n.Right) && !instrumenting {
if n.Right == nil {
// TODO(austin): Check all "implicit zeroing"
break
}
@ -2255,17 +2256,20 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
// No write barrier for implicit zeroing.
if r == nil {
return false
}
// No write barrier if this is a pointer to a go:notinheap
// type, since the write barrier's inheap(ptr) check will fail.
if l.Type.IsPtr() && l.Type.Elem().NotInHeap {
return false
}
// Implicit zeroing is still zeroing, so it needs write
// barriers. In practice, these are all to stack variables
// (even if isstack isn't smart enough to figure that out), so
// they'll be eliminated by the backend.
if r == nil {
return true
}
// Ignore no-op conversions when making decision.
// Ensures that xp = unsafe.Pointer(&x) is treated
// the same as xp = &x.
@ -2273,15 +2277,13 @@ func needwritebarrier(l *Node, r *Node) bool {
r = r.Left
}
// No write barrier for zeroing or initialization to constant.
if iszero(r) || r.Op == OLITERAL {
return false
}
// No write barrier for storing static (read-only) data.
if r.Op == ONAME && strings.HasPrefix(r.Sym.Name, "statictmp_") {
return false
}
// TODO: We can eliminate write barriers if we know *both* the
// current and new content of the slot must already be shaded.
// We know a pointer is shaded if it's nil, or points to
// static data, a global (variable or function), or the stack.
// The nil optimization could be particularly useful for
// writes to just-allocated objects. Unfortunately, knowing
// the "current" value of the slot requires flow analysis.
// No write barrier for storing address of stack values,
// which are guaranteed only to be written to the stack.
@ -2289,18 +2291,6 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
// No write barrier for storing address of global, which
// is live no matter what.
if r.Op == OADDR && r.Left.isGlobal() {
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
}

View File

@ -34,7 +34,7 @@ func f1(q *Q, xx []byte) interface{} { // ERROR "live at entry to f1: xx" "live
//go:noinline
func f2(d []byte, n int) (odata, res []byte, e interface{}) { // ERROR "live at entry to f2: d"
if n > len(d) {
return d, nil, &T{M: "hello"} // ERROR "live at call to newobject: d"
return d, nil, &T{M: "hello"} // ERROR "live at call to newobject: d" "live at call to writebarrierptr: d"
}
res = d[:n]
odata = d[n:]

View File

@ -164,8 +164,9 @@ type T17 struct {
}
func f17(x *T17) {
// See golang.org/issue/13901
x.f = f17 // no barrier
// Originally from golang.org/issue/13901, but the hybrid
// barrier requires both to have barriers.
x.f = f17 // ERROR "write barrier"
x.f = func(y *T17) { *y = *x } // ERROR "write barrier"
}
@ -207,8 +208,8 @@ func f21(x *int) {
// Global -> heap pointer updates must have write barriers.
x21 = x // ERROR "write barrier"
y21.x = x // ERROR "write barrier"
x21 = &z21 // no barrier
y21.x = &z21 // no barrier
x21 = &z21 // ERROR "write barrier"
y21.x = &z21 // ERROR "write barrier"
y21 = struct{ x *int }{x} // ERROR "write barrier"
}