diff options
| author | James Miller <james@aatch.net> | 2014-04-16 11:35:18 +1200 |
|---|---|---|
| committer | James Miller <james@aatch.net> | 2014-04-16 11:35:31 +1200 |
| commit | 42b39924d87739f2dcda3e788c6e8655d310954f (patch) | |
| tree | 25b6b5fabb3b1ed9aef4f2373b9354f099c660b4 /src/libstd | |
| parent | 10f94e3fe5859fe7fc001cf26f4fa401d9a2ee2e (diff) | |
| download | rust-42b39924d87739f2dcda3e788c6e8655d310954f.tar.gz rust-42b39924d87739f2dcda3e788c6e8655d310954f.zip | |
Improve the copying code for slices and Vec
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/slice.rs | 20 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 21 |
2 files changed, 36 insertions, 5 deletions
diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index aedaa5b3c15..f4f97ea8c92 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -760,9 +760,20 @@ impl<'a, T: Clone> CloneableVector<T> 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 { + // 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 + result.set_len(len); + let mut i = 0; + while i < len { + mem::move_val_init( + result.unsafe_mut_ref(i), + self.unsafe_ref(i).clone()); + i = i + 1; + } } result } @@ -2584,7 +2595,8 @@ pub mod bytes { impl<A: Clone> 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 a69120de00f..034d53aa78b 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -311,7 +311,26 @@ impl<T: Clone> Vec<T> { impl<T:Clone> Clone for Vec<T> { fn clone(&self) -> Vec<T> { - self.iter().map(|x| x.clone()).collect() + let len = self.len; + let mut vector = Vec::with_capacity(len); + vector.len = 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 slice = vector.as_mut_slice(); + let this_slice = self.as_slice(); + let mut i = 0; + while i < len { + unsafe { + mem::move_val_init( + slice.unsafe_mut_ref(i), + this_slice.unsafe_ref(i).clone()); + } + i = i + 1; + } + } + vector } fn clone_from(&mut self, other: &Vec<T>) { |
