Skip to content

Commit

Permalink
PUSH_PROBE_FRAME on arm64
Browse files Browse the repository at this point in the history
  • Loading branch information
VSadov committed Jul 21, 2022
1 parent 75a01b9 commit c321a96
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 60 deletions.
10 changes: 5 additions & 5 deletions src/coreclr/nativeaot/Runtime/amd64/GcProbe.asm
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
include AsmMacros.inc

;;
;; See PUSH_COOP_PINVOKE_FRAME, this macro is very similar, but also saves RAX and accepts the register
;; bitmask in RCX
;; See PUSH_COOP_PINVOKE_FRAME, this macro is very similar, but also saves RAX and accepts
;; the register bitmask
;;
;; On entry:
;; - BITMASK: bitmask describing pushes, may be volatile register or constant value
;; - BITMASK: bitmask describing pushes, a volatile register
;; - RAX: managed function return value, may be an object or byref
;; - preserved regs: need to stay preserved, may contain objects or byrefs
;;
Expand All @@ -31,7 +31,7 @@ PUSH_PROBE_FRAME macro threadReg, trashReg, BITMASK
push_vol_reg BITMASK ; save the register bitmask passed in by caller
push_vol_reg threadReg ; Thread * (unused by stackwalker)
push_nonvol_reg rbp ; save caller's RBP
mov trashReg, [rsp + 12*8] ; Find the return address
mov trashReg, [rsp + 12*8] ; Find the return address
push_vol_reg trashReg ; save m_RIP
lea trashReg, [rsp + 0] ; trashReg == address of frame

Expand All @@ -41,7 +41,7 @@ PUSH_PROBE_FRAME macro threadReg, trashReg, BITMASK
;; save xmm0 in case it's being used as a return value
movdqa [rsp + 20h], xmm0

; link the frame into the Thread
;; link the frame into the Thread
mov [threadReg + OFFSETOF__Thread__m_pDeferredTransitionFrame], trashReg
endm

Expand Down
81 changes: 26 additions & 55 deletions src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@ m_CallersSP field 8 ; SP at routine entry
field 4 * 8 ; d0..d3
PROBE_FRAME_SIZE field 0

