@@ -315,15 +315,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
315
315
#[ inline]
316
316
fn to_owned ( & self ) -> ~[ T ] {
317
317
let len = self . len ( ) ;
318
- let mut result = Vec :: with_capacity ( len) ;
319
- // Unsafe code so this can be optimised to a memcpy (or something
320
- // similarly fast) when T is Copy. LLVM is easily confused, so any
321
- // extra operations during the loop can prevent this optimisation
318
+ let data_size = len. checked_mul ( & mem:: size_of :: < T > ( ) ) ;
319
+ let data_size = data_size. expect ( "overflow in to_owned()" ) ;
320
+ let size = mem:: size_of :: < RawVec < ( ) > > ( ) . checked_add ( & data_size) ;
321
+ let size = size. expect ( "overflow in to_owned()" ) ;
322
+
322
323
unsafe {
324
+ let ret = malloc_raw ( size) as * mut RawVec < ( ) > ;
325
+
326
+ ( * ret) . fill = len * mem:: nonzero_size_of :: < T > ( ) ;
327
+ ( * ret) . alloc = len * mem:: nonzero_size_of :: < T > ( ) ;
328
+
329
+ // Be careful with the following loop. We want it to be optimized
330
+ // to a memcpy (or something similarly fast) when T is Copy. LLVM
331
+ // is easily confused, so any extra operations during the loop can
332
+ // prevent this optimization.
323
333
let mut i = 0 ;
324
- let p = result. as_mut_ptr ( ) ;
325
- // Use try_finally here otherwise the write to length
326
- // inside the loop stops LLVM from optimising this.
334
+ let p = & mut ( * ret) . data as * mut _ as * mut T ;
327
335
try_finally (
328
336
& mut i, ( ) ,
329
337
|i, ( ) | while * i < len {
@@ -332,9 +340,15 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
332
340
self . unsafe_ref ( * i) . clone ( ) ) ;
333
341
* i += 1 ;
334
342
} ,
335
- |i| result. set_len ( * i) ) ;
343
+ |i| if * i < len {
344
+ // we must be failing, clean up after ourselves
345
+ for j in range ( 0 , * i as int ) {
346
+ ptr:: read ( & * p. offset ( j) ) ;
347
+ }
348
+ exchange_free ( ret as * u8 ) ;
349
+ } ) ;
350
+ cast:: transmute ( ret)
336
351
}
337
- result. move_iter ( ) . collect ( )
338
352
}
339
353
340
354
#[ inline( always) ]
0 commit comments