aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/asm_arm.s
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-11-15 14:54:24 -0800
committerAustin Clements <austin@google.com>2018-02-13 16:34:17 +0000
commit1de1f316df84569c449d6d709b0d711921ea6116 (patch)
tree8ac47388708fe13a4f86bc27e780185be5b9a7a3 /src/runtime/asm_arm.s
parent24dd83d7eb0f08ea5cf541ead3f2b36448468bfa (diff)
downloadgo-1de1f316df84569c449d6d709b0d711921ea6116.tar.gz
go-1de1f316df84569c449d6d709b0d711921ea6116.zip
runtime: buffered write barrier for arm
Updates #22460. Change-Id: I5581df7ad553237db7df3701b117ad99e0593b78 Reviewed-on: https://go-review.googlesource.com/92698 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/asm_arm.s')
-rw-r--r--src/runtime/asm_arm.s58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s
index d10c370a7d..0b429705e8 100644
--- a/src/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -1054,3 +1054,61 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1
MOVW $1, R3
MOVB R3, 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 condition codes.
+// It does not clobber any other general-purpose registers,
+// but may clobber others (e.g., floating point registers).
+// The act of CALLing gcWriteBarrier will clobber R14 (LR).
+TEXT runtime·gcWriteBarrier(SB),NOSPLIT|NOFRAME,$0
+ // Save the registers clobbered by the fast path.
+ MOVM.DB.W [R0,R1], (R13)
+ MOVW g_m(g), R0
+ MOVW m_p(R0), R0
+ MOVW (p_wbBuf+wbBuf_next)(R0), R1
+ // Increment wbBuf.next position.
+ ADD $8, R1
+ MOVW R1, (p_wbBuf+wbBuf_next)(R0)
+ MOVW (p_wbBuf+wbBuf_end)(R0), R0
+ CMP R1, R0
+ // Record the write.
+ MOVW R3, -8(R1) // Record value
+ MOVW (R2), R0 // TODO: This turns bad writes into bad reads.
+ MOVW R0, -4(R1) // Record *slot
+ // Is the buffer full? (flags set in CMP above)
+ B.EQ flush
+ret:
+ MOVM.IA.W (R13), [R0,R1]
+ // Do the write.
+ MOVW R3, (R2)
+ // Normally RET on nacl clobbers R12, but because this
+ // function has no frame it doesn't have to usual epilogue.
+ RET
+
+flush:
+ // Save all general purpose registers since these could be
+ // clobbered by wbBufFlush and were not saved by the caller.
+ //
+ // R0 and R1 were saved at entry.
+ // R10 is g, so preserved.
+ // R11 is linker temp, so no need to save.
+ // R13 is stack pointer.
+ // R15 is PC.
+ //
+ // This also sets up R2 and R3 as the arguments to wbBufFlush.
+ MOVM.DB.W [R2-R9,R12], (R13)
+ // Save R14 (LR) because the fast path above doesn't save it,
+ // but needs it to RET. This is after the MOVM so it appears below
+ // the arguments in the stack frame.
+ MOVM.DB.W [R14], (R13)
+
+ // This takes arguments R2 and R3.
+ CALL runtime·wbBufFlush(SB)
+
+ MOVM.IA.W (R13), [R14]
+ MOVM.IA.W (R13), [R2-R9,R12]
+ JMP ret