Commit afbe646a authored by Austin Clements's avatar Austin Clements

cmd/compile: report typedslicecopy write barriers

Most write barrier calls are inserted by SSA, but copy and append are
lowered to runtime.typedslicecopy during walk. Fix these to set
Func.WBPos and emit the "write barrier" warning, as done for the write
barriers inserted by SSA. As part of this, we refactor setting WBPos
and emitting this warning into the frontend so it can be shared by
both walk and SSA.

Change-Id: I5fe9997d9bdb55e03e01dd58aee28908c35f606b
Reviewed-on: https://go-review.googlesource.com/73411
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 507ca082
...@@ -136,11 +136,6 @@ func buildssa(fn *Node, worker int) *ssa.Func { ...@@ -136,11 +136,6 @@ func buildssa(fn *Node, worker int) *ssa.Func {
if fn.Func.Pragma&Nosplit != 0 { if fn.Func.Pragma&Nosplit != 0 {
s.f.NoSplit = true s.f.NoSplit = true
} }
defer func() {
if s.f.WBPos.IsKnown() {
fn.Func.WBPos = s.f.WBPos
}
}()
s.exitCode = fn.Func.Exit s.exitCode = fn.Func.Exit
s.panics = map[funcLine]*ssa.Block{} s.panics = map[funcLine]*ssa.Block{}
...@@ -5180,10 +5175,6 @@ func (e *ssafn) Debug_checknil() bool { ...@@ -5180,10 +5175,6 @@ func (e *ssafn) Debug_checknil() bool {
return Debug_checknil != 0 return Debug_checknil != 0
} }
func (e *ssafn) Debug_wb() bool {
return Debug_wb != 0
}
func (e *ssafn) UseWriteBarrier() bool { func (e *ssafn) UseWriteBarrier() bool {
return use_writebarrier return use_writebarrier
} }
...@@ -5205,6 +5196,10 @@ func (e *ssafn) Syslook(name string) *obj.LSym { ...@@ -5205,6 +5196,10 @@ func (e *ssafn) Syslook(name string) *obj.LSym {
return nil return nil
} }
func (e *ssafn) SetWBPos(pos src.XPos) {
e.curfn.Func.setWBPos(pos)
}
func (n *Node) Typ() *types.Type { func (n *Node) Typ() *types.Type {
return n.Type return n.Type
} }
......
...@@ -427,7 +427,7 @@ type Func struct { ...@@ -427,7 +427,7 @@ type Func struct {
Label int32 // largest auto-generated label in this function Label int32 // largest auto-generated label in this function
Endlineno src.XPos Endlineno src.XPos
WBPos src.XPos // position of first write barrier WBPos src.XPos // position of first write barrier; see SetWBPos
Pragma syntax.Pragma // go:xxx function annotations Pragma syntax.Pragma // go:xxx function annotations
...@@ -484,6 +484,15 @@ func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) } ...@@ -484,6 +484,15 @@ func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) } func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) } func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
func (f *Func) setWBPos(pos src.XPos) {
if Debug_wb != 0 {
Warnl(pos, "write barrier")
}
if !f.WBPos.IsKnown() {
f.WBPos = pos
}
}
type Op uint8 type Op uint8
// Node ops. // Node ops.
......
...@@ -2955,6 +2955,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2955,6 +2955,7 @@ func appendslice(n *Node, init *Nodes) *Node {
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
nptr1.Etype = 1 nptr1.Etype = 1
nptr2 := l2 nptr2 := l2
Curfn.Func.setWBPos(n.Pos)
fn := syslook("typedslicecopy") fn := syslook("typedslicecopy")
fn = substArgTypes(fn, l1.Type, l2.Type) fn = substArgTypes(fn, l1.Type, l2.Type)
var ln Nodes var ln Nodes
...@@ -3117,6 +3118,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { ...@@ -3117,6 +3118,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
// //
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 types.Haspointers(n.Left.Type.Elem()) {
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)
} }
......
...@@ -88,7 +88,6 @@ type Logger interface { ...@@ -88,7 +88,6 @@ type Logger interface {
// Forwards the Debug flags from gc // Forwards the Debug flags from gc
Debug_checknil() bool Debug_checknil() bool
Debug_wb() bool
} }
type Frontend interface { type Frontend interface {
...@@ -131,6 +130,10 @@ type Frontend interface { ...@@ -131,6 +130,10 @@ type Frontend interface {
// UseWriteBarrier returns whether write barrier is enabled // UseWriteBarrier returns whether write barrier is enabled
UseWriteBarrier() bool UseWriteBarrier() bool
// SetWBPos indicates that a write barrier has been inserted
// in this function at position pos.
SetWBPos(pos src.XPos)
} }
// interface used to hold a *gc.Node (a stack variable). // interface used to hold a *gc.Node (a stack variable).
......
...@@ -125,6 +125,8 @@ func (d DummyFrontend) Syslook(s string) *obj.LSym { ...@@ -125,6 +125,8 @@ func (d DummyFrontend) Syslook(s string) *obj.LSym {
func (DummyFrontend) UseWriteBarrier() bool { func (DummyFrontend) UseWriteBarrier() bool {
return true // only writebarrier_test cares return true // only writebarrier_test cares
} }
func (DummyFrontend) SetWBPos(pos src.XPos) {
}
func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) } func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
func (d DummyFrontend) Log() bool { return true } func (d DummyFrontend) Log() bool { return true }
...@@ -132,7 +134,6 @@ func (d DummyFrontend) Log() bool { return true } ...@@ -132,7 +134,6 @@ func (d DummyFrontend) Log() bool { return true }
func (d DummyFrontend) Fatalf(_ src.XPos, msg string, args ...interface{}) { d.t.Fatalf(msg, args...) } func (d DummyFrontend) Fatalf(_ src.XPos, msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
func (d DummyFrontend) Warnl(_ src.XPos, msg string, args ...interface{}) { d.t.Logf(msg, args...) } func (d DummyFrontend) Warnl(_ src.XPos, msg string, args ...interface{}) { d.t.Logf(msg, args...) }
func (d DummyFrontend) Debug_checknil() bool { return false } func (d DummyFrontend) Debug_checknil() bool { return false }
func (d DummyFrontend) Debug_wb() bool { return false }
var dummyTypes Types var dummyTypes Types
......
...@@ -44,8 +44,6 @@ type Func struct { ...@@ -44,8 +44,6 @@ type Func struct {
scheduled bool // Values in Blocks are in final order scheduled bool // Values in Blocks are in final order
NoSplit bool // true if function is marked as nosplit. Used by schedule check pass. NoSplit bool // true if function is marked as nosplit. Used by schedule check pass.
WBPos src.XPos // line number of first write barrier
// when register allocation is done, maps value ids to locations // when register allocation is done, maps value ids to locations
RegAlloc []Location RegAlloc []Location
......
...@@ -226,12 +226,7 @@ func writebarrier(f *Func) { ...@@ -226,12 +226,7 @@ func writebarrier(f *Func) {
if fn != nil { if fn != nil {
// Note that we set up a writebarrier function call. // Note that we set up a writebarrier function call.
if !f.WBPos.IsKnown() { f.fe.SetWBPos(pos)
f.WBPos = pos
}
if f.fe.Debug_wb() {
f.Warnl(pos, "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