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)