Skip to content

Commit 42b3992

Browse files
committed
Improve the copying code for slices and Vec
1 parent 10f94e3 commit 42b3992

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

src/libstd/slice.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -760,9 +760,20 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
760760
/// Returns a copy of `v`.
761761
#[inline]
762762
fn to_owned(&self) -> ~[T] {
763-
let mut result = with_capacity(self.len());
764-
for e in self.iter() {
765-
result.push((*e).clone());
763+
let len = self.len();
764+
let mut result = with_capacity(len);
765+
unsafe {
766+
// Unsafe code so this can be optimised to a memcpy (or something
767+
// similarly fast) when T is Copy. LLVM is easily confused, so any
768+
// extra operations during the loop can prevent this optimisation
769+
result.set_len(len);
770+
let mut i = 0;
771+
while i < len {
772+
mem::move_val_init(
773+
result.unsafe_mut_ref(i),
774+
self.unsafe_ref(i).clone());
775+
i = i + 1;
776+
}
766777
}
767778
result
768779
}
@@ -2584,7 +2595,8 @@ pub mod bytes {
25842595
impl<A: Clone> Clone for ~[A] {
25852596
#[inline]
25862597
fn clone(&self) -> ~[A] {
2587-
self.iter().map(|item| item.clone()).collect()
2598+
// Use the fast to_owned on &[A] for cloning
2599+
self.as_slice().to_owned()
25882600
}
25892601

25902602
fn clone_from(&mut self, source: &~[A]) {

src/libstd/vec.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,26 @@ impl<T: Clone> Vec<T> {
311311

312312
impl<T:Clone> Clone for Vec<T> {
313313
fn clone(&self) -> Vec<T> {
314-
self.iter().map(|x| x.clone()).collect()
314+
let len = self.len;
315+
let mut vector = Vec::with_capacity(len);
316+
vector.len = len;
317+
// Unsafe code so this can be optimised to a memcpy (or something
318+
// similarly fast) when T is Copy. LLVM is easily confused, so any
319+
// extra operations during the loop can prevent this optimisation
320+
{
321+
let slice = vector.as_mut_slice();
322+
let this_slice = self.as_slice();
323+
let mut i = 0;
324+
while i < len {
325+
unsafe {
326+
mem::move_val_init(
327+
slice.unsafe_mut_ref(i),
328+
this_slice.unsafe_ref(i).clone());
329+
}
330+
i = i + 1;
331+
}
332+
}
333+
vector
315334
}
316335

317336
fn clone_from(&mut self, other: &Vec<T>) {

0 commit comments

Comments
 (0)