aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa')
-rw-r--r--src/cmd/compile/internal/ssa/_gen/genericOps.go1
-rw-r--r--src/cmd/compile/internal/ssa/deadcode.go14
-rw-r--r--src/cmd/compile/internal/ssa/func.go6
-rw-r--r--src/cmd/compile/internal/ssa/lower.go2
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go6
-rw-r--r--src/cmd/compile/internal/ssa/writebarrier.go35
6 files changed, 17 insertions, 47 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/genericOps.go b/src/cmd/compile/internal/ssa/_gen/genericOps.go
index 6ecccc3e92..deb2cb8bd5 100644
--- a/src/cmd/compile/internal/ssa/_gen/genericOps.go
+++ b/src/cmd/compile/internal/ssa/_gen/genericOps.go
@@ -379,6 +379,7 @@ var genericOps = []opData{
{name: "StoreWB", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory.
{name: "MoveWB", argLength: 3, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size, aux=type. Returns memory.
{name: "ZeroWB", argLength: 2, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=mem, auxint=size, aux=type. Returns memory.
+ {name: "WBend", argLength: 1, typ: "Mem"}, // Write barrier code is done, interrupting is now allowed.
// WB invokes runtime.gcWriteBarrier. This is not a normal
// call: it takes arguments in registers, doesn't clobber
diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
index cfadda82b0..bd4282ecdb 100644
--- a/src/cmd/compile/internal/ssa/deadcode.go
+++ b/src/cmd/compile/internal/ssa/deadcode.go
@@ -290,20 +290,6 @@ func deadcode(f *Func) {
b.truncateValues(i)
}
- // Remove dead blocks from WBLoads list.
- i = 0
- for _, b := range f.WBLoads {
- if reachable[b.ID] {
- f.WBLoads[i] = b
- i++
- }
- }
- clearWBLoads := f.WBLoads[i:]
- for j := range clearWBLoads {
- clearWBLoads[j] = nil
- }
- f.WBLoads = f.WBLoads[:i]
-
// Remove unreachable blocks. Return dead blocks to allocator.
i = 0
for _, b := range f.Blocks {
diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go
index b10911aa92..ba3d1e589e 100644
--- a/src/cmd/compile/internal/ssa/func.go
+++ b/src/cmd/compile/internal/ssa/func.go
@@ -64,12 +64,6 @@ type Func struct {
// AuxCall describing parameters and results for this function.
OwnAux *AuxCall
- // WBLoads is a list of Blocks that branch on the write
- // barrier flag. Safe-points are disabled from the OpLoad that
- // reads the write-barrier flag until the control flow rejoins
- // below the two successors of this block.
- WBLoads []*Block
-
freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil.
freeBlocks *Block // free Blocks linked by succstorage[0].b. All other fields except ID are 0/nil.
diff --git a/src/cmd/compile/internal/ssa/lower.go b/src/cmd/compile/internal/ssa/lower.go
index 88eb6748e8..e4aac47cee 100644
--- a/src/cmd/compile/internal/ssa/lower.go
+++ b/src/cmd/compile/internal/ssa/lower.go
@@ -29,7 +29,7 @@ func checkLower(f *Func) {
continue // lowered
}
switch v.Op {
- case OpSP, OpSPanchored, OpSB, OpInitMem, OpArg, OpArgIntReg, OpArgFloatReg, OpPhi, OpVarDef, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpSelectN, OpConvert, OpInlMark:
+ case OpSP, OpSPanchored, OpSB, OpInitMem, OpArg, OpArgIntReg, OpArgFloatReg, OpPhi, OpVarDef, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpSelectN, OpConvert, OpInlMark, OpWBend:
continue // ok not to lower
case OpMakeResult:
if b.Controls[0] == v {
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index baf0d7ba32..76ca9e059d 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -3022,6 +3022,7 @@ const (
OpStoreWB
OpMoveWB
OpZeroWB
+ OpWBend
OpWB
OpHasCPUFeature
OpPanicBounds
@@ -38929,6 +38930,11 @@ var opcodeTable = [...]opInfo{
generic: true,
},
{
+ name: "WBend",
+ argLen: 1,
+ generic: true,
+ },
+ {
name: "WB",
auxType: auxSym,
argLen: 3,
diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go
index 02f5649d59..d2e10cab62 100644
--- a/src/cmd/compile/internal/ssa/writebarrier.go
+++ b/src/cmd/compile/internal/ssa/writebarrier.go
@@ -197,8 +197,6 @@ func writebarrier(f *Func) {
// order values in store order
b.Values = storeOrder(b.Values, sset, storeNumber)
-
- firstSplit := true
again:
// find the start and end of the last contiguous WB store sequence.
// a branch will be inserted there. values after it will be moved
@@ -374,17 +372,19 @@ func writebarrier(f *Func) {
}
// merge memory
- // Splice memory Phi into the last memory of the original sequence,
- // which may be used in subsequent blocks. Other memories in the
- // sequence must be dead after this block since there can be only
- // one memory live.
+ mem = bEnd.NewValue2(pos, OpPhi, types.TypeMem, memThen, memElse)
+ // The last store becomes the WBend marker. This marker is used by the liveness
+ // pass to determine what parts of the code are preemption-unsafe.
+ // All subsequent memory operations use this memory, so we have to sacrifice the
+ // previous last memory op to become this new value.
bEnd.Values = append(bEnd.Values, last)
last.Block = bEnd
- last.reset(OpPhi)
+ last.reset(OpWBend)
last.Pos = last.Pos.WithNotStmt()
last.Type = types.TypeMem
- last.AddArg(memThen)
- last.AddArg(memElse)
+ last.AddArg(mem)
+
+ // Free all the old stores, except last which became the WBend marker.
for _, w := range stores {
if w != last {
w.resetArgs()
@@ -402,23 +402,6 @@ func writebarrier(f *Func) {
w.Block = bEnd
}
- // Preemption is unsafe between loading the write
- // barrier-enabled flag and performing the write
- // because that would allow a GC phase transition,
- // which would invalidate the flag. Remember the
- // conditional block so liveness analysis can disable
- // safe-points. This is somewhat subtle because we're
- // splitting b bottom-up.
- if firstSplit {
- // Add b itself.
- b.Func.WBLoads = append(b.Func.WBLoads, b)
- firstSplit = false
- } else {
- // We've already split b, so we just pushed a
- // write barrier test into bEnd.
- b.Func.WBLoads = append(b.Func.WBLoads, bEnd)
- }
-
// if we have more stores in this block, do this block again
if nWBops > 0 {
goto again