Make Vec::clone and slice::to_owned failure-safe
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user