Skip to content

Commit be334d5

Browse files
committed
Make Vec::clone and slice::to_owned failure-safe
1 parent 42b3992 commit be334d5

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

src/libstd/slice.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -762,18 +762,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
762762
fn to_owned(&self) -> ~[T] {
763763
let len = self.len();
764764
let mut result = with_capacity(len);
765+
// Unsafe code so this can be optimised to a memcpy (or something
766+
// similarly fast) when T is Copy. LLVM is easily confused, so any
767+
// extra operations during the loop can prevent this optimisation
765768
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);
770769
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-
}
770+
let p = result.as_mut_ptr();
771+
// Use try_finally here otherwise the write to length
772+
// inside the loop stops LLVM from optimising this.
773+
try_finally(
774+
&mut i, (),
775+
|i, ()| while *i < len {
776+
mem::move_val_init(
777+
&mut(*p.offset(*i as int)),
778+
self.unsafe_ref(*i).clone());
779+
*i += 1;
780+
},
781+
|i| result.set_len(*i));
777782
}
778783
result
779784
}

src/libstd/vec.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,21 +313,18 @@ impl<T:Clone> Clone for Vec<T> {
313313
fn clone(&self) -> Vec<T> {
314314
let len = self.len;
315315
let mut vector = Vec::with_capacity(len);
316-
vector.len = len;
317316
// Unsafe code so this can be optimised to a memcpy (or something
318317
// similarly fast) when T is Copy. LLVM is easily confused, so any
319318
// extra operations during the loop can prevent this optimisation
320319
{
321-
let slice = vector.as_mut_slice();
322320
let this_slice = self.as_slice();
323-
let mut i = 0;
324-
while i < len {
321+
while vector.len < len {
325322
unsafe {
326323
mem::move_val_init(
327-
slice.unsafe_mut_ref(i),
328-
this_slice.unsafe_ref(i).clone());
324+
vector.as_mut_slice().unsafe_mut_ref(vector.len),
325+
this_slice.unsafe_ref(vector.len).clone());
329326
}
330-
i = i + 1;
327+
vector.len += 1;
331328
}
332329
}
333330
vector

0 commit comments

Comments
 (0)