]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: buffered write barrier for s390x
authorAustin Clements <austin@google.com>
Wed, 15 Nov 2017 22:54:24 +0000 (14:54 -0800)
committerAustin Clements <austin@google.com>
Tue, 13 Feb 2018 16:34:24 +0000 (16:34 +0000)
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>
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/s390x/ssa.go
src/cmd/compile/internal/ssa/gen/S390X.rules
src/cmd/compile/internal/ssa/gen/S390XOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteS390X.go
src/cmd/vet/all/whitelist/s390x.txt
src/runtime/asm_s390x.s

index a463b222e1f30d85b3edd520c2cd85faa01ba170..7f947530b1742f6da1bd6020ff257efdecb02d0a 100644 (file)
@@ -408,7 +408,7 @@ func Main(archInit func(*Arch)) {
        }
 
        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:
                // Other architectures don't support the buffered
                // write barrier yet.
index c9d1f52c8f842d64a81e466c7954caa450d7edb3..23735ec3a6899be82a7d630658cec4c0faf9993e 100644 (file)
@@ -511,6 +511,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.To.Reg = v.Reg()
        case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter:
                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,
                ssa.OpS390XMOVWBR, ssa.OpS390XMOVDBR:
                p := s.Prog(v.Op.Asm())
index 6b997bd46d81a1c9ada8db899e1da74ddb113246..5c457d0a75118cb1b8a4cb68484ccf4a55a94331 100644 (file)
 
 (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
 // Below: optimizations
index ec4c9b2a3e3ec13b77ca43d09648e914b6a7deed..73510d40a14efbb4be3a5c7f368e6504b8dc50bf 100644 (file)
@@ -116,6 +116,7 @@ func init() {
 
                // R10 and R11 are reserved by the assembler.
                gp   = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14")
+               gpg  = gp | buildReg("g")
                gpsp = gp | sp
 
                // 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: "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.
                // We have a special op for this so as to not confuse GC
                // (particularly stack maps). It takes a memory arg so it
index 6859f36e517af32481db73bc9fd2f8d211401a5f..5075c1cc2398f7a7c01f091e83ddae97158b8f08 100644 (file)
@@ -1686,6 +1686,7 @@ const (
        OpS390XLoweredNilCheck
        OpS390XLoweredRound32F
        OpS390XLoweredRound64F
+       OpS390XLoweredWB
        OpS390XMOVDconvert
        OpS390XFlagEQ
        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",
                argLen: 2,
index fe9b2bd001b243e7ccff79760b0be522cba10643..43929d0550400bb3031a71ce42f1e6ff916b37f3 100644 (file)
@@ -753,6 +753,8 @@ func rewriteValueS390X(v *Value) bool {
                return rewriteValueS390X_OpTrunc64to32_0(v)
        case OpTrunc64to8:
                return rewriteValueS390X_OpTrunc64to8_0(v)
+       case OpWB:
+               return rewriteValueS390X_OpWB_0(v)
        case OpXor16:
                return rewriteValueS390X_OpXor16_0(v)
        case OpXor32:
@@ -39218,6 +39220,24 @@ func rewriteValueS390X_OpTrunc64to8_0(v *Value) bool {
                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 {
        // match: (Xor16 x y)
        // cond:
index f18236c4f112dee1c1fdf7e68d40eb2560de4218..68e5461a3c599b13dc393abf1596fbe66f98d5e3 100644 (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/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/asm_ARCHSUFF.s: [GOARCH] gcWriteBarrier: function gcWriteBarrier missing Go declaration
index 6b71830557707b64ae950f71d8b925e2d614710b..766a408c3c2ca3f3ccedda2233dd50968a739e5a 100644 (file)
@@ -1303,3 +1303,69 @@ TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
 TEXT ·checkASM(SB),NOSPLIT,$0-1
        MOVB    $1, ret+0(FP)
        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