@@ -668,15 +668,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
668
668
#[ inline]
669
669
fn to_owned ( & self ) -> ~[ T ] {
670
670
let len = self . len ( ) ;
671
- let mut result = Vec :: with_capacity ( len) ;
672
- // Unsafe code so this can be optimised to a memcpy (or something
673
- // similarly fast) when T is Copy. LLVM is easily confused, so any
674
- // extra operations during the loop can prevent this optimisation
671
+ let data_size = len. checked_mul ( & mem:: size_of :: < T > ( ) ) ;
672
+ let data_size = data_size. expect ( "overflow in to_owned()" ) ;
673
+ let size = mem:: size_of :: < RawVec < ( ) > > ( ) . checked_add ( & data_size) ;
674
+ let size = size. expect ( "overflow in to_owned()" ) ;
675
+
675
676
unsafe {
677
+ let ret = malloc_raw ( size) as * mut RawVec < ( ) > ;
678
+
679
+ ( * ret) . fill = len * mem:: nonzero_size_of :: < T > ( ) ;
680
+ ( * ret) . alloc = len * mem:: nonzero_size_of :: < T > ( ) ;
681
+
682
+ // Be careful with the following loop. We want it to be optimized
683
+ // to a memcpy (or something similarly fast) when T is Copy. LLVM
684
+ // is easily confused, so any extra operations during the loop can
685
+ // prevent this optimization.
676
686
let mut i = 0 ;
677
- let p = result. as_mut_ptr ( ) ;
678
- // Use try_finally here otherwise the write to length
679
- // inside the loop stops LLVM from optimising this.
687
+ let p = & mut ( * ret) . data as * mut _ as * mut T ;
680
688
try_finally (
681
689
& mut i, ( ) ,
682
690
|i, ( ) | while * i < len {
@@ -685,9 +693,15 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
685
693
self . unsafe_ref ( * i) . clone ( ) ) ;
686
694
* i += 1 ;
687
695
} ,
688
- |i| result. set_len ( * i) ) ;
696
+ |i| if * i < len {
697
+ // we must be failing, clean up after ourselves
698
+ for j in range ( 0 , * i as int ) {
699
+ ptr:: read ( & * p. offset ( j) ) ;
700
+ }
701
+ exchange_free ( ret as * u8 ) ;
702
+ } ) ;
703
+ cast:: transmute ( ret)
689
704
}
690
- result. move_iter ( ) . collect ( )
691
705
}
692
706
693
707
#[ inline( always) ]
0 commit comments