Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
Untitled diff
생성일
2년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
0 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
196 행
복사
35 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
228 행
복사
복사
복사됨
복사
복사됨
LEAF_ENTRY JIT_ByRefWriteBarrier
, _TEXT
LEAF_ENTRY JIT_ByRefWriteBarrier
Batch
, _TEXT
NextByref:
mov rcx, [rsi]
mov rcx, [rsi]
; If !WRITE_BARRIER_CHECK do the write first, otherwise we might have to do some ShadowGC stuff
; If !WRITE_BARRIER_CHECK do the write first, otherwise we might have to do some ShadowGC stuff
ifndef WRITE_BARRIER_CHECK
ifndef WRITE_BARRIER_CHECK
; rcx is [rsi]
; rcx is [rsi]
mov [rdi], rcx
mov [rdi], rcx
endif
endif
; When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference
; When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference
; but if it isn't then it will just return.
; but if it isn't then it will just return.
;
;
; See if this is in GCHeap
; See if this is in GCHeap
cmp rdi, [g_lowest_address]
cmp rdi, [g_lowest_address]
jb NotInHeap
jb NotInHeap
cmp rdi, [g_highest_address]
cmp rdi, [g_highest_address]
jnb NotInHeap
jnb NotInHeap
ifdef WRITE_BARRIER_CHECK
ifdef WRITE_BARRIER_CHECK
; we can only trash rcx in this function so in _DEBUG we need to save
; we can only trash rcx in this function so in _DEBUG we need to save
; some scratch registers.
; some scratch registers.
push r10
push r10
push r11
push r11
push rax
push rax
; **ALSO update the shadow GC heap if that is enabled**
; **ALSO update the shadow GC heap if that is enabled**
; Do not perform the work if g_GCShadow is 0
; Do not perform the work if g_GCShadow is 0
cmp g_GCShadow, 0
cmp g_GCShadow, 0
je NoShadow
je NoShadow
; If we end up outside of the heap don't corrupt random memory
; If we end up outside of the heap don't corrupt random memory
mov r10, rdi
mov r10, rdi
sub r10, [g_lowest_address]
sub r10, [g_lowest_address]
jb NoShadow
jb NoShadow
; Check that our adjusted destination is somewhere in the shadow gc
; Check that our adjusted destination is somewhere in the shadow gc
add r10, [g_GCShadow]
add r10, [g_GCShadow]
cmp r10, [g_GCShadowEnd]
cmp r10, [g_GCShadowEnd]
jnb NoShadow
jnb NoShadow
; Write ref into real GC
; Write ref into real GC
mov [rdi], rcx
mov [rdi], rcx
; Write ref into shadow GC
; Write ref into shadow GC
mov [r10], rcx
mov [r10], rcx
; Ensure that the write to the shadow heap occurs before the read from
; Ensure that the write to the shadow heap occurs before the read from
; the GC heap so that race conditions are caught by INVALIDGCVALUE
; the GC heap so that race conditions are caught by INVALIDGCVALUE
mfence
mfence
; Check that GC/ShadowGC values match
; Check that GC/ShadowGC values match
mov r11, [rdi]
mov r11, [rdi]
mov rax, [r10]
mov rax, [r10]
cmp rax, r11
cmp rax, r11
je DoneShadow
je DoneShadow
mov r11, INVALIDGCVALUE
mov r11, INVALIDGCVALUE
mov [r10], r11
mov [r10], r11
jmp DoneShadow
jmp DoneShadow
; If we don't have a shadow GC we won't have done the write yet
; If we don't have a shadow GC we won't have done the write yet
NoShadow:
NoShadow:
mov [rdi], rcx
mov [rdi], rcx
; If we had a shadow GC then we already wrote to the real GC at the same time
; If we had a shadow GC then we already wrote to the real GC at the same time
; as the shadow GC so we want to jump over the real write immediately above.
; as the shadow GC so we want to jump over the real write immediately above.
; Additionally we know for sure that we are inside the heap and therefore don't
; Additionally we know for sure that we are inside the heap and therefore don't
; need to replicate the above checks.
; need to replicate the above checks.
DoneShadow:
DoneShadow:
pop rax
pop rax
pop r11
pop r11
pop r10
pop r10
endif
endif
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
; Update the write watch table if necessary
; Update the write watch table if necessary
cmp byte ptr [g_sw_ww_enabled_for_gc_heap], 0h
cmp byte ptr [g_sw_ww_enabled_for_gc_heap], 0h
je CheckCardTable
je CheckCardTable
mov rax, rdi
mov rax, rdi
shr rax, 0Ch ; SoftwareWriteWatch::AddressToTableByteIndexShift
shr rax, 0Ch ; SoftwareWriteWatch::AddressToTableByteIndexShift
add rax, qword ptr [g_sw_ww_table]
add rax, qword ptr [g_sw_ww_table]
cmp byte ptr [rax], 0h
cmp byte ptr [rax], 0h
jne CheckCardTable
jne CheckCardTable
mov byte ptr [rax], 0FFh
mov byte ptr [rax], 0FFh
endif
endif
; See if we can just quick out
; See if we can just quick out
CheckCardTable:
CheckCardTable:
cmp rcx, [g_ephemeral_low]
cmp rcx, [g_ephemeral_low]
jb Exit
jb Exit
cmp rcx, [g_ephemeral_high]
cmp rcx, [g_ephemeral_high]
jnb Exit
jnb Exit
; do the following checks only if we are allowed to trash rax
; do the following checks only if we are allowed to trash rax
; otherwise we don't have enough registers
; otherwise we don't have enough registers
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
mov rax, rcx
mov rax, rcx
mov cl, [g_region_shr]
mov cl, [g_region_shr]
test cl, cl
test cl, cl
je SkipCheck
je SkipCheck
; check if the source is in gen 2 - then it's not an ephemeral pointer
; check if the source is in gen 2 - then it's not an ephemeral pointer
shr rax, cl
shr rax, cl
add rax, [g_region_to_generation_table]
add rax, [g_region_to_generation_table]
cmp byte ptr [rax], 82h
cmp byte ptr [rax], 82h
je Exit
je Exit
; check if the destination happens to be in gen 0
; check if the destination happens to be in gen 0
mov rax, rdi
mov rax, rdi
shr rax, cl
shr rax, cl
add rax, [g_region_to_generation_table]
add rax, [g_region_to_generation_table]
cmp byte ptr [rax], 0
cmp byte ptr [rax], 0
je Exit
je Exit
SkipCheck:
SkipCheck:
cmp [g_region_use_bitwise_write_barrier], 0
cmp [g_region_use_bitwise_write_barrier], 0
je CheckCardTableByte
je CheckCardTableByte
; compute card table bit
; compute card table bit
mov rcx, rdi
mov rcx, rdi
mov al, 1
mov al, 1
shr rcx, 8
shr rcx, 8
and cl, 7
and cl, 7
shl al, cl
shl al, cl
; move current rdi value into rcx and then increment the pointers
; move current rdi value into rcx and then increment the pointers
mov rcx, rdi
mov rcx, rdi
add rsi, 8h
add rsi, 8h
add rdi, 8h
add rdi, 8h
; Check if we need to update the card table
; Check if we need to update the card table
; Calc pCardByte
; Calc pCardByte
shr rcx, 0Bh
shr rcx, 0Bh
add rcx, [g_card_table]
add rcx, [g_card_table]
; Check if this card table bit is already set
; Check if this card table bit is already set
test byte ptr [rcx], al
test byte ptr [rcx], al
je SetCardTableBit
je SetCardTableBit
복사
복사됨
복사
복사됨
; Check if we have more in the batch and run again
dec r8d
jne NextByref
REPRET
REPRET
SetCardTableBit:
SetCardTableBit:
lock or byte ptr [rcx], al
lock or byte ptr [rcx], al
jmp CheckCardBundle
jmp CheckCardBundle
endif
endif
CheckCardTableByte:
CheckCardTableByte:
; move current rdi value into rcx and then increment the pointers
; move current rdi value into rcx and then increment the pointers
mov rcx, rdi
mov rcx, rdi
add rsi, 8h
add rsi, 8h
add rdi, 8h
add rdi, 8h
; Check if we need to update the card table
; Check if we need to update the card table
; Calc pCardByte
; Calc pCardByte
shr rcx, 0Bh
shr rcx, 0Bh
add rcx, [g_card_table]
add rcx, [g_card_table]
; Check if this card is dirty
; Check if this card is dirty
cmp byte ptr [rcx], 0FFh
cmp byte ptr [rcx], 0FFh
jne UpdateCardTable
jne UpdateCardTable
복사
복사됨
복사
복사됨
; Check if we have more in the batch and run again
dec r8d
jne NextByref
REPRET
REPRET
UpdateCardTable:
UpdateCardTable:
mov byte ptr [rcx], 0FFh
mov byte ptr [rcx], 0FFh
CheckCardBundle:
CheckCardBundle:
ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
; check if we need to update the card bundle table
; check if we need to update the card bundle table
; restore destination address from rdi - rdi has been incremented by 8 already
; restore destination address from rdi - rdi has been incremented by 8 already
lea rcx, [rdi-8]
lea rcx, [rdi-8]
shr rcx, 15h
shr rcx, 15h
add rcx, [g_card_bundle_table]
add rcx, [g_card_bundle_table]
cmp byte ptr [rcx], 0FFh
cmp byte ptr [rcx], 0FFh
jne UpdateCardBundleTable
jne UpdateCardBundleTable
복사
복사됨
복사
복사됨
; Check if we have more in the batch and run again
dec r8d
jne NextByref
REPRET
REPRET
UpdateCardBundleTable:
UpdateCardBundleTable:
mov byte ptr [rcx], 0FFh
mov byte ptr [rcx], 0FFh
endif
endif
복사
복사됨
복사
복사됨
; Check if we have more in the batch and run again
dec r8d
jne NextByref
ret
ret
align 16
align 16
NotInHeap:
NotInHeap:
; If WRITE_BARRIER_CHECK then we won't have already done the mov and should do it here
; If WRITE_BARRIER_CHECK then we won't have already done the mov and should do it here
; If !WRITE_BARRIER_CHECK we want _NotInHeap and _Leave to be the same and have both
; If !WRITE_BARRIER_CHECK we want _NotInHeap and _Leave to be the same and have both
; 16 byte aligned.
; 16 byte aligned.
ifdef WRITE_BARRIER_CHECK
ifdef WRITE_BARRIER_CHECK
; rcx is [rsi]
; rcx is [rsi]
mov [rdi], rcx
mov [rdi], rcx
endif
endif
복사
복사됨
복사
복사됨
; At least one write is already done, increment the pointers
add rdi, 8h
add rsi, 8h
dec r8d
je NotInHeapExit
; Now we can do the rest of the writes without checking the heap
NextByrefUnchecked:
mov rcx, [rsi]
mov [rdi], rcx
add rdi, 8h
add rsi, 8h
dec r8d
jne NextByrefUnchecked
NotInHeapExit:
ret
Exit:
Exit:
; Increment the pointers before leaving
; Increment the pointers before leaving
add rdi, 8h
add rdi, 8h
add rsi, 8h
add rsi, 8h
복사
복사됨
복사
복사됨
; Check if we have more in the batch and run again
dec r8d
jne NextByref
ret
ret
복사
복사됨
복사
복사됨
LEAF_END_MARKED JIT_ByRefWriteBarrier
, _TEXT
LEAF_END_MARKED JIT_ByRefWriteBarrier
Batch
, _TEXT
저장된 비교 결과
원본
파일 열기
LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT mov rcx, [rsi] ; If !WRITE_BARRIER_CHECK do the write first, otherwise we might have to do some ShadowGC stuff ifndef WRITE_BARRIER_CHECK ; rcx is [rsi] mov [rdi], rcx endif ; When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference ; but if it isn't then it will just return. ; ; See if this is in GCHeap cmp rdi, [g_lowest_address] jb NotInHeap cmp rdi, [g_highest_address] jnb NotInHeap ifdef WRITE_BARRIER_CHECK ; we can only trash rcx in this function so in _DEBUG we need to save ; some scratch registers. push r10 push r11 push rax ; **ALSO update the shadow GC heap if that is enabled** ; Do not perform the work if g_GCShadow is 0 cmp g_GCShadow, 0 je NoShadow ; If we end up outside of the heap don't corrupt random memory mov r10, rdi sub r10, [g_lowest_address] jb NoShadow ; Check that our adjusted destination is somewhere in the shadow gc add r10, [g_GCShadow] cmp r10, [g_GCShadowEnd] jnb NoShadow ; Write ref into real GC mov [rdi], rcx ; Write ref into shadow GC mov [r10], rcx ; Ensure that the write to the shadow heap occurs before the read from ; the GC heap so that race conditions are caught by INVALIDGCVALUE mfence ; Check that GC/ShadowGC values match mov r11, [rdi] mov rax, [r10] cmp rax, r11 je DoneShadow mov r11, INVALIDGCVALUE mov [r10], r11 jmp DoneShadow ; If we don't have a shadow GC we won't have done the write yet NoShadow: mov [rdi], rcx ; If we had a shadow GC then we already wrote to the real GC at the same time ; as the shadow GC so we want to jump over the real write immediately above. ; Additionally we know for sure that we are inside the heap and therefore don't ; need to replicate the above checks. DoneShadow: pop rax pop r11 pop r10 endif ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP ; Update the write watch table if necessary cmp byte ptr [g_sw_ww_enabled_for_gc_heap], 0h je CheckCardTable mov rax, rdi shr rax, 0Ch ; SoftwareWriteWatch::AddressToTableByteIndexShift add rax, qword ptr [g_sw_ww_table] cmp byte ptr [rax], 0h jne CheckCardTable mov byte ptr [rax], 0FFh endif ; See if we can just quick out CheckCardTable: cmp rcx, [g_ephemeral_low] jb Exit cmp rcx, [g_ephemeral_high] jnb Exit ; do the following checks only if we are allowed to trash rax ; otherwise we don't have enough registers ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP mov rax, rcx mov cl, [g_region_shr] test cl, cl je SkipCheck ; check if the source is in gen 2 - then it's not an ephemeral pointer shr rax, cl add rax, [g_region_to_generation_table] cmp byte ptr [rax], 82h je Exit ; check if the destination happens to be in gen 0 mov rax, rdi shr rax, cl add rax, [g_region_to_generation_table] cmp byte ptr [rax], 0 je Exit SkipCheck: cmp [g_region_use_bitwise_write_barrier], 0 je CheckCardTableByte ; compute card table bit mov rcx, rdi mov al, 1 shr rcx, 8 and cl, 7 shl al, cl ; move current rdi value into rcx and then increment the pointers mov rcx, rdi add rsi, 8h add rdi, 8h ; Check if we need to update the card table ; Calc pCardByte shr rcx, 0Bh add rcx, [g_card_table] ; Check if this card table bit is already set test byte ptr [rcx], al je SetCardTableBit REPRET SetCardTableBit: lock or byte ptr [rcx], al jmp CheckCardBundle endif CheckCardTableByte: ; move current rdi value into rcx and then increment the pointers mov rcx, rdi add rsi, 8h add rdi, 8h ; Check if we need to update the card table ; Calc pCardByte shr rcx, 0Bh add rcx, [g_card_table] ; Check if this card is dirty cmp byte ptr [rcx], 0FFh jne UpdateCardTable REPRET UpdateCardTable: mov byte ptr [rcx], 0FFh CheckCardBundle: ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES ; check if we need to update the card bundle table ; restore destination address from rdi - rdi has been incremented by 8 already lea rcx, [rdi-8] shr rcx, 15h add rcx, [g_card_bundle_table] cmp byte ptr [rcx], 0FFh jne UpdateCardBundleTable REPRET UpdateCardBundleTable: mov byte ptr [rcx], 0FFh endif ret align 16 NotInHeap: ; If WRITE_BARRIER_CHECK then we won't have already done the mov and should do it here ; If !WRITE_BARRIER_CHECK we want _NotInHeap and _Leave to be the same and have both ; 16 byte aligned. ifdef WRITE_BARRIER_CHECK ; rcx is [rsi] mov [rdi], rcx endif Exit: ; Increment the pointers before leaving add rdi, 8h add rsi, 8h ret LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT
수정본
파일 열기
LEAF_ENTRY JIT_ByRefWriteBarrierBatch, _TEXT NextByref: mov rcx, [rsi] ; If !WRITE_BARRIER_CHECK do the write first, otherwise we might have to do some ShadowGC stuff ifndef WRITE_BARRIER_CHECK ; rcx is [rsi] mov [rdi], rcx endif ; When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference ; but if it isn't then it will just return. ; ; See if this is in GCHeap cmp rdi, [g_lowest_address] jb NotInHeap cmp rdi, [g_highest_address] jnb NotInHeap ifdef WRITE_BARRIER_CHECK ; we can only trash rcx in this function so in _DEBUG we need to save ; some scratch registers. push r10 push r11 push rax ; **ALSO update the shadow GC heap if that is enabled** ; Do not perform the work if g_GCShadow is 0 cmp g_GCShadow, 0 je NoShadow ; If we end up outside of the heap don't corrupt random memory mov r10, rdi sub r10, [g_lowest_address] jb NoShadow ; Check that our adjusted destination is somewhere in the shadow gc add r10, [g_GCShadow] cmp r10, [g_GCShadowEnd] jnb NoShadow ; Write ref into real GC mov [rdi], rcx ; Write ref into shadow GC mov [r10], rcx ; Ensure that the write to the shadow heap occurs before the read from ; the GC heap so that race conditions are caught by INVALIDGCVALUE mfence ; Check that GC/ShadowGC values match mov r11, [rdi] mov rax, [r10] cmp rax, r11 je DoneShadow mov r11, INVALIDGCVALUE mov [r10], r11 jmp DoneShadow ; If we don't have a shadow GC we won't have done the write yet NoShadow: mov [rdi], rcx ; If we had a shadow GC then we already wrote to the real GC at the same time ; as the shadow GC so we want to jump over the real write immediately above. ; Additionally we know for sure that we are inside the heap and therefore don't ; need to replicate the above checks. DoneShadow: pop rax pop r11 pop r10 endif ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP ; Update the write watch table if necessary cmp byte ptr [g_sw_ww_enabled_for_gc_heap], 0h je CheckCardTable mov rax, rdi shr rax, 0Ch ; SoftwareWriteWatch::AddressToTableByteIndexShift add rax, qword ptr [g_sw_ww_table] cmp byte ptr [rax], 0h jne CheckCardTable mov byte ptr [rax], 0FFh endif ; See if we can just quick out CheckCardTable: cmp rcx, [g_ephemeral_low] jb Exit cmp rcx, [g_ephemeral_high] jnb Exit ; do the following checks only if we are allowed to trash rax ; otherwise we don't have enough registers ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP mov rax, rcx mov cl, [g_region_shr] test cl, cl je SkipCheck ; check if the source is in gen 2 - then it's not an ephemeral pointer shr rax, cl add rax, [g_region_to_generation_table] cmp byte ptr [rax], 82h je Exit ; check if the destination happens to be in gen 0 mov rax, rdi shr rax, cl add rax, [g_region_to_generation_table] cmp byte ptr [rax], 0 je Exit SkipCheck: cmp [g_region_use_bitwise_write_barrier], 0 je CheckCardTableByte ; compute card table bit mov rcx, rdi mov al, 1 shr rcx, 8 and cl, 7 shl al, cl ; move current rdi value into rcx and then increment the pointers mov rcx, rdi add rsi, 8h add rdi, 8h ; Check if we need to update the card table ; Calc pCardByte shr rcx, 0Bh add rcx, [g_card_table] ; Check if this card table bit is already set test byte ptr [rcx], al je SetCardTableBit ; Check if we have more in the batch and run again dec r8d jne NextByref REPRET SetCardTableBit: lock or byte ptr [rcx], al jmp CheckCardBundle endif CheckCardTableByte: ; move current rdi value into rcx and then increment the pointers mov rcx, rdi add rsi, 8h add rdi, 8h ; Check if we need to update the card table ; Calc pCardByte shr rcx, 0Bh add rcx, [g_card_table] ; Check if this card is dirty cmp byte ptr [rcx], 0FFh jne UpdateCardTable ; Check if we have more in the batch and run again dec r8d jne NextByref REPRET UpdateCardTable: mov byte ptr [rcx], 0FFh CheckCardBundle: ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES ; check if we need to update the card bundle table ; restore destination address from rdi - rdi has been incremented by 8 already lea rcx, [rdi-8] shr rcx, 15h add rcx, [g_card_bundle_table] cmp byte ptr [rcx], 0FFh jne UpdateCardBundleTable ; Check if we have more in the batch and run again dec r8d jne NextByref REPRET UpdateCardBundleTable: mov byte ptr [rcx], 0FFh endif ; Check if we have more in the batch and run again dec r8d jne NextByref ret align 16 NotInHeap: ; If WRITE_BARRIER_CHECK then we won't have already done the mov and should do it here ; If !WRITE_BARRIER_CHECK we want _NotInHeap and _Leave to be the same and have both ; 16 byte aligned. ifdef WRITE_BARRIER_CHECK ; rcx is [rsi] mov [rdi], rcx endif ; At least one write is already done, increment the pointers add rdi, 8h add rsi, 8h dec r8d je NotInHeapExit ; Now we can do the rest of the writes without checking the heap NextByrefUnchecked: mov rcx, [rsi] mov [rdi], rcx add rdi, 8h add rsi, 8h dec r8d jne NextByrefUnchecked NotInHeapExit: ret Exit: ; Increment the pointers before leaving add rdi, 8h add rsi, 8h ; Check if we have more in the batch and run again dec r8d jne NextByref ret LEAF_END_MARKED JIT_ByRefWriteBarrierBatch, _TEXT
비교하기