diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index aedaa5b3c159f..153e21c780c09 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -760,9 +760,25 @@ impl<'a, T: Clone> CloneableVector for &'a [T] { /// Returns a copy of `v`. #[inline] fn to_owned(&self) -> ~[T] { - let mut result = with_capacity(self.len()); - for e in self.iter() { - result.push((*e).clone()); + let len = self.len(); + let mut result = with_capacity(len); + // Unsafe code so this can be optimised to a memcpy (or something + // similarly fast) when T is Copy. LLVM is easily confused, so any + // extra operations during the loop can prevent this optimisation + unsafe { + let mut i = 0; + let p = result.as_mut_ptr(); + // Use try_finally here otherwise the write to length + // inside the loop stops LLVM from optimising this. + try_finally( + &mut i, (), + |i, ()| while *i < len { + mem::move_val_init( + &mut(*p.offset(*i as int)), + self.unsafe_ref(*i).clone()); + *i += 1; + }, + |i| result.set_len(*i)); } result } @@ -2584,7 +2600,8 @@ pub mod bytes { impl Clone for ~[A] { #[inline] fn clone(&self) -> ~[A] { - self.iter().map(|item| item.clone()).collect() + // Use the fast to_owned on &[A] for cloning + self.as_slice().to_owned() } fn clone_from(&mut self, source: &~[A]) { diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index a69120de00f7d..96cbac8869ef2 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -311,7 +311,23 @@ impl Vec { impl Clone for Vec { fn clone(&self) -> Vec { - self.iter().map(|x| x.clone()).collect() + let len = self.len; + let mut vector = Vec::with_capacity(len); + // Unsafe code so this can be optimised to a memcpy (or something + // similarly fast) when T is Copy. LLVM is easily confused, so any + // extra operations during the loop can prevent this optimisation + { + let this_slice = self.as_slice(); + while vector.len < len { + unsafe { + mem::move_val_init( + vector.as_mut_slice().unsafe_mut_ref(vector.len), + this_slice.unsafe_ref(vector.len).clone()); + } + vector.len += 1; + } + } + vector } fn clone_from(&mut self, other: &Vec) {