mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 03:27:04 +09:00
adjust call convention of JIT_ByRefWriteBarrier to be compatible with standard GC
This commit is contained in:
parent
5a8c497d68
commit
0736977f46
5 changed files with 183 additions and 79 deletions
|
@ -204,12 +204,11 @@
|
|||
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
|
||||
#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC
|
||||
|
||||
// TODO: Satori make more precise?
|
||||
// Registers killed by CORINFO_HELP_ASSIGN_BYREF.
|
||||
#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_TRASH_NOGC)
|
||||
|
||||
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF.
|
||||
#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_CALLEE_TRASH_NOGC & ~(RBM_RDI | RBM_RSI))
|
||||
#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_RAX | RBM_RCX)
|
||||
|
||||
// Registers killed by CORINFO_HELP_ASSIGN_BYREF.
|
||||
#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF)
|
||||
|
||||
// We have two register classifications
|
||||
// * callee trash: aka volatile or caller saved
|
||||
|
|
|
@ -400,7 +400,7 @@ LEAF_ENTRY RhpAssignRef, _TEXT
|
|||
|
||||
JustAssign:
|
||||
ALTERNATE_ENTRY RhpAssignRefAVLocationNotHeap
|
||||
mov [rdi], rsi // no card marking, src is not a heap object
|
||||
mov [rdi], rsi // no card marking, src is not a heap object
|
||||
// set rdi, rsi per contract with JIT_ByRefWriteBarrier
|
||||
add rdi, 8
|
||||
mov rsi, r10
|
||||
|
@ -515,9 +515,17 @@ ALTERNATE_ENTRY RhpAssignRefAVLocation
|
|||
push rdx
|
||||
push r10
|
||||
|
||||
// also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
|
||||
// Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
|
||||
sub rsp, 16
|
||||
movdqu [rsp], xmm0
|
||||
|
||||
// void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
|
||||
call qword ptr [rdx + 8]
|
||||
|
||||
movdqu xmm0, [rsp]
|
||||
add rsp, 16
|
||||
|
||||
pop r10
|
||||
pop rdx
|
||||
pop rsi
|
||||
|
@ -529,31 +537,48 @@ LEAF_END RhpAssignRef, _TEXT
|
|||
//
|
||||
// RhpByRefAssignRef simulates movs instruction for object references.
|
||||
//
|
||||
// On entry:
|
||||
// rdi: address of ref-field (assigned to)
|
||||
// rsi: address of the data (source)
|
||||
//
|
||||
// On exit:
|
||||
// rdi, rsi are incremented by 8,
|
||||
// rdi, rdx, r9, r10, r11: trashed
|
||||
//
|
||||
// Entry:
|
||||
// RDI - address of ref-field (assigned to)
|
||||
// RSI - address of the data (source)
|
||||
// Exit:
|
||||
// RCX is trashed
|
||||
// RAX is trashed
|
||||
// RDI, RSI are incremented by SIZEOF(LPVOID)
|
||||
LEAF_ENTRY RhpByRefAssignRef, _TEXT
|
||||
lea r10, [rsi + 8]
|
||||
// See if dst is in GCHeap
|
||||
mov rax, [C_VAR(g_card_bundle_table)] // fetch the page byte map
|
||||
mov rcx, rdi
|
||||
shr rcx, 30 // dst page index
|
||||
cmp byte ptr [rax + rcx], 0
|
||||
jne InHeap
|
||||
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
|
||||
mov rcx, [rsi]
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
|
||||
mov [rdi], rcx
|
||||
add rdi, 8
|
||||
add rsi, 8
|
||||
ret
|
||||
|
||||
InHeap:
|
||||
// JIT_WriteBarrier may trash these registers
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
|
||||
// save preadjusted rsi
|
||||
lea r10, [rsi + 8]
|
||||
mov rsi, [rsi]
|
||||
|
||||
// See if dst is in GCHeap
|
||||
mov rax, [C_VAR(g_card_bundle_table)] // fetch the page byte map
|
||||
mov r8, rdi
|
||||
shr r8, 30 // dst page index
|
||||
cmp byte ptr [rax + r8], 0
|
||||
jne C_FUNC(CheckedEntry)
|
||||
call CheckedEntry
|
||||
|
||||
NotInHeap_RhpByRefAssignRef:
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
|
||||
mov [rdi], rsi
|
||||
add rdi, 8
|
||||
mov rsi, r10
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
ret
|
||||
LEAF_END RhpByRefAssignRef, _TEXT
|
||||
|
||||
|
|
|
@ -508,17 +508,28 @@ ALTERNATE_ENTRY RhpAssignRefAVLocation
|
|||
mov r9, rsp
|
||||
and rsp, -16
|
||||
|
||||
; save rsp, rcx, rdx, r8 and have enough stack for the callee
|
||||
; save rsp, rcx, rdx, r8
|
||||
push r9
|
||||
push rcx
|
||||
push rdx
|
||||
push r8
|
||||
|
||||
; also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
|
||||
; Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
|
||||
sub rsp, 16
|
||||
movdqu [rsp], xmm0
|
||||
|
||||
; shadow space
|
||||
sub rsp, 20h
|
||||
|
||||
; void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
|
||||
call qword ptr [r8 + 8]
|
||||
|
||||
add rsp, 20h
|
||||
|
||||
movdqu xmm0, [rsp]
|
||||
add rsp, 16
|
||||
|
||||
pop r8
|
||||
pop rdx
|
||||
pop rcx
|
||||
|
@ -528,33 +539,51 @@ LEAF_END RhpAssignRef, _TEXT
|
|||
|
||||
;;
|
||||
;; RhpByRefAssignRef simulates movs instruction for object references.
|
||||
;;
|
||||
;; On entry:
|
||||
;; rdi: address of ref-field (assigned to)
|
||||
;; rsi: address of the data (source)
|
||||
;;
|
||||
;; On exit:
|
||||
;; rdi, rsi are incremented by 8,
|
||||
;; rcx, r8, r9, r11: trashed
|
||||
;;
|
||||
;; Entry:
|
||||
;; RDI - address of ref-field (assigned to)
|
||||
;; RSI - address of the data (source)
|
||||
;; Exit:
|
||||
;; RCX is trashed
|
||||
;; RAX is trashed
|
||||
;; RDI, RSI are incremented by SIZEOF(LPVOID)
|
||||
LEAF_ENTRY RhpByRefAssignRef, _TEXT
|
||||
mov rcx, rdi
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
|
||||
mov rdx, [rsi]
|
||||
add rdi, 8h
|
||||
add rsi, 8h
|
||||
|
||||
; See if dst is in GCHeap
|
||||
mov rax, [g_card_bundle_table] ; fetch the page byte map
|
||||
mov r8, rcx
|
||||
shr r8, 30 ; dst page index
|
||||
cmp byte ptr [rax + r8], 0
|
||||
jne CheckedEntry
|
||||
mov rax, [g_card_bundle_table] ; fetch the page byte map
|
||||
mov rcx, rdi
|
||||
shr rcx, 30 ; dst page index
|
||||
cmp byte ptr [rax + rcx], 0
|
||||
jne InHeap
|
||||
|
||||
NotInHeap:
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
|
||||
mov rcx, [rsi]
|
||||
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
|
||||
mov [rcx], rdx
|
||||
ret
|
||||
mov [rdi], rcx
|
||||
add rdi, 8h
|
||||
add rsi, 8h
|
||||
ret
|
||||
|
||||
InHeap:
|
||||
|
||||
; JIT_WriteBarrier may trash these registers
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
|
||||
mov rcx, rdi
|
||||
mov rdx, [rsi]
|
||||
add rdi, 8h
|
||||
add rsi, 8h
|
||||
|
||||
call CheckedEntry
|
||||
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
ret
|
||||
LEAF_END RhpByRefAssignRef, _TEXT
|
||||
|
||||
LEAF_ENTRY RhpCheckedLockCmpXchg, _TEXT
|
||||
|
|
|
@ -443,9 +443,17 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
|
|||
push rdx
|
||||
push r10
|
||||
|
||||
// also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
|
||||
// Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
|
||||
sub rsp, 16
|
||||
movdqu [rsp], xmm0
|
||||
|
||||
// void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
|
||||
call qword ptr [rdx + 8]
|
||||
|
||||
movdqu xmm0, [rsp]
|
||||
add rsp, 16
|
||||
|
||||
pop r10
|
||||
pop rdx
|
||||
pop rsi
|
||||
|
@ -460,29 +468,43 @@ LEAF_END_MARKED JIT_WriteBarrier, _TEXT
|
|||
// Entry:
|
||||
// RDI - address of ref-field (assigned to)
|
||||
// RSI - address of the data (source)
|
||||
// Note: RyuJIT assumes that all volatile registers can be trashed by
|
||||
// the CORINFO_HELP_ASSIGN_BYREF helper (i.e. JIT_ByRefWriteBarrier)
|
||||
// except RDI and RSI. This helper uses and defines RDI and RSI, so
|
||||
// they remain as live GC refs or byrefs, and are not killed.
|
||||
// Exit:
|
||||
// RCX is trashed
|
||||
// RAX is trashed
|
||||
// RDI, RSI are incremented by SIZEOF(LPVOID)
|
||||
LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
|
||||
// See if dst is in GCHeap
|
||||
PREPARE_EXTERNAL_VAR g_card_bundle_table, rax // fetch the page byte map
|
||||
mov rcx, rdi
|
||||
shr rcx, 30 // dst page index
|
||||
cmp byte ptr [rax + rcx], 0
|
||||
jne InHeap
|
||||
|
||||
mov rcx, [rsi]
|
||||
mov [rdi], rcx
|
||||
add rdi, 8
|
||||
add rsi, 8
|
||||
ret
|
||||
|
||||
InHeap:
|
||||
// JIT_WriteBarrier may trash these registers
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
|
||||
// save preadjusted rsi
|
||||
lea r10, [rsi + 8]
|
||||
mov rsi, [rsi]
|
||||
|
||||
// See if dst is in GCHeap
|
||||
PREPARE_EXTERNAL_VAR g_card_bundle_table, rax // fetch the page byte map
|
||||
mov rax, [rax]
|
||||
call CheckedEntry
|
||||
|
||||
mov r8, rdi
|
||||
shr r8, 30 // dst page index
|
||||
cmp byte ptr [rax + r8], 0
|
||||
jne C_FUNC(CheckedEntry)
|
||||
|
||||
NotInHeap_ByRefWriteBarrier:
|
||||
mov [rdi], rsi
|
||||
add rdi, 8
|
||||
mov rsi, r10
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
ret
|
||||
LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT
|
||||
|
||||
|
|
|
@ -376,17 +376,28 @@ endif
|
|||
mov r9, rsp
|
||||
and rsp, -16
|
||||
|
||||
; save rsp, rcx, rdx, r8 and have enough stack for the callee
|
||||
; save rsp, rcx, rdx, r8
|
||||
push r9
|
||||
push rcx
|
||||
push rdx
|
||||
push r8
|
||||
|
||||
; also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
|
||||
; Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
|
||||
sub rsp, 16
|
||||
movdqu [rsp], xmm0
|
||||
|
||||
; shadow space
|
||||
sub rsp, 20h
|
||||
|
||||
; void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
|
||||
call qword ptr [r8 + 8]
|
||||
|
||||
add rsp, 20h
|
||||
|
||||
movdqu xmm0, [rsp]
|
||||
add rsp, 16
|
||||
|
||||
pop r8
|
||||
pop rdx
|
||||
pop rcx
|
||||
|
@ -399,27 +410,45 @@ LEAF_END_MARKED JIT_WriteBarrier, _TEXT
|
|||
; Entry:
|
||||
; RDI - address of ref-field (assigned to)
|
||||
; RSI - address of the data (source)
|
||||
; Note: RyuJIT assumes that all volatile registers can be trashed by
|
||||
; the CORINFO_HELP_ASSIGN_BYREF helper (i.e. JIT_ByRefWriteBarrier)
|
||||
; except RDI and RSI. This helper uses and defines RDI and RSI, so
|
||||
; they remain as live GC refs or byrefs, and are not killed.
|
||||
; Exit:
|
||||
; RCX is trashed
|
||||
; RAX is trashed
|
||||
; RDI, RSI are incremented by SIZEOF(LPVOID)
|
||||
LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
|
||||
; See if dst is in GCHeap
|
||||
mov rax, [g_card_bundle_table] ; fetch the page byte map
|
||||
mov rcx, rdi
|
||||
shr rcx, 30 ; dst page index
|
||||
cmp byte ptr [rax + rcx], 0
|
||||
jne InHeap
|
||||
|
||||
mov rcx, [rsi]
|
||||
mov [rdi], rcx
|
||||
add rdi, 8h
|
||||
add rsi, 8h
|
||||
ret
|
||||
|
||||
InHeap:
|
||||
|
||||
; JIT_WriteBarrier may trash these registers
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
|
||||
mov rcx, rdi
|
||||
mov rdx, [rsi]
|
||||
add rdi, 8h
|
||||
add rsi, 8h
|
||||
|
||||
; See if dst is in GCHeap
|
||||
mov rax, [g_card_bundle_table] ; fetch the page byte map
|
||||
mov r8, rcx
|
||||
shr r8, 30 ; dst page index
|
||||
cmp byte ptr [rax + r8], 0
|
||||
jne CheckedEntry
|
||||
call CheckedEntry
|
||||
|
||||
NotInHeap:
|
||||
mov [rcx], rdx
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
ret
|
||||
LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue