@@ -100,6 +100,21 @@ DEFINE_UNCHECKED_WRITE_BARRIER_CORE macro BASENAME, REFREG
100100 ;; we're in a debug build and write barrier checking has been enabled).
101101 UPDATE_GC_SHADOW BASENAME , REFREG , rcx
102102
103+ ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
104+ mov r11 , [ g_write_watch_table ]
105+ cmp r11 , 0
106+ je &BASENAME&_CheckCardTable_&REFREG&
107+
108+ mov r10 , rcx
109+ shr r10 , 0Ch ;; SoftwareWriteWatch::AddressToTableByteIndexShift
110+ add r10 , r11
111+ cmp byte ptr [ r10 ], 0
112+ jne &BASENAME&_CheckCardTable_&REFREG&
113+ mov byte ptr [ r10 ], 0FFh
114+ endif
115+
116+ &BASENAME&_CheckCardTable_&REFREG&:
117+
103118 ;; If the reference is to an object that's not in an ephemeral generation we have no need to track it
104119 ;; (since the object won't be collected or moved by an ephemeral collection).
105120 cmp REFREG , [ g_ephemeral_low ]
@@ -111,17 +126,25 @@ DEFINE_UNCHECKED_WRITE_BARRIER_CORE macro BASENAME, REFREG
111126 ;; track this write. The location address is translated into an offset in the card table bitmap. We set
112127 ;; an entire byte in the card table since it's quicker than messing around with bitmasks and we only write
113128 ;; the byte if it hasn't already been done since writes are expensive and impact scaling.
114- shr rcx , 11
115- add rcx , [ g_card_table ]
129+ shr rcx , 0Bh
130+ mov r10 , [ g_card_table ]
131+ cmp byte ptr [ rcx + r10 ], 0FFh
132+ je &BASENAME&_NoBarrierRequired_&REFREG&
133+
134+ ;; We get here if it's necessary to update the card table.
135+ mov byte ptr [ rcx + r10 ], 0FFh
136+
137+ ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
138+ ;; Shift rcx by 0Ah more to get the card bundle byte (we shifted by 0x0B already)
139+ shr rcx , 0Ah
140+ add rcx , [ g_card_bundle_table ]
116141 cmp byte ptr [ rcx ], 0FFh
117- jne &BASENAME&_UpdateCardTable_&REFREG&
118-
119- &BASENAME&_NoBarrierRequired_&REFREG&:
120- ret
142+ je &BASENAME&_NoBarrierRequired_&REFREG&
121143
122- ;; We get here if it's necessary to update the card table.
123- &BASENAME&_UpdateCardTable_&REFREG&:
124144 mov byte ptr [ rcx ], 0FFh
145+ endif
146+
147+ &BASENAME&_NoBarrierRequired_&REFREG&:
125148 ret
126149
127150endm
@@ -248,55 +271,74 @@ LEAF_END RhpCheckedXchg, _TEXT
248271;; On entry:
249272;; rdi: address of ref-field (assigned to)
250273;; rsi: address of the data (source)
251- ;; rcx: be trashed
252274;;
253275;; On exit:
254276;; rdi, rsi are incremented by 8,
255- ;; rcx: trashed
277+ ;; rcx, r10, r11 : trashed
256278;;
257279LEAF_ENTRY RhpByRefAssignRef , _TEXT
258280 mov rcx , [ rsi ]
259281 mov [ rdi ], rcx
260282
261283 ;; Check whether the writes were even into the heap. If not there's no card update required.
262284 cmp rdi , [ g_lowest_address ]
263- jb RhpByRefAssignRef_NotInHeap
285+ jb RhpByRefAssignRef_NoBarrierRequired
264286 cmp rdi , [ g_highest_address ]
265- jae RhpByRefAssignRef_NotInHeap
287+ jae RhpByRefAssignRef_NoBarrierRequired
266288
267289 ;; Update the shadow copy of the heap with the same value just written to the same heap. (A no-op unless
268290 ;; we're in a debug build and write barrier checking has been enabled).
269291 UPDATE_GC_SHADOW BASENAME , rcx , rdi
270292
293+ ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
294+ mov r11 , [ g_write_watch_table ]
295+ cmp r11 , 0
296+ je RhpByRefAssignRef_CheckCardTable
297+
298+ mov r10 , rdi
299+ shr r10 , 0Ch ;; SoftwareWriteWatch::AddressToTableByteIndexShift
300+ add r10 , r11
301+ cmp byte ptr [ r10 ], 0
302+ jne RhpByRefAssignRef_CheckCardTable
303+ mov byte ptr [ r10 ], 0FFh
304+ endif
305+
306+ RhpByRefAssignRef_CheckCardTable:
307+
271308 ;; If the reference is to an object that's not in an ephemeral generation we have no need to track it
272309 ;; (since the object won't be collected or moved by an ephemeral collection).
273310 cmp rcx , [ g_ephemeral_low ]
274- jb RhpByRefAssignRef_NotInHeap
311+ jb RhpByRefAssignRef_NoBarrierRequired
275312 cmp rcx , [ g_ephemeral_high ]
276- jae RhpByRefAssignRef_NotInHeap
313+ jae RhpByRefAssignRef_NoBarrierRequired
277314
278- ;; move current rdi value into rcx and then increment the pointers
315+ ;; move current rdi value into rcx, we need to keep rdi and eventually increment by 8
279316 mov rcx , rdi
280- add rsi , 8h
281- add rdi , 8h
282317
283318 ;; We have a location on the GC heap being updated with a reference to an ephemeral object so we must
284319 ;; track this write. The location address is translated into an offset in the card table bitmap. We set
285320 ;; an entire byte in the card table since it's quicker than messing around with bitmasks and we only write
286321 ;; the byte if it hasn't already been done since writes are expensive and impact scaling.
287- shr rcx , 11
288- add rcx , [ g_card_table ]
289- cmp byte ptr [ rcx ], 0FFh
290- jne RhpByRefAssignRef_UpdateCardTable
291- ret
322+ shr rcx , 0Bh
323+ mov r10 , [ g_card_table ]
324+ cmp byte ptr [ rcx + r10 ], 0FFh
325+ je RhpByRefAssignRef_NoBarrierRequired
292326
293327;; We get here if it's necessary to update the card table.
294- RhpByRefAssignRef_UpdateCardTable:
328+ mov byte ptr [ rcx + r10 ], 0FFh
329+
330+ ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
331+ ;; Shift rcx by 0Ah more to get the card bundle byte (we shifted by 0Bh already)
332+ shr rcx , 0Ah
333+ add rcx , [ g_card_bundle_table ]
334+ cmp byte ptr [ rcx ], 0FFh
335+ je RhpByRefAssignRef_NoBarrierRequired
336+
295337 mov byte ptr [ rcx ], 0FFh
296- ret
338+ endif
297339
298- RhpByRefAssignRef_NotInHeap :
299- ; Increment the pointers before leaving
340+ RhpByRefAssignRef_NoBarrierRequired :
341+ ;; Increment the pointers before leaving
300342 add rdi , 8h
301343 add rsi , 8h
302344 ret
0 commit comments