我試圖更好地理解 Rust 何時執行邊界檢查,以及如何確定編譯器是否能夠優化某些部分。
pub fn get_unchecked_mut(a: i32) -> Vec<i32>{
let buffers = &mut vec![1, 2, 3];
let mut i = a as usize;;
while i < buffers.len() {
unsafe {
let buf = buffers.get_unchecked_mut(i);
*buf = a;
};
i = 1;
}
return buffers.to_vec();
}
#[inline(never)]
pub fn normal_slice_index(a: i32) -> Vec<i32> {
let buffers = &mut vec![1, 2, 3];
let mut i = a as usize;;
while i < buffers.len() {
buffers[i] = a;
i = 1;
}
return buffers.to_vec();
}
pub fn iter_mut(a: i32) ->Vec<i32> {
let buffers = &mut vec![1, 2, 3];
let i = a as usize;
for buf in buffers[i..].iter_mut() {
*buf = a;
}
return buffers.to_vec();
}
這導致以下程式集:
core::ptr::drop_in_place<alloc::vec::Vec<i32>>:
mov rax, qword ptr [rdi 8]
test rax, rax
je .LBB0_2
mov ecx, 4
mul rcx
test rax, rax
je .LBB0_2
mov rdi, qword ptr [rdi]
mov edx, 4
mov rsi, rax
jmp qword ptr [rip __rust_dealloc@GOTPCREL]
.LBB0_2:
ret
.LCPI1_0:
.quad 3
.quad 3
example::get_unchecked_mut:
push rbp
push r14
push rbx
sub rsp, 32
mov ebp, esi
mov r14, rdi
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB1_12
mov rbx, rax
movabs rax, 8589934593
mov qword ptr [rbx], rax
mov dword ptr [rbx 8], 3
mov qword ptr [rsp 8], rbx
movaps xmm0, xmmword ptr [rip .LCPI1_0]
movups xmmword ptr [rsp 16], xmm0
cmp ebp, 2
ja .LBB1_5
mov eax, ebp
add dword ptr [rbx 4*rax], ebp
cmp ebp, 2
jae .LBB1_5
add dword ptr [rbx 4*rax 4], ebp
test ebp, ebp
jne .LBB1_5
add dword ptr [rbx 4*rax 8], ebp
.LBB1_5:
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB1_6
mov qword ptr [r14], rax
mov ecx, dword ptr [rbx 8]
mov dword ptr [rax 8], ecx
mov rcx, qword ptr [rbx]
mov qword ptr [rax], rcx
movaps xmm0, xmmword ptr [rip .LCPI1_0]
movups xmmword ptr [r14 8], xmm0
mov esi, 12
mov edx, 4
mov rdi, rbx
call qword ptr [rip __rust_dealloc@GOTPCREL]
mov rax, r14
add rsp, 32
pop rbx
pop r14
pop rbp
ret
.LBB1_12:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
ud2
.LBB1_6:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
ud2
mov rbx, rax
lea rdi, [rsp 8]
call core::ptr::drop_in_place<alloc::vec::Vec<i32>>
mov rdi, rbx
call _Unwind_Resume@PLT
ud2
call qword ptr [rip core::panicking::panic_no_unwind@GOTPCREL]
ud2
.LCPI2_0:
.quad 3
.quad 3
example::normal_slice_index:
push rbp
push r14
push rbx
sub rsp, 32
mov ebp, esi
mov r14, rdi
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB2_12
mov rbx, rax
movabs rax, 8589934593
mov qword ptr [rbx], rax
mov dword ptr [rbx 8], 3
mov qword ptr [rsp 8], rbx
movaps xmm0, xmmword ptr [rip .LCPI2_0]
movups xmmword ptr [rsp 16], xmm0
cmp ebp, 2
ja .LBB2_5
mov eax, ebp
add dword ptr [rbx 4*rax], ebp
cmp ebp, 2
jae .LBB2_5
add dword ptr [rbx 4*rax 4], ebp
test ebp, ebp
jne .LBB2_5
add dword ptr [rbx 4*rax 8], ebp
.LBB2_5:
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB2_6
mov qword ptr [r14], rax
mov ecx, dword ptr [rbx 8]
mov dword ptr [rax 8], ecx
mov rcx, qword ptr [rbx]
mov qword ptr [rax], rcx
movaps xmm0, xmmword ptr [rip .LCPI2_0]
movups xmmword ptr [r14 8], xmm0
mov esi, 12
mov edx, 4
mov rdi, rbx
call qword ptr [rip __rust_dealloc@GOTPCREL]
mov rax, r14
add rsp, 32
pop rbx
pop r14
pop rbp
ret
.LBB2_12:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
ud2
.LBB2_6:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
ud2
mov rbx, rax
lea rdi, [rsp 8]
call core::ptr::drop_in_place<alloc::vec::Vec<i32>>
mov rdi, rbx
call _Unwind_Resume@PLT
ud2
call qword ptr [rip core::panicking::panic_no_unwind@GOTPCREL]
ud2
.LCPI3_0:
.quad 3
.quad 3
example::iter_mut:
push rbp
push r14
push rbx
sub rsp, 32
mov ebp, esi
mov r14, rdi
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB3_22
mov rbx, rax
movabs rax, 8589934593
mov qword ptr [rbx], rax
mov dword ptr [rbx 8], 3
mov qword ptr [rsp 8], rbx
movdqa xmm0, xmmword ptr [rip .LCPI3_0]
movdqu xmmword ptr [rsp 16], xmm0
movsxd rdi, ebp
cmp edi, 4
jae .LBB3_2
cmp ebp, 3
je .LBB3_16
lea rax, [rbx 4*rdi]
lea rdx, [4*rdi]
mov ecx, 8
sub rcx, rdx
cmp rcx, 28
jb .LBB3_14
shr rcx, 2
add rcx, 1
mov r8, rcx
and r8, -8
movd xmm0, ebp
pshufd xmm0, xmm0, 0
lea rdx, [r8 - 8]
mov r9, rdx
shr r9, 3
add r9, 1
test rdx, rdx
je .LBB3_7
mov rsi, r9
and rsi, -2
lea rdx, [rbx 4*rdi]
add rdx, 48
xor edi, edi
.LBB3_9:
movdqu xmm1, xmmword ptr [rdx 4*rdi - 48]
movdqu xmm2, xmmword ptr [rdx 4*rdi - 32]
movdqu xmm3, xmmword ptr [rdx 4*rdi - 16]
movdqu xmm4, xmmword ptr [rdx 4*rdi]
paddd xmm1, xmm0
paddd xmm2, xmm0
movdqu xmmword ptr [rdx 4*rdi - 48], xmm1
movdqu xmmword ptr [rdx 4*rdi - 32], xmm2
paddd xmm3, xmm0
paddd xmm4, xmm0
movdqu xmmword ptr [rdx 4*rdi - 16], xmm3
movdqu xmmword ptr [rdx 4*rdi], xmm4
add rdi, 16
add rsi, -2
jne .LBB3_9
test r9b, 1
je .LBB3_12
.LBB3_11:
movdqu xmm1, xmmword ptr [rax 4*rdi]
movdqu xmm2, xmmword ptr [rax 4*rdi 16]
paddd xmm1, xmm0
paddd xmm2, xmm0
movdqu xmmword ptr [rax 4*rdi], xmm1
movdqu xmmword ptr [rax 4*rdi 16], xmm2
.LBB3_12:
cmp rcx, r8
je .LBB3_16
lea rax, [rax 4*r8]
.LBB3_14:
mov rcx, rbx
add rcx, 12
.LBB3_15:
add dword ptr [rax], ebp
add rax, 4
cmp rax, rcx
jne .LBB3_15
.LBB3_16:
mov edi, 12
mov esi, 4
call qword ptr [rip __rust_alloc@GOTPCREL]
test rax, rax
je .LBB3_17
mov qword ptr [r14], rax
mov ecx, dword ptr [rbx 8]
mov dword ptr [rax 8], ecx
mov rcx, qword ptr [rbx]
mov qword ptr [rax], rcx
movaps xmm0, xmmword ptr [rip .LCPI3_0]
movups xmmword ptr [r14 8], xmm0
mov esi, 12
mov edx, 4
mov rdi, rbx
call qword ptr [rip __rust_dealloc@GOTPCREL]
mov rax, r14
add rsp, 32
pop rbx
pop r14
pop rbp
ret
.LBB3_7:
xor edi, edi
test r9b, 1
jne .LBB3_11
jmp .LBB3_12
.LBB3_22:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
ud2
.LBB3_2:
lea rdx, [rip .L__unnamed_1]
mov esi, 3
call qword ptr [rip core::slice::index::slice_start_index_len_fail@GOTPCREL]
jmp .LBB3_3
.LBB3_17:
mov edi, 12
mov esi, 4
call qword ptr [rip alloc::alloc::handle_alloc_error@GOTPCREL]
.LBB3_3:
ud2
mov rbx, rax
lea rdi, [rsp 8]
call core::ptr::drop_in_place<alloc::vec::Vec<i32>>
mov rdi, rbx
call _Unwind_Resume@PLT
ud2
call qword ptr [rip core::panicking::panic_no_unwind@GOTPCREL]
ud2
.L__unnamed_2:
.ascii "/app/example.rs"
.L__unnamed_1:
.quad .L__unnamed_2
.asciz "\017\000\000\000\000\000\000\000!\000\000\000\020\000\000"
DW.ref.rust_eh_personality:
.quad rust_eh_personality
對于這 3 個場景,Rust 什么時候執行邊界檢查,這在 Assembly 中是什么樣的?
get_unchecked_mut()保證不進行任何邊界檢查,但后兩者是否會發生?我想它確實如此,但我在 ASM 的任何地方都找不到它。
uj5u.com熱心網友回復:
在normal_slice_index編譯器中,只需展開回圈并分別處理元素。邊界檢查在第 112-113 行:
cmp ebp, 2
ja .LBB2_5
由于您明確擁有while i < buffers.len(),因此不會有錯誤。
iter_mut邊界檢查在第 187-188 行:
cmp edi, 4
jae .LBB3_2
在.LBB3_3我們有:
mov esi, 3
call qword ptr [rip core::slice::index::slice_start_index_len_fail@GOTPCREL]
這將引發錯誤。
請注意,由于您vec對編譯器可見,因此它知道長度為 3 并且已行內。如果您將向量作為引數傳入,代碼可能看起來會有所不同。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/514007.html
標籤:部件锈
