Make Vec::clone and slice::to_owned failure-safe

This commit is contained in:
James Miller
2014-04-16 14:29:36 +12:00
parent 42b39924d8
commit be334d5824
2 changed files with 19 additions and 17 deletions

View File

@@ -762,18 +762,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
fn to_owned(&self) -> ~[T] { fn to_owned(&self) -> ~[T] {
let len = self.len(); let len = self.len();
let mut result = with_capacity(len); let mut result = with_capacity(len);
unsafe {
// Unsafe code so this can be optimised to a memcpy (or something // Unsafe code so this can be optimised to a memcpy (or something
// similarly fast) when T is Copy. LLVM is easily confused, so any // similarly fast) when T is Copy. LLVM is easily confused, so any
// extra operations during the loop can prevent this optimisation // extra operations during the loop can prevent this optimisation
result.set_len(len); unsafe {
let mut i = 0; let mut i = 0;
while i < len { 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( mem::move_val_init(
result.unsafe_mut_ref(i), &mut(*p.offset(*i as int)),
self.unsafe_ref(i).clone()); self.unsafe_ref(*i).clone());
i = i + 1; *i += 1;
} },
|i| result.set_len(*i));
} }
result result
} }

View File

@@ -313,21 +313,18 @@ impl<T:Clone> Clone for Vec<T> {
fn clone(&self) -> Vec<T> { fn clone(&self) -> Vec<T> {
let len = self.len; let len = self.len;
let mut vector = Vec::with_capacity(len); let mut vector = Vec::with_capacity(len);
vector.len = len;
// Unsafe code so this can be optimised to a memcpy (or something // Unsafe code so this can be optimised to a memcpy (or something
// similarly fast) when T is Copy. LLVM is easily confused, so any // similarly fast) when T is Copy. LLVM is easily confused, so any
// extra operations during the loop can prevent this optimisation // extra operations during the loop can prevent this optimisation
{ {
let slice = vector.as_mut_slice();
let this_slice = self.as_slice(); let this_slice = self.as_slice();
let mut i = 0; while vector.len < len {
while i < len {
unsafe { unsafe {
mem::move_val_init( mem::move_val_init(
slice.unsafe_mut_ref(i), vector.as_mut_slice().unsafe_mut_ref(vector.len),
this_slice.unsafe_ref(i).clone()); this_slice.unsafe_ref(vector.len).clone());
} }
i = i + 1; vector.len += 1;
} }
} }
vector vector