5b67d14a605364a6ffc58e9c1f57ed364cbe5fb0
[platform/upstream/coreclr.git] / src / vm / amd64 / jithelpers_slow.S
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 .intel_syntax noprefix
6 #include "unixasmmacros.inc"
7
8 #ifdef _DEBUG
9 // Version for when we're sure to be in the GC, checks whether or not the card
10 // needs to be updated
11 //
12 // void JIT_WriteBarrier_Debug(Object** dst, Object* src)
13 LEAF_ENTRY JIT_WriteBarrier_Debug, _TEXT
14
15 #ifdef WRITE_BARRIER_CHECK
16         // **ALSO update the shadow GC heap if that is enabled**
17         // Do not perform the work if g_GCShadow is 0
18         PREPARE_EXTERNAL_VAR g_GCShadow, rax
19         cmp     qword ptr [rax], 0
20         je      NoShadow
21
22         // If we end up outside of the heap don't corrupt random memory
23         mov     r10, rdi
24         PREPARE_EXTERNAL_VAR g_lowest_address, r11
25         sub     r10, [r11]
26         jb      NoShadow
27
28         // Check that our adjusted destination is somewhere in the shadow gc
29         add     r10, [rax]
30         PREPARE_EXTERNAL_VAR g_GCShadowEnd, r11
31         cmp     r10, [r11]
32         ja      NoShadow
33
34         // Write ref into real GC// see comment below about possibility of AV
35         mov     [rdi], rsi
36         // Write ref into shadow GC
37         mov     [r10], rsi
38
39         // Ensure that the write to the shadow heap occurs before the read from
40         // the GC heap so that race conditions are caught by INVALIDGCVALUE
41         mfence
42
43         // Check that GC/ShadowGC values match
44         mov     r11, [rdi]
45         mov     rax, [r10]
46         cmp     rax, r11
47         je      DoneShadow
48         mov     r11, INVALIDGCVALUE
49         mov     [r10], r11
50
51         jmp     DoneShadow
52
53     // If we don't have a shadow GC we won't have done the write yet
54     NoShadow:
55 #endif
56
57         mov     rax, rsi
58
59         // Do the move. It is correct to possibly take an AV here, the EH code
60         // figures out that this came from a WriteBarrier and correctly maps it back
61         // to the managed method which called the WriteBarrier (see setup in
62         // InitializeExceptionHandling, vm\exceptionhandling.cpp).
63         mov     [rdi], rax
64
65 #ifdef WRITE_BARRIER_CHECK
66     // If we had a shadow GC then we already wrote to the real GC at the same time
67     // as the shadow GC so we want to jump over the real write immediately above
68     DoneShadow:
69 #endif
70
71         // See if we can just quick out
72         PREPARE_EXTERNAL_VAR g_ephemeral_low, r10
73         cmp     rax, [r10]
74         jb      Exit_Debug
75         PREPARE_EXTERNAL_VAR g_ephemeral_high, r10
76         cmp     rax, [r10]
77         jnb     Exit_Debug
78
79         // Check if we need to update the card table
80         // Calc pCardByte
81         shr     rdi, 0Bh
82         PREPARE_EXTERNAL_VAR g_card_table, r10
83         add     rdi, [r10]
84
85         // Check if this card is dirty
86         cmp     byte ptr [rdi], 0FFh
87         jne     UpdateCardTable_Debug
88         REPRET
89
90     UpdateCardTable_Debug:
91         mov     byte ptr [rdi], 0FFh
92         ret
93
94     .balign 16
95     Exit_Debug:
96         REPRET
97 LEAF_END_MARKED JIT_WriteBarrier_Debug, _TEXT
98 #endif
99