;; Support for setting up a transition frame when performing a GC probe. In many respects this is very
;; similar to the logic in PUSH_COOP_PINVOKE_FRAME in AsmMacros.h. In most cases setting up the
;; transition frame comprises the entirety of the caller's prolog (and initial non-prolog code) and
;; similarly for the epilog. Those cases can be dealt with using PROLOG_PROBE_FRAME and EPILOG_PROBE_FRAME
;; defined below. For the special cases where additional work has to be done in the prolog we also provide
;; the lower level macros ALLOC_PROBE_FRAME, FREE_PROBE_FRAME and INIT_PROBE_FRAME that allow more control
;; to be asserted.
;; Perform the parts of setting up a probe frame that can occur during the prolog (and indeed this macro
;; can only be called from within the prolog).
;; See PUSH_COOP_PINVOKE_FRAME, this macro is very similar, but also saves return registers
;; and accepts the register bitmask
;; Call this macro first in the method (no further prolog instructions can be added after this).
;;
;; $threadReg : register containing the Thread* (this will be preserved).
;; $trashReg : register that can be trashed by this macro
;; $BITMASK : value to initialize m_dwFlags field with (register or #constant)
MACRO
ALLOC_PROBE_FRAME
PUSH_PROBE_FRAME $threadReg, $trashReg, $BITMASK

; Define the method prolog, allocating enough stack space for the PInvokeTransitionFrame and saving
; incoming register values into it.

;; First create PInvokeTransitionFrame
PROLOG_SAVE_REG_PAIR fp, lr, #-(PROBE_FRAME_SIZE)! ;; Push down stack pointer and store FP and LR
Expand All @@ -56,12 +57,21 @@ PROBE_FRAME_SIZE field 0
PROLOG_NOP stp d0, d1, [sp, #0x90]
PROLOG_NOP stp d2, d3, [sp, #0xA0]

;; Perform the rest of the PInvokeTransitionFrame initialization.
str $BITMASK, [sp, #OFFSETOF__PInvokeTransitionFrame__m_Flags] ; save the register bitmask passed in by caller
str $threadReg,[sp, #OFFSETOF__PInvokeTransitionFrame__m_pThread] ; Thread * (unused by stackwalker)
add $trashReg, sp, #PROBE_FRAME_SIZE ; recover value of caller's SP
str $trashReg, [sp, #m_CallersSP] ; save caller's SP

;; link the frame into the Thread
mov $trashReg, sp
str $trashReg, [$threadReg, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
MEND

;; Undo the effects of an ALLOC_PROBE_FRAME. This may only be called within an epilog. Note that all
;; registers are restored (apart for sp and pc), even volatiles.
MACRO
FREE_PROBE_FRAME
POP_PROBE_FRAME

;; Restore the integer return registers
PROLOG_NOP ldr x0, [sp, #0x78]
Expand All @@ -81,42 +91,6 @@ PROBE_FRAME_SIZE field 0
EPILOG_RESTORE_REG_PAIR fp, lr, #(PROBE_FRAME_SIZE)!
MEND

;; Complete the setup of a probe frame allocated with ALLOC_PROBE_FRAME with the initialization that can
;; occur only outside the prolog (includes linking the frame to the current Thread). This macro assumes SP
;; is invariant outside of the prolog.
;;
;; $threadReg : register containing the Thread* (this will be preserved)
;; $trashReg : register that can be trashed by this macro
;; $savedRegsMask : register containing flags
MACRO
INIT_PROBE_FRAME $threadReg, $trashReg, $savedRegsMask

str $threadReg, [sp, #OFFSETOF__PInvokeTransitionFrame__m_pThread] ; Thread *
str $savedRegsMask, [sp, #OFFSETOF__PInvokeTransitionFrame__m_Flags]
add $trashReg, sp, #PROBE_FRAME_SIZE
str $trashReg, [sp, #m_CallersSP]
MEND

;; Simple macro to use when setting up the probe frame can comprise the entire prolog. Call this macro
;; first in the method (no further prolog instructions can be added after this).
;;
;; $threadReg : register containing the Thread* (this will be preserved).
;; $trashReg : register that can be trashed by this macro
;; $savedRegsMask : value to initialize m_dwFlags field with (register or #constant)
MACRO
PROLOG_PROBE_FRAME $threadReg, $trashReg, $savedRegsMask

; Define the method prolog, allocating enough stack space for the PInvokeTransitionFrame and saving
; incoming register values into it.
ALLOC_PROBE_FRAME


; Perform the rest of the PInvokeTransitionFrame initialization.
INIT_PROBE_FRAME $threadReg, $trashReg, $savedRegsMask
mov $trashReg, sp
str $trashReg, [$threadReg, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
MEND

;;
;; The prolog for all GC suspension hijacks (normal and stress). Fixes up the hijacked return address, and
;; clears the hijack state.
Expand Down Expand Up @@ -166,11 +140,8 @@ PROBE_FRAME_SIZE field 0

MEND

;;
;;
;;
;; GC Probe Hijack target
;;
;;
EXTERN RhpPInvokeExceptionGuard

Expand All @@ -193,18 +164,18 @@ DoRhpGcProbe
EXTERN RhpThrowHwEx

NESTED_ENTRY RhpGcProbe
PROLOG_PROBE_FRAME x2, x3, x12
PUSH_PROBE_FRAME x2, x3, x12

ldr x0, [x2, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
bl RhpWaitForGC2

ldr x2, [sp, #OFFSETOF__PInvokeTransitionFrame__m_Flags]
tbnz x2, #PTFF_THREAD_ABORT_BIT, %F1

FREE_PROBE_FRAME
POP_PROBE_FRAME
EPILOG_RETURN
1
FREE_PROBE_FRAME
POP_PROBE_FRAME
EPILOG_NOP mov w0, #STATUS_REDHAWK_THREAD_ABORT
EPILOG_NOP mov x1, lr ;; return address as exception PC
EPILOG_NOP b RhpThrowHwEx
Expand Down Expand Up @@ -252,11 +223,11 @@ DoRhpGcProbe
;; All other registers restored as they were when the hijack was first reached.
;;
NESTED_ENTRY RhpGcStressProbe
PROLOG_PROBE_FRAME x2, x3, x12
PUSH_PROBE_FRAME x2, x3, x12

bl $REDHAWKGCINTERFACE__STRESSGC

FREE_PROBE_FRAME
POP_PROBE_FRAME
EPILOG_RETURN
NESTED_END RhpGcStressProbe

Expand Down

0 comments on commit c321a96

Please sign in to comment.