Skip to content

Commit 13876e9

Browse files
Fix write barriers in NativeAOT (#74455)
Co-authored-by: Anton Lapounov <antonl@microsoft.com>
1 parent fdd9a86 commit 13876e9

File tree

7 files changed

+36
-31
lines changed

7 files changed

+36
-31
lines changed

src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ FORCEINLINE void InlinedBulkWriteBarrier(void* pMemStart, size_t cbMemSize)
229229
// Compute the shadow heap address corresponding to the beginning of the range of heap addresses modified
230230
// and in the process range check it to make sure we have the shadow version allocated.
231231
uintptr_t* shadowSlot = (uintptr_t*)(g_GCShadow + ((uint8_t*)pMemStart - g_lowest_address));
232-
if (shadowSlot <= (uintptr_t*)g_GCShadowEnd)
232+
if (shadowSlot < (uintptr_t*)g_GCShadowEnd)
233233
{
234234
// Iterate over every pointer sized slot in the range, copying data from the real heap to the shadow heap.
235235
// As we perform each copy we need to recheck the real heap contents with an ordered read to ensure we're
@@ -239,6 +239,7 @@ FORCEINLINE void InlinedBulkWriteBarrier(void* pMemStart, size_t cbMemSize)
239239

240240
uintptr_t* realSlot = (uintptr_t*)pMemStart;
241241
uintptr_t slotCount = cbMemSize / sizeof(uintptr_t);
242+
ASSERT(slotCount < (uintptr_t*)g_GCShadowEnd - shadowSlot);
242243
do
243244
{
244245
// Update shadow slot from real slot.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
jb LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG)
2828
add \DESTREG, [C_VAR(g_GCShadow)]
2929
cmp \DESTREG, [C_VAR(g_GCShadowEnd)]
30-
ja LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG)
30+
jae LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG)
3131

3232
// Update the shadow heap.
3333
mov [\DESTREG], \REFREG

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ UPDATE_GC_SHADOW macro BASENAME, REFREG, DESTREG
4343
jb &BASENAME&_UpdateShadowHeap_PopThenDone_&REFREG&
4444
add DESTREG, [g_GCShadow]
4545
cmp DESTREG, [g_GCShadowEnd]
46-
ja &BASENAME&_UpdateShadowHeap_PopThenDone_&REFREG&
46+
jae &BASENAME&_UpdateShadowHeap_PopThenDone_&REFREG&
4747

4848
;; Update the shadow heap.
4949
mov [DESTREG], REFREG

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
ldr r12, =C_FUNC(g_GCShadowEnd)
3939
ldr r12, [r12]
4040
cmp \DESTREG, r12
41-
jhi LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG)
41+
bhs LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG)
4242

4343
// Update the shadow heap.
4444
str \REFREG, [\DESTREG]
@@ -105,15 +105,15 @@ LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG):
105105

106106
// If the reference is to an object that's not in an ephemeral generation we have no need to track it
107107
// (since the object won't be collected or moved by an ephemeral collection).
108-
ldr r12, =C_FUNC(g_ephemeral_low)
108+
ldr r12, =C_FUNC(g_ephemeral_low)
109109
ldr r12, [r12]
110110
cmp \REFREG, r12
111111
blo LOCAL_LABEL(\BASENAME\()_EXIT_\REFREG)
112112

113-
ldr r12, =C_FUNC(g_ephemeral_high)
113+
ldr r12, =C_FUNC(g_ephemeral_high)
114114
ldr r12, [r12]
115-
cmp \REFREG, r12
116-
bhi LOCAL_LABEL(\BASENAME\()_EXIT_\REFREG)
115+
cmp \REFREG, r12
116+
bhs LOCAL_LABEL(\BASENAME\()_EXIT_\REFREG)
117117

118118
// We have a location on the GC heap being updated with a reference to an ephemeral object so we must
119119
// track this write. The location address is translated into an offset in the card table bitmap. We set
@@ -167,11 +167,11 @@ ALTERNATE_ENTRY RhpAssignRef
167167
//
168168
// Note that none of this is relevant for single cpu machines. We may choose to implement a
169169
// uniprocessor specific version of this barrier if uni-proc becomes a significant scenario again.
170-
dmb
170+
dmb
171171

