about summary refs log tree commit diff
path: root/src/libarena
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-04-24 01:45:50 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-05-23 18:51:46 +0200
commitba5d9c094daf8d78178058e7a3498b66d47db950 (patch)
tree10713684723db39b4058a0187a9d6b278226d083 /src/libarena
parent28482db2479b24caef8f738a5973d2e410ed13bf (diff)
Optimize alloc_from_iter
Diffstat (limited to 'src/libarena')
-rw-r--r--src/libarena/lib.rs29
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)
                 }
             }
             (_, _) => {