Skip to content

Commit

Permalink
Make Vec::clone and slice::to_owned failure-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Aatch committed Apr 16, 2014
1 parent 42b3992 commit be334d5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 17 deletions.
25 changes: 15 additions & 10 deletions src/libstd/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,18 +762,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
fn to_owned(&self) -> ~[T] {
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 {
// 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;
}
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
}
Expand Down
11 changes: 4 additions & 7 deletions src/libstd/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,21 +313,18 @@ impl<T:Clone> Clone for Vec<T> {
fn clone(&self) -> Vec<T> {
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 {
while vector.len < len {
unsafe {
mem::move_val_init(
slice.unsafe_mut_ref(i),
this_slice.unsafe_ref(i).clone());
vector.as_mut_slice().unsafe_mut_ref(vector.len),
this_slice.unsafe_ref(vector.len).clone());
}
i = i + 1;
vector.len += 1;
}
}
vector
Expand Down

5 comments on commit be334d5

@bors
Copy link
Contributor

@bors bors commented on be334d5 Apr 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from thestinger
at Aatch@be334d5

@bors
Copy link
Contributor

@bors bors commented on be334d5 Apr 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging Aatch/rust/vector-copy-faster = be334d5 into auto

@bors
Copy link
Contributor

@bors bors commented on be334d5 Apr 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aatch/rust/vector-copy-faster = be334d5 merged ok, testing candidate = f39ba69

@bors
Copy link
Contributor

@bors bors commented on be334d5 Apr 16, 2014

@bors
Copy link
Contributor

@bors bors commented on be334d5 Apr 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = f39ba69

Please sign in to comment.