Untitled diff
69 लाइनें
LEAF_ENTRY RhpByRefAssignRef, _TEXT
LEAF_ENTRY RhpByRefAssignRefBatch, _TEXT
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
RhpByRefAssignRefBatch_NextByref:
ALTERNATE_ENTRY RhpByRefAssignRefBatchAVLocation1
mov rcx, [rsi]
mov rcx, [rsi]
ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
ALTERNATE_ENTRY RhpByRefAssignRefBatchAVLocation2
mov [rdi], rcx
mov [rdi], rcx
;; Check whether the writes were even into the heap. If not there's no card update required.
;; Check whether the writes were even into the heap. If not there's no card update required.
cmp rdi, [g_lowest_address]
cmp rdi, [g_lowest_address]
jb RhpByRefAssignRef_NoBarrierRequired
jb RhpByRefAssignRefBatch_NotInHeap
cmp rdi, [g_highest_address]
cmp rdi, [g_highest_address]
jae RhpByRefAssignRef_NoBarrierRequired
jae RhpByRefAssignRefBatch_NotInHeap
;; Update the shadow copy of the heap with the same value just written to the same heap. (A no-op unless
;; Update the shadow copy of the heap with the same value just written to the same heap. (A no-op unless
;; we're in a debug build and write barrier checking has been enabled).
;; we're in a debug build and write barrier checking has been enabled).
UPDATE_GC_SHADOW BASENAME, rcx, rdi
UPDATE_GC_SHADOW BASENAME, rcx, rdi
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
mov r11, [g_write_watch_table]
mov r11, [g_write_watch_table]
cmp r11, 0
cmp r11, 0
je RhpByRefAssignRef_CheckCardTable
je RhpByRefAssignRefBatch_CheckCardTable
mov r10, rdi
mov r10, rdi
shr r10, 0Ch ;; SoftwareWriteWatch::AddressToTableByteIndexShift
shr r10, 0Ch ;; SoftwareWriteWatch::AddressToTableByteIndexShift
add r10, r11
add r10, r11
cmp byte ptr [r10], 0
cmp byte ptr [r10], 0
jne RhpByRefAssignRef_CheckCardTable
jne RhpByRefAssignRefBatch_CheckCardTable
mov byte ptr [r10], 0FFh
mov byte ptr [r10], 0FFh
endif
endif
RhpByRefAssignRef_CheckCardTable:
RhpByRefAssignRefBatch_CheckCardTable:
;; If the reference is to an object that's not in an ephemeral generation we have no need to track it
;; If the reference is to an object that's not in an ephemeral generation we have no need to track it
;; (since the object won't be collected or moved by an ephemeral collection).
;; (since the object won't be collected or moved by an ephemeral collection).
cmp rcx, [g_ephemeral_low]
cmp rcx, [g_ephemeral_low]
jb RhpByRefAssignRef_NoBarrierRequired
jb RhpByRefAssignRefBatch_NoBarrierRequired
cmp rcx, [g_ephemeral_high]
cmp rcx, [g_ephemeral_high]
jae RhpByRefAssignRef_NoBarrierRequired
jae RhpByRefAssignRefBatch_NoBarrierRequired
;; move current rdi value into rcx, we need to keep rdi and eventually increment by 8
;; move current rdi value into rcx, we need to keep rdi and eventually increment by 8
mov rcx, rdi
mov rcx, rdi
;; We have a location on the GC heap being updated with a reference to an ephemeral object so we must
;; We have a location on the GC heap being updated with a reference to an ephemeral object so we must
;; track this write. The location address is translated into an offset in the card table bitmap. We set
;; track this write. The location address is translated into an offset in the card table bitmap. We set
;; an entire byte in the card table since it's quicker than messing around with bitmasks and we only write
;; an entire byte in the card table since it's quicker than messing around with bitmasks and we only write
;; the byte if it hasn't already been done since writes are expensive and impact scaling.
;; the byte if it hasn't already been done since writes are expensive and impact scaling.
shr rcx, 0Bh
shr rcx, 0Bh
mov r10, [g_card_table]
mov r10, [g_card_table]
cmp byte ptr [rcx + r10], 0FFh
cmp byte ptr [rcx + r10], 0FFh
je RhpByRefAssignRef_NoBarrierRequired
je RhpByRefAssignRefBatch_NoBarrierRequired
;; We get here if it's necessary to update the card table.
;; We get here if it's necessary to update the card table.
mov byte ptr [rcx + r10], 0FFh
mov byte ptr [rcx + r10], 0FFh
ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
;; Shift rcx by 0Ah more to get the card bundle byte (we shifted by 0Bh already)
;; Shift rcx by 0Ah more to get the card bundle byte (we shifted by 0Bh already)
shr rcx, 0Ah
shr rcx, 0Ah
add rcx, [g_card_bundle_table]
add rcx, [g_card_bundle_table]
cmp byte ptr [rcx], 0FFh
cmp byte ptr [rcx], 0FFh
je RhpByRefAssignRef_NoBarrierRequired
je RhpByRefAssignRefBatch_NoBarrierRequired
mov byte ptr [rcx], 0FFh
mov byte ptr [rcx], 0FFh
endif
endif
RhpByRefAssignRefBatch_NotInHeap:
;; At least one write is already done, increment the pointers
add rdi, 8h
add rsi, 8h
dec r8d
je RhpByRefAssignRefBatch_NotInHeapExit
;; Now we can do the rest of the writes without checking the heap
RhpByRefAssignRefBatch_NextByrefUnchecked:
mov rcx, [rsi]
mov [rdi], rcx
add rdi, 8h
add rsi, 8h
dec r8d
jne RhpByRefAssignRefBatch_NextByrefUnchecked
RhpByRefAssignRefBatch_NotInHeapExit:
ret
RhpByRefAssignRef_NoBarrierRequired:
RhpByRefAssignRefBatch_NoBarrierRequired:
;; Increment the pointers before leaving
;; Increment the pointers before leaving
add rdi, 8h
add rdi, 8h
add rsi, 8h
add rsi, 8h
dec r8d
jne RhpByRefAssignRefBatch_NextByref
ret
ret
LEAF_END RhpByRefAssignRef, _TEXT
LEAF_END RhpByRefAssignRefBatch, _TEXT