172172
// Write the reference into the location. Note that we rely on the fact that no GC can occur between here
173173
// and the card table update we may perform below.
174-
ALTERNATE_ENTRY "RhpAssignRefAvLocation"\EXPORT_REG_NAME // WriteBarrierFunctionAvLocation
174+
ALTERNATE_ENTRY "RhpAssignRefAvLocation"\EXPORT_REG_NAME // WriteBarrierFunctionAvLocation
175175
.ifc \REFREG, r1
176176
ALTERNATE_ENTRY RhpAssignRefAVLocation
177177
.endif
@@ -198,14 +198,14 @@ DEFINE_UNCHECKED_WRITE_BARRIER r1, r1
198198

199199
// The location being updated might not even lie in the GC heap (a handle or stack location for instance),
200200
// in which case no write barrier is required.
201-
ldr r12, =C_FUNC(g_lowest_address)
201+
ldr r12, =C_FUNC(g_lowest_address)
202202
ldr r12, [r12]
203203
cmp r0, r12
204204
blo LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG)
205-
ldr r12, =C_FUNC(g_highest_address)
205+
ldr r12, =C_FUNC(g_highest_address)
206206
ldr r12, [r12]
207207
cmp r0, r12
208-
bhi LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG)
208+
bhs LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG)
209209

210210
DEFINE_UNCHECKED_WRITE_BARRIER_CORE \BASENAME, \REFREG
211211

@@ -270,7 +270,7 @@ LEAF_ENTRY RhpCheckedLockCmpXchg, _TEXT
270270
// barrier must occur before the object reference update, so we have to do it unconditionally even
271271
// though the update may fail below.
272272
dmb
273-
ALTERNATE_ENTRY RhpCheckedLockCmpXchgAVLocation
273+
ALTERNATE_ENTRY RhpCheckedLockCmpXchgAVLocation
274274
LOCAL_LABEL(RhpCheckedLockCmpXchgRetry):
275275
ldrex r3, [r0]
276276
cmp r2, r3
@@ -337,7 +337,7 @@ LEAF_ENTRY RhpByRefAssignRef, _TEXT
337337
ldr r3, =C_FUNC(g_highest_address)
338338
ldr r3, [r3]
339339
cmp r0, r3
340-
bhi LOCAL_LABEL(RhpByRefAssignRef_NotInHeap)
340+
bhs LOCAL_LABEL(RhpByRefAssignRef_NotInHeap)
341341

342342
// Update the shadow copy of the heap with the same value just written to the same heap. (A no-op unless
343343
// we're in a debug build and write barrier checking has been enabled).
@@ -352,7 +352,7 @@ LEAF_ENTRY RhpByRefAssignRef, _TEXT
352352
ldr r3, =C_FUNC(g_ephemeral_high)
353353
ldr r3, [r3]
354354
cmp r2, r3
355-
bhi LOCAL_LABEL(RhpByRefAssignRef_NotInHeap)
355+
bhs LOCAL_LABEL(RhpByRefAssignRef_NotInHeap)
356356

357357
// move current r0 value into r2 and then increment the pointers
358358
mov r2, r0

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@
3838
// Transform destReg into the equivalent address in the shadow heap.
3939
PREPARE_EXTERNAL_VAR_INDIRECT g_lowest_address, X9
4040
subs \destReg, \destReg, x9
41-
blt 0f
41+
blo 0f
4242

4343
PREPARE_EXTERNAL_VAR_INDIRECT g_GCShadow, X9
4444
add \destReg, \destReg, x9
4545

4646
PREPARE_EXTERNAL_VAR_INDIRECT g_GCShadowEnd, X9
4747
cmp \destReg, x9
48-
bgt 0f
48+
bhs 0f
4949

