diff options
| author | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2019-04-24 01:45:50 +0200 |
|---|---|---|
| committer | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2019-05-23 18:51:46 +0200 |
| commit | ba5d9c094daf8d78178058e7a3498b66d47db950 (patch) | |
| tree | 10713684723db39b4058a0187a9d6b278226d083 /src | |
| parent | 28482db2479b24caef8f738a5973d2e410ed13bf (diff) | |
Optimize alloc_from_iter
Diffstat (limited to 'src')
| -rw-r--r-- | src/libarena/lib.rs | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index ce5e5f23a94..d6bec816e4e 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -487,8 +487,30 @@ impl DroplessArena { } #[inline] + unsafe fn write_from_iter<T, I: Iterator<Item = T>>( + &self, + mut iter: I, + len: usize, + mem: *mut T, + ) -> &mut [T] { + let mut i = 0; + // Use a manual loop since LLVM manages to optimize it better for + // slice iterators + loop { + let value = iter.next(); + if i >= len || value.is_none() { + // We only return as many items as the iterator gave us, even + // though it was supposed to give us `len` + return slice::from_raw_parts_mut(mem, i); + } + ptr::write(mem.offset(i as isize), value.unwrap()); + i += 1; + } + } + + #[inline] pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] { - let mut iter = iter.into_iter(); + let iter = iter.into_iter(); assert!(mem::size_of::<T>() != 0); assert!(!mem::needs_drop::<T>()); @@ -505,10 +527,7 @@ impl DroplessArena { let size = len.checked_mul(mem::size_of::<T>()).unwrap(); let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T; unsafe { - for i in 0..len { - ptr::write(mem.offset(i as isize), iter.next().unwrap()) - } - slice::from_raw_parts_mut(mem, len) + self.write_from_iter(iter, len, mem) } } (_, _) => { |
