Skip to content

Commit eb8d992

Browse files
authored
Make ByRefWriteBarrier to use the same call convention as in standard GC for R2R compatibility. (VSadov#56)
1 parent 5a8c497 commit eb8d992

File tree

5 files changed

+183
-79
lines changed

5 files changed

+183
-79
lines changed

src/coreclr/jit/targetamd64.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,11 @@
204204
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
205205
#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC
206206

207-
// TODO: Satori make more precise?
208-
// Registers killed by CORINFO_HELP_ASSIGN_BYREF.
209-
#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_TRASH_NOGC)
210-
211207
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF.
212-
#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_CALLEE_TRASH_NOGC & ~(RBM_RDI | RBM_RSI))
208+
#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_RAX | RBM_RCX)
209+
210+
// Registers killed by CORINFO_HELP_ASSIGN_BYREF.
211+
#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF)
213212

214213
// We have two register classifications
215214
// * callee trash: aka volatile or caller saved

src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ LEAF_ENTRY RhpAssignRef, _TEXT
400400

401401
JustAssign:
402402
ALTERNATE_ENTRY RhpAssignRefAVLocationNotHeap
403-
mov [rdi], rsi // no card marking, src is not a heap object
403+
mov [rdi], rsi // no card marking, src is not a heap object
404404
// set rdi, rsi per contract with JIT_ByRefWriteBarrier
405405
add rdi, 8
406406
mov rsi, r10
@@ -515,9 +515,17 @@ ALTERNATE_ENTRY RhpAssignRefAVLocation
515515
push rdx
516516
push r10
517517

518+
// also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
519+
// Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
520+
sub rsp, 16
521+
movdqu [rsp], xmm0
522+
518523
// void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
519524
call qword ptr [rdx + 8]
520525

526+
movdqu xmm0, [rsp]
527+
add rsp, 16
528+
521529
pop r10
522530
pop rdx
523531
pop rsi
@@ -529,31 +537,48 @@ LEAF_END RhpAssignRef, _TEXT
529537
//
530538
// RhpByRefAssignRef simulates movs instruction for object references.
531539
//
532-
// On entry:
533-
// rdi: address of ref-field (assigned to)
534-
// rsi: address of the data (source)
535-
//
536-
// On exit:
537-
// rdi, rsi are incremented by 8,
538-
// rdi, rdx, r9, r10, r11: trashed
539-
//
540+
// Entry:
541+
// RDI - address of ref-field (assigned to)
542+
// RSI - address of the data (source)
543+
// Exit:
544+
// RCX is trashed
545+
// RAX is trashed
546+
// RDI, RSI are incremented by SIZEOF(LPVOID)
540547
LEAF_ENTRY RhpByRefAssignRef, _TEXT
541-
lea r10, [rsi + 8]
542-
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
543-
mov rsi, [rsi]
544-
545-
// See if dst is in GCHeap
548+
// See if dst is in GCHeap
546549
mov rax, [C_VAR(g_card_bundle_table)] // fetch the page byte map
547-
mov r8, rdi
548-
shr r8, 30 // dst page index
549-
cmp byte ptr [rax + r8], 0
550-
jne C_FUNC(CheckedEntry)
550+
mov rcx, rdi
551+
shr rcx, 30 // dst page index
552+
cmp byte ptr [rax + rcx], 0
553+
jne InHeap
551554

552-
NotInHeap_RhpByRefAssignRef:
555+
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
556+
mov rcx, [rsi]
553557
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
554-
mov [rdi], rsi
558+
mov [rdi], rcx
555559
add rdi, 8
556-
mov rsi, r10
560+
add rsi, 8
561+
ret
562+
563+
InHeap:
564+
// JIT_WriteBarrier may trash these registers
565+
push rdx
566+
push r8
567+
push r9
568+
push r10
569+
push r11
570+
571+
// save preadjusted rsi
572+
lea r10, [rsi + 8]
573+
mov rsi, [rsi]
574+
575+
call CheckedEntry
576+
577+
pop r11
578+
pop r10
579+
pop r9
580+
pop r8
581+
pop rdx
557582
ret
558583
LEAF_END RhpByRefAssignRef, _TEXT
559584

src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.asm

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -508,17 +508,28 @@ ALTERNATE_ENTRY RhpAssignRefAVLocation
508508
mov r9, rsp
509509
and rsp, -16
510510

511-
; save rsp, rcx, rdx, r8 and have enough stack for the callee
511+
; save rsp, rcx, rdx, r8
512512
push r9
513513
push rcx
514514
push rdx
515515
push r8
516+
517+
; also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
518+
; Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
519+
sub rsp, 16
520+
movdqu [rsp], xmm0
521+
522+
; shadow space
516523
sub rsp, 20h
517524

518525
; void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
519526
call qword ptr [r8 + 8]
520527

521528
add rsp, 20h
529+
530+
movdqu xmm0, [rsp]
531+
add rsp, 16
532+
522533
pop r8
523534
pop rdx
524535
pop rcx
@@ -528,33 +539,51 @@ LEAF_END RhpAssignRef, _TEXT
528539

529540
;;
530541
;; RhpByRefAssignRef simulates movs instruction for object references.
531-
;;
532-
;; On entry:
533-
;; rdi: address of ref-field (assigned to)
534-
;; rsi: address of the data (source)
535-
;;
536-
;; On exit:
537-
;; rdi, rsi are incremented by 8,
538-
;; rcx, r8, r9, r11: trashed
539-
;;
542+
;; Entry:
543+
;; RDI - address of ref-field (assigned to)
544+
;; RSI - address of the data (source)
545+
;; Exit:
546+
;; RCX is trashed
547+
;; RAX is trashed
548+
;; RDI, RSI are incremented by SIZEOF(LPVOID)
540549
LEAF_ENTRY RhpByRefAssignRef, _TEXT
541-
mov rcx, rdi
542-
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
543-
mov rdx, [rsi]
544-
add rdi, 8h
545-
add rsi, 8h
546-
547550
; See if dst is in GCHeap
548-
mov rax, [g_card_bundle_table] ; fetch the page byte map
549-
mov r8, rcx
550-
shr r8, 30 ; dst page index
551-
cmp byte ptr [rax + r8], 0
552-
jne CheckedEntry
551+
mov rax, [g_card_bundle_table] ; fetch the page byte map
552+
mov rcx, rdi
553+
shr rcx, 30 ; dst page index
554+
cmp byte ptr [rax + rcx], 0
555+
jne InHeap
553556

554-
NotInHeap:
557+
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
558+
mov rcx, [rsi]
555559
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
556-
mov [rcx], rdx
557-
ret
560+
mov [rdi], rcx
561+
add rdi, 8h
562+
add rsi, 8h
563+
ret
564+
565+
InHeap:
566+
567+
; JIT_WriteBarrier may trash these registers
568+
push rdx
569+
push r8
570+
push r9
571+
push r10
572+
push r11
573+
574+
mov rcx, rdi
575+
mov rdx, [rsi]
576+
add rdi, 8h
577+
add rsi, 8h
578+
579+
call CheckedEntry
580+
581+
pop r11
582+
pop r10
583+
pop r9
584+
pop r8
585+
pop rdx
586+
ret
558587
LEAF_END RhpByRefAssignRef, _TEXT
559588

560589
LEAF_ENTRY RhpCheckedLockCmpXchg, _TEXT

src/coreclr/vm/amd64/patchedcode.S

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,17 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
443443
push rdx
444444
push r10
445445

446+
// also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
447+
// Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
448+
sub rsp, 16
449+
movdqu [rsp], xmm0
450+
446451
// void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
447452
call qword ptr [rdx + 8]
448453

454+
movdqu xmm0, [rsp]
455+
add rsp, 16
456+
449457
pop r10
450458
pop rdx
451459
pop rsi
@@ -460,29 +468,43 @@ LEAF_END_MARKED JIT_WriteBarrier, _TEXT
460468
// Entry:
461469
// RDI - address of ref-field (assigned to)
462470
// RSI - address of the data (source)
463-
// Note: RyuJIT assumes that all volatile registers can be trashed by
464-
// the CORINFO_HELP_ASSIGN_BYREF helper (i.e. JIT_ByRefWriteBarrier)
465-
// except RDI and RSI. This helper uses and defines RDI and RSI, so
466-
// they remain as live GC refs or byrefs, and are not killed.
467471
// Exit:
472+
// RCX is trashed
473+
// RAX is trashed
468474
// RDI, RSI are incremented by SIZEOF(LPVOID)
469475
LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
470-
lea r10, [rsi + 8]
471-
mov rsi, [rsi]
472-
473476
// See if dst is in GCHeap
474477
PREPARE_EXTERNAL_VAR g_card_bundle_table, rax // fetch the page byte map
475-
mov rax, [rax]
476-
477-
mov r8, rdi
478-
shr r8, 30 // dst page index
479-
cmp byte ptr [rax + r8], 0
480-
jne C_FUNC(CheckedEntry)
478+
mov rcx, rdi
479+
shr rcx, 30 // dst page index
480+
cmp byte ptr [rax + rcx], 0
481+
jne InHeap
481482

482-
NotInHeap_ByRefWriteBarrier:
483-
mov [rdi], rsi
483+
mov rcx, [rsi]
484+
mov [rdi], rcx
484485
add rdi, 8
485-
mov rsi, r10
486+
add rsi, 8
487+
ret
488+
489+
InHeap:
490+
// JIT_WriteBarrier may trash these registers
491+
push rdx
492+
push r8
493+
push r9
494+
push r10
495+
push r11
496+
497+
// save preadjusted rsi
498+
lea r10, [rsi + 8]
499+
mov rsi, [rsi]
500+
501+
call CheckedEntry
502+
503+
pop r11
504+
pop r10
505+
pop r9
506+
pop r8
507+
pop rdx
486508
ret
487509
LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT
488510

src/coreclr/vm/amd64/patchedcode.asm

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -376,17 +376,28 @@ endif
376376
mov r9, rsp
377377
and rsp, -16
378378

379-
; save rsp, rcx, rdx, r8 and have enough stack for the callee
379+
; save rsp, rcx, rdx, r8
380380
push r9
381381
push rcx
382382
push rdx
383383
push r8
384+
385+
; also save xmm0, in case it is used for stack clearing, as JIT_ByRefWriteBarrier should not trash xmm0
386+
; Hopefully EscapeFn cannot corrupt other xmm regs, since there is no float math or vectorizable code in there.
387+
sub rsp, 16
388+
movdqu [rsp], xmm0
389+
390+
; shadow space
384391
sub rsp, 20h
385392

386393
; void SatoriRegion::EscapeFn(SatoriObject** dst, SatoriObject* src, SatoriRegion* region)
387394
call qword ptr [r8 + 8]
388395

389396
add rsp, 20h
397+
398+
movdqu xmm0, [rsp]
399+
add rsp, 16
400+
390401
pop r8
391402
pop rdx
392403
pop rcx
@@ -399,27 +410,45 @@ LEAF_END_MARKED JIT_WriteBarrier, _TEXT
399410
; Entry:
400411
; RDI - address of ref-field (assigned to)
401412
; RSI - address of the data (source)
402-
; Note: RyuJIT assumes that all volatile registers can be trashed by
403-
; the CORINFO_HELP_ASSIGN_BYREF helper (i.e. JIT_ByRefWriteBarrier)
404-
; except RDI and RSI. This helper uses and defines RDI and RSI, so
405-
; they remain as live GC refs or byrefs, and are not killed.
406413
; Exit:
414+
; RCX is trashed
415+
; RAX is trashed
407416
; RDI, RSI are incremented by SIZEOF(LPVOID)
408417
LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
418+
; See if dst is in GCHeap
419+
mov rax, [g_card_bundle_table] ; fetch the page byte map
420+
mov rcx, rdi
421+
shr rcx, 30 ; dst page index
422+
cmp byte ptr [rax + rcx], 0
423+
jne InHeap
424+
425+
mov rcx, [rsi]
426+
mov [rdi], rcx
427+
add rdi, 8h
428+
add rsi, 8h
429+
ret
430+
431+
InHeap:
432+
433+
; JIT_WriteBarrier may trash these registers
434+
push rdx
435+
push r8
436+
push r9
437+
push r10
438+
push r11
439+
409440
mov rcx, rdi
410441
mov rdx, [rsi]
411442
add rdi, 8h
412443
add rsi, 8h
413444

414-
; See if dst is in GCHeap
415-
mov rax, [g_card_bundle_table] ; fetch the page byte map
416-
mov r8, rcx
417-
shr r8, 30 ; dst page index
418-
cmp byte ptr [rax + r8], 0
419-
jne CheckedEntry
445+
call CheckedEntry
420446

421-
NotInHeap:
422-
mov [rcx], rdx
447+
pop r11
448+
pop r10
449+
pop r9
450+
pop r8
451+
pop rdx
423452
ret
424453
LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT
425454

0 commit comments

Comments
 (0)