5050
// Update the shadow heap.
5151
str \refReg, [\destReg]
@@ -120,11 +120,11 @@
120120
// an object not on the epehemeral segment.
121121
PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_low, x\trash
122122
cmp \refReg, x\trash
123-
blt 0f
123+
blo 0f
124124

125125
PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_high, x\trash
126126
cmp \refReg, x\trash
127-
bge 0f
127+
bhs 0f
128128

129129
// Set this objects card, if it has not already been set.
130130

@@ -172,11 +172,13 @@
172172

173173
PREPARE_EXTERNAL_VAR_INDIRECT g_lowest_address, x\trash
174174
cmp \destReg, x\trash
175-
blt 0f
176175

177176
PREPARE_EXTERNAL_VAR_INDIRECT g_highest_address, x\trash
178-
cmp \destReg, x\trash
179-
bgt 0f
177+
178+
// If \destReg >= g_lowest_address, compare \destReg to g_highest_address.
179+
// Otherwise, set the C flag (0x2) to take the next branch.
180+
ccmp \destReg, x\trash, #0x2, hs
181+
bhs 0f
180182

181183
INSERT_UNCHECKED_WRITE_BARRIER_CORE \destReg, \refReg, \trash, \trash2
182184

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ INVALIDGCVALUE EQU 0xCCCCCCCD
5454
adrp x12, g_lowest_address
5555
ldr x12, [x12, g_lowest_address]
5656
subs $destReg, $destReg, x12
57-
blt %ft0
57+
blo %ft0
5858

5959
adrp x12, $g_GCShadow
6060
ldr x12, [x12, $g_GCShadow]
@@ -63,7 +63,7 @@ INVALIDGCVALUE EQU 0xCCCCCCCD
6363
adrp x12, $g_GCShadowEnd
6464
ldr x12, [x12, $g_GCShadowEnd]
6565
cmp $destReg, x12
66-
bgt %ft0
66+
bhs %ft0
6767

6868
;; Update the shadow heap.
6969
str $refReg, [$destReg]
@@ -127,12 +127,12 @@ INVALIDGCVALUE EQU 0xCCCCCCCD
127127
adrp x12, g_ephemeral_low
128128
ldr x12, [x12, g_ephemeral_low]
129129
cmp $refReg, x12
130-
blt %ft0
130+
blo %ft0
131131

132132
adrp x12, g_ephemeral_high
133133
ldr x12, [x12, g_ephemeral_high]
134134
cmp $refReg, x12
135-
bge %ft0
135+
bhs %ft0
136136

137137
;; Set this object's card, if it hasn't already been set.
138138
adrp x12, g_card_table
@@ -170,12 +170,14 @@ INVALIDGCVALUE EQU 0xCCCCCCCD
170170
adrp x12, g_lowest_address
171171
ldr x12, [x12, g_lowest_address]
172172
cmp $destReg, x12
173-
blt %ft0
174173

175174
adrp x12, g_highest_address
176175
ldr x12, [x12, g_highest_address]
177-
cmp $destReg, x12
178-
bgt %ft0
176+
177+
;; If $destReg >= g_lowest_address, compare $destReg to g_highest_address.
178+
;; Otherwise, set the C flag (0x2) to take the next branch.
179+
ccmp $destReg, x12, #0x2, hs
180+
bhs %ft0
179181

180182
INSERT_UNCHECKED_WRITE_BARRIER_CORE $destReg, $refReg, $trashReg
181183

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ UPDATE_GC_SHADOW macro BASENAME, DESTREG, REFREG
4848
jb &BASENAME&_UpdateShadowHeap_PopThenDone_&DESTREG&_&REFREG&
4949
add DESTREG, [g_GCShadow]
5050
cmp DESTREG, [g_GCShadowEnd]
51-
ja &BASENAME&_UpdateShadowHeap_PopThenDone_&DESTREG&_&REFREG&
51+
jae &BASENAME&_UpdateShadowHeap_PopThenDone_&DESTREG&_&REFREG&
5252

5353
;; Update the shadow heap.
5454
mov [DESTREG], REFREG

0 commit comments

Comments
 (0)