Skip to content

Commit d644235

Browse files
committed
optimize from_page_table_indices
The new code behaves exactly the same as the old code, but can be much better optimized by LLVM. In particular the bounds checks previously implied through `set_bits` and `VirtAddr::new` can now be elided. This also increases the chances of these functions being inlined. The generated assembly for the old implementation looks like this: ```asm x86_64::structures::paging::page::Page::from_page_table_indices: push rax movzx edi, di cmp edi, 512 jae .LBB48_8 movzx esi, si cmp esi, 512 jae .LBB48_8 movzx edx, dx cmp edx, 512 jae .LBB48_8 movzx eax, cx cmp eax, 512 jae .LBB48_8 mov rcx, rdi shl rcx, 39 shl rsi, 30 or rsi, rcx shl rdx, 21 shl rax, 12 or rax, rdx or rax, rsi shr edi, 8 je .LBB48_7 cmp edi, 1 jne .LBB48_9 shl rax, 16 sar rax, 16 .LBB48_7: shl rax, 16 sar rax, 16 and rax, -4096 pop rcx ret .LBB48_8: lea rdi, [rip, +, .L__unnamed_46] lea rdx, [rip, +, .L__unnamed_15] mov esi, 33 call qword, ptr, [rip, +, _ZN4core9panicking5panic17h87fd92496103e3b8E@GOTPCREL] .LBB48_9: mov qword, ptr, [rsp], rax lea rdi, [rip, +, .L__unnamed_9] lea rcx, [rip, +, .L__unnamed_10] lea r8, [rip, +, .L__unnamed_11] mov rdx, rsp mov esi, 74 call qword, ptr, [rip, +, _ZN4core6result13unwrap_failed17hc28f4ee1a6255957E@GOTPCREL] ``` The generated assembly for the new implementation looks like this: ```asm x86_64::structures::paging::page::Page::from_page_table_indices: shl rdi, 55 movzx esi, si shl rsi, 46 or rsi, rdi movzx edx, dx shl rdx, 37 movzx eax, cx shl rax, 28 or rax, rdx or rax, rsi sar rax, 16 ret ```
1 parent 3eb9c22 commit d644235

File tree

1 file changed

+12
-18
lines changed

1 file changed

+12
-18
lines changed

src/structures/paging/page.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,10 @@ impl Page<Size1GiB> {
182182
p4_index: PageTableIndex,
183183
p3_index: PageTableIndex,
184184
) -> Self {
185-
use bit_field::BitField;
186-
187185
let mut addr = 0;
188-
addr.set_bits(39..48, u64::from(p4_index));
189-
addr.set_bits(30..39, u64::from(p3_index));
190-
Page::containing_address(VirtAddr::new(addr))
186+
addr |= u64::from(p4_index) << 39;
187+
addr |= u64::from(p3_index) << 30;
188+
Page::containing_address(VirtAddr::new_truncate(addr))
191189
}
192190
}
193191

@@ -199,13 +197,11 @@ impl Page<Size2MiB> {
199197
p3_index: PageTableIndex,
200198
p2_index: PageTableIndex,
201199
) -> Self {
202-
use bit_field::BitField;
203-
204200
let mut addr = 0;
205-
addr.set_bits(39..48, u64::from(p4_index));
206-
addr.set_bits(30..39, u64::from(p3_index));
207-
addr.set_bits(21..30, u64::from(p2_index));
208-
Page::containing_address(VirtAddr::new(addr))
201+
addr |= u64::from(p4_index) << 39;
202+
addr |= u64::from(p3_index) << 30;
203+
addr |= u64::from(p2_index) << 21;
204+
Page::containing_address(VirtAddr::new_truncate(addr))
209205
}
210206
}
211207

@@ -218,14 +214,12 @@ impl Page<Size4KiB> {
218214
p2_index: PageTableIndex,
219215
p1_index: PageTableIndex,
220216
) -> Self {
221-
use bit_field::BitField;
222-
223217
let mut addr = 0;
224-
addr.set_bits(39..48, u64::from(p4_index));
225-
addr.set_bits(30..39, u64::from(p3_index));
226-
addr.set_bits(21..30, u64::from(p2_index));
227-
addr.set_bits(12..21, u64::from(p1_index));
228-
Page::containing_address(VirtAddr::new(addr))
218+
addr |= u64::from(p4_index) << 39;
219+
addr |= u64::from(p3_index) << 30;
220+
addr |= u64::from(p2_index) << 21;
221+
addr |= u64::from(p1_index) << 12;
222+
Page::containing_address(VirtAddr::new_truncate(addr))
229223
}
230224

231225
/// Returns the level 1 page table index of this page.

0 commit comments

Comments
 (0)