1
0
mirror of https://github.com/golang/go synced 2024-11-19 13:04:45 -07:00

runtime: buffered write barrier for s390x

Updates #22460.

Change-Id: I3f793e69577c1b837ad2666e6209a97a452405d4
Reviewed-on: https://go-review.googlesource.com/92703
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Austin Clements 2017-11-15 14:54:24 -08:00
parent ae7d5f84f8
commit 2ae1e1ae2f
8 changed files with 118 additions and 1 deletions

View File

@ -408,7 +408,7 @@ func Main(archInit func(*Arch)) {
} }
switch objabi.GOARCH { switch objabi.GOARCH {
case "amd64", "amd64p32", "386", "arm", "arm64", "ppc64", "ppc64le", "mips64", "mips64le", "mips", "mipsle": case "amd64", "amd64p32", "386", "arm", "arm64", "ppc64", "ppc64le", "mips64", "mips64le", "mips", "mipsle", "s390x":
default: default:
// Other architectures don't support the buffered // Other architectures don't support the buffered
// write barrier yet. // write barrier yet.

View File

@ -511,6 +511,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = v.Reg() p.To.Reg = v.Reg()
case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter: case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter:
s.Call(v) s.Call(v)
case ssa.OpS390XLoweredWB:
p := s.Prog(obj.ACALL)
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_EXTERN
p.To.Sym = v.Aux.(*obj.LSym)
case ssa.OpS390XFLOGR, ssa.OpS390XNEG, ssa.OpS390XNEGW, case ssa.OpS390XFLOGR, ssa.OpS390XNEG, ssa.OpS390XNEGW,
ssa.OpS390XMOVWBR, ssa.OpS390XMOVDBR: ssa.OpS390XMOVWBR, ssa.OpS390XMOVDBR:
p := s.Prog(v.Op.Asm()) p := s.Prog(v.Op.Asm())

View File

@ -446,6 +446,9 @@
(If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg <typ.Bool> cond)) yes no) (If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg <typ.Bool> cond)) yes no)
// Write barrier.
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
// *************************** // ***************************
// Above: lowering rules // Above: lowering rules
// Below: optimizations // Below: optimizations

View File

