github.com/primecitizens/pcz/std@v0.2.1/core/gc/wb_amd64.s (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2009 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 //go:build amd64 9 10 #include "textflag.h" 11 12 // gcWriteBarrier informs the GC about heap pointer writes. 13 // 14 // gcWriteBarrier returns space in a write barrier buffer which 15 // should be filled in by the caller. 16 // gcWriteBarrier does NOT follow the Go ABI. It accepts the 17 // number of bytes of buffer needed in R11, and returns a pointer 18 // to the buffer space in R11. 19 // It clobbers FLAGS. It does not clobber any general-purpose registers, 20 // but may clobber others (e.g., SSE registers). 21 // Typical use would be, when doing *(CX+88) = AX 22 // CMPL $0, runtime.writeBarrier(SB) 23 // JEQ dowrite 24 // CALL runtime.gcBatchBarrier2(SB) 25 // MOVQ AX, (R11) 26 // MOVQ 88(CX), DX 27 // MOVQ DX, 8(R11) 28 // dowrite: 29 // MOVQ AX, 88(CX) 30 TEXT gcWriteBarrier<>(SB),NOSPLIT,$112 31 // Save the registers clobbered by the fast path. This is slightly 32 // faster than having the caller spill these. 33 MOVQ R12, 96(SP) 34 MOVQ R13, 104(SP) 35 retry: 36 // TODO: Consider passing g.m.p in as an argument so they can be shared 37 // across a sequence of write barriers. 38 MOVQ g_m(R14), R13 39 MOVQ m_p(R13), R13 40 // Get current buffer write position. 41 MOVQ (p_wbBuf+wbBuf_next)(R13), R12 // original next position 42 ADDQ R11, R12 // new next position 43 // Is the buffer full? 44 CMPQ R12, (p_wbBuf+wbBuf_end)(R13) 45 JA flush 46 // Commit to the larger buffer. 47 MOVQ R12, (p_wbBuf+wbBuf_next)(R13) 48 // Make return value (the original next position) 49 SUBQ R11, R12 50 MOVQ R12, R11 51 // Restore registers. 52 MOVQ 96(SP), R12 53 MOVQ 104(SP), R13 54 RET 55 56 flush: 57 // Save all general purpose registers since these could be 58 // clobbered by wbBufFlush and were not saved by the caller. 59 // It is possible for wbBufFlush to clobber other registers 60 // (e.g., SSE registers), but the compiler takes care of saving 61 // those in the caller if necessary. This strikes a balance 62 // with registers that are likely to be used. 63 // 64 // We don't have type information for these, but all code under 65 // here is NOSPLIT, so nothing will observe these. 66 // 67 // TODO: We could strike a different balance; e.g., saving X0 68 // and not saving GP registers that are less likely to be used. 69 MOVQ DI, 0(SP) 70 MOVQ AX, 8(SP) 71 MOVQ BX, 16(SP) 72 MOVQ CX, 24(SP) 73 MOVQ DX, 32(SP) 74 // DI already saved 75 MOVQ SI, 40(SP) 76 MOVQ BP, 48(SP) 77 MOVQ R8, 56(SP) 78 MOVQ R9, 64(SP) 79 MOVQ R10, 72(SP) 80 MOVQ R11, 80(SP) 81 // R12 already saved 82 // R13 already saved 83 // R14 is g 84 MOVQ R15, 88(SP) 85 86 CALL runtime·wbBufFlush(SB) 87 88 MOVQ 0(SP), DI 89 MOVQ 8(SP), AX 90 MOVQ 16(SP), BX 91 MOVQ 24(SP), CX 92 MOVQ 32(SP), DX 93 MOVQ 40(SP), SI 94 MOVQ 48(SP), BP 95 MOVQ 56(SP), R8 96 MOVQ 64(SP), R9 97 MOVQ 72(SP), R10 98 MOVQ 80(SP), R11 99 MOVQ 88(SP), R15 100 JMP retry 101 102 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 103 MOVL $8, R11 104 JMP gcWriteBarrier<>(SB) 105 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 106 MOVL $16, R11 107 JMP gcWriteBarrier<>(SB) 108 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 109 MOVL $24, R11 110 JMP gcWriteBarrier<>(SB) 111 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 112 MOVL $32, R11 113 JMP gcWriteBarrier<>(SB) 114 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 115 MOVL $40, R11 116 JMP gcWriteBarrier<>(SB) 117 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 118 MOVL $48, R11 119 JMP gcWriteBarrier<>(SB) 120 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 121 MOVL $56, R11 122 JMP gcWriteBarrier<>(SB) 123 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 124 MOVL $64, R11 125 JMP gcWriteBarrier<>(SB)