@ -116,6 +116,7 @@ func init() {
// R10 and R11 are reserved by the assembler. // R10 and R11 are reserved by the assembler.
gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14") gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14")
gpg = gp | buildReg("g")
gpsp = gp | sp gpsp = gp | sp
// R0 is considered to contain the value 0 in address calculations. // R0 is considered to contain the value 0 in address calculations.
@ -453,6 +454,11 @@ func init() {
{name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true}, {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true},
{name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true}, {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true},
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
// It saves all GP registers if necessary,
// but clobbers R14 (LR) because it's a call.
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
// MOVDconvert converts between pointers and integers. // MOVDconvert converts between pointers and integers.
// We have a special op for this so as to not confuse GC // We have a special op for this so as to not confuse GC
// (particularly stack maps). It takes a memory arg so it // (particularly stack maps). It takes a memory arg so it

View File

@ -1686,6 +1686,7 @@ const (
OpS390XLoweredNilCheck OpS390XLoweredNilCheck
OpS390XLoweredRound32F OpS390XLoweredRound32F
OpS390XLoweredRound64F OpS390XLoweredRound64F
OpS390XLoweredWB
OpS390XMOVDconvert OpS390XMOVDconvert
OpS390XFlagEQ OpS390XFlagEQ
OpS390XFlagLT OpS390XFlagLT
@ -22074,6 +22075,20 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "LoweredWB",
auxType: auxSym,
argLen: 3,
clobberFlags: true,
symEffect: SymNone,
reg: regInfo{
inputs: []inputInfo{
{0, 4}, // R2
{1, 8}, // R3
},
clobbers: 4294918144, // R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
{ {
name: "MOVDconvert", name: "MOVDconvert",
argLen: 2, argLen: 2,

View File

@ -753,6 +753,8 @@ func rewriteValueS390X(v *Value) bool {
return rewriteValueS390X_OpTrunc64to32_0(v) return rewriteValueS390X_OpTrunc64to32_0(v)
case OpTrunc64to8: case OpTrunc64to8:
return rewriteValueS390X_OpTrunc64to8_0(v) return rewriteValueS390X_OpTrunc64to8_0(v)
case OpWB:
return rewriteValueS390X_OpWB_0(v)
case OpXor16: case OpXor16:
return rewriteValueS390X_OpXor16_0(v) return rewriteValueS390X_OpXor16_0(v)
case OpXor32: case OpXor32:
@ -39218,6 +39220,24 @@ func rewriteValueS390X_OpTrunc64to8_0(v *Value) bool {
return true return true
} }
} }
func rewriteValueS390X_OpWB_0(v *Value) bool {
// match: (WB {fn} destptr srcptr mem)
// cond:
// result: (LoweredWB {fn} destptr srcptr mem)
for {
fn := v.Aux
_ = v.Args[2]
destptr := v.Args[0]
srcptr := v.Args[1]
mem := v.Args[2]
v.reset(OpS390XLoweredWB)
v.Aux = fn
v.AddArg(destptr)
v.AddArg(srcptr)
v.AddArg(mem)
return true
}
}
func rewriteValueS390X_OpXor16_0(v *Value) bool { func rewriteValueS390X_OpXor16_0(v *Value) bool {
// match: (Xor16 x y) // match: (Xor16 x y)
// cond: // cond:

View File

@ -15,3 +15,5 @@ runtime/memclr_s390x.s: [s390x] memclr_s390x_exrl_xc: function memclr_s390x_exrl
runtime/memmove_s390x.s: [s390x] memmove_s390x_exrl_mvc: function memmove_s390x_exrl_mvc missing Go declaration runtime/memmove_s390x.s: [s390x] memmove_s390x_exrl_mvc: function memmove_s390x_exrl_mvc missing Go declaration
runtime/tls_s390x.s: [s390x] save_g: function save_g missing Go declaration runtime/tls_s390x.s: [s390x] save_g: function save_g missing Go declaration
runtime/tls_s390x.s: [s390x] load_g: function load_g missing Go declaration runtime/tls_s390x.s: [s390x] load_g: function load_g missing Go declaration
runtime/asm_ARCHSUFF.s: [GOARCH] gcWriteBarrier: function gcWriteBarrier missing Go declaration

View File

@ -1303,3 +1303,69 @@ TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
TEXT ·checkASM(SB),NOSPLIT,$0-1 TEXT ·checkASM(SB),NOSPLIT,$0-1
MOVB $1, ret+0(FP) MOVB $1, ret+0(FP)
RET RET
// gcWriteBarrier performs a heap pointer write and informs the GC.
//
// gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
// - R2 is the destination of the write
// - R3 is the value being written at R2.
// It clobbers R10 and R11 (the linker temp registers).
// It does not clobber any other general-purpose registers,
// but may clobber others (e.g., floating point registers).
TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$88
// Save the registers clobbered by the fast path.
MOVD R1, 80(R15)
MOVD R4, 88(R15)
MOVD g_m(g), R1
MOVD m_p(R1), R1
MOVD (p_wbBuf+wbBuf_next)(R1), R4
// Increment wbBuf.next position.
ADD $16, R4
MOVD R4, (p_wbBuf+wbBuf_next)(R1)
MOVD (p_wbBuf+wbBuf_end)(R1), R1
MOVD R1, R10 // R10 is linker temp register
// Record the write.
MOVD R3, -16(R4) // Record value
MOVD (R2), R1 // TODO: This turns bad writes into bad reads.
MOVD R1, -8(R4) // Record *slot
// Is the buffer full?
CMPBEQ R4, R10, flush
ret:
MOVD 80(R15), R1
MOVD 88(R15), R4
// Do the write.
MOVD R3, (R2)
RET
flush:
// Save all general purpose registers since these could be
// clobbered by wbBufFlush and were not saved by the caller.
MOVD R2, 8(R15) // Also first argument to wbBufFlush
MOVD R3, 16(R15) // Also second argument to wbBufFlush
MOVD R0, 24(R15)
// R1 already saved.
// R4 already saved.
MOVD R5, 32(R15)
MOVD R6, 40(R15)
MOVD R7, 48(R15)
MOVD R8, 56(R15)
MOVD R9, 64(R15)
// R10 and R11 are linker temp registers.
MOVD R12, 72(R15)
// R13 is g.
// R14 is LR.
// R15 is SP.
// This takes arguments R2 and R3.
CALL runtime·wbBufFlush(SB)
MOVD 8(R15), R2
MOVD 16(R15), R3
MOVD 24(R15), R0
MOVD 32(R15), R5
MOVD 40(R15), R6
MOVD 48(R15), R7
MOVD 56(R15), R8
MOVD 64(R15), R9
MOVD 72(R15), R12
JMP ret