12
12
13
13
use cast:: { forget, transmute} ;
14
14
use clone:: Clone ;
15
- use cmp:: { Ord , Eq , Ordering , TotalEq , TotalOrd } ;
15
+ use cmp:: { Ord , Eq , Ordering , TotalEq , TotalOrd , max } ;
16
16
use container:: { Container , Mutable } ;
17
17
use default:: Default ;
18
18
use fmt;
19
19
use iter:: { DoubleEndedIterator , FromIterator , Extendable , Iterator , range} ;
20
- use libc:: { free, c_void} ;
21
- use mem:: { size_of, move_val_init} ;
20
+ use mem:: { min_align_of, move_val_init, size_of} ;
22
21
use mem;
23
22
use num;
24
23
use num:: { CheckedMul , CheckedAdd } ;
25
24
use ops:: { Add , Drop } ;
26
25
use option:: { None , Option , Some , Expect } ;
27
26
use ptr:: RawPtr ;
28
27
use ptr;
29
- use rt:: global_heap:: { malloc_raw, realloc_raw} ;
30
28
use raw:: Slice ;
31
29
use RawVec = raw :: Vec ;
30
+ use rt:: heap:: { allocate, reallocate, deallocate} ;
32
31
use slice:: { ImmutableEqVector , ImmutableVector , Items , MutItems , MutableVector } ;
33
32
use slice:: { MutableTotalOrdVector , OwnedVector , Vector } ;
34
33
use slice:: { MutableVectorAllocating } ;
@@ -96,7 +95,7 @@ impl<T> Vec<T> {
96
95
Vec :: new ( )
97
96
} else {
98
97
let size = capacity. checked_mul ( & size_of :: < T > ( ) ) . expect ( "capacity overflow" ) ;
99
- let ptr = unsafe { malloc_raw ( size) } ;
98
+ let ptr = unsafe { allocate ( size, min_align_of :: < T > ( ) ) } ;
100
99
Vec { len : 0 , cap : capacity, ptr : ptr as * mut T }
101
100
}
102
101
}
@@ -401,6 +400,16 @@ impl<T> Container for Vec<T> {
401
400
}
402
401
}
403
402
403
+ // FIXME: #13996: need a way to mark the return value as `noalias`
404
+ #[ inline( never) ]
405
+ unsafe fn alloc_or_realloc ( ptr : * mut u8 , size : uint , align : uint , old_size : uint ) -> * mut u8 {
406
+ if old_size == 0 {
407
+ allocate ( size, align)
408
+ } else {
409
+ reallocate ( ptr, size, align, old_size)
410
+ }
411
+ }
412
+
404
413
impl < T > Vec < T > {
405
414
/// Returns the number of elements the vector can hold without
406
415
/// reallocating.
@@ -479,31 +488,35 @@ impl<T> Vec<T> {
479
488
pub fn reserve_exact ( & mut self , capacity : uint ) {
480
489
if capacity > self . cap {
481
490
let size = capacity. checked_mul ( & size_of :: < T > ( ) ) . expect ( "capacity overflow" ) ;
482
- self . cap = capacity;
483
491
unsafe {
484
- self . ptr = realloc_raw ( self . ptr as * mut u8 , size) as * mut T ;
492
+ self . ptr = alloc_or_realloc ( self . ptr as * mut u8 , size, min_align_of :: < T > ( ) ,
493
+ self . cap * size_of :: < T > ( ) ) as * mut T ;
485
494
}
495
+ self . cap = capacity;
486
496
}
487
497
}
488
498
489
- /// Shrink the capacity of the vector to match the length
499
+ /// Shrink the capacity of the vector as much as possible
490
500
///
491
501
/// # Example
492
502
///
493
503
/// ```rust
494
504
/// let mut vec = vec!(1, 2, 3);
495
505
/// vec.shrink_to_fit();
496
- /// assert_eq!(vec.capacity(), vec.len());
497
506
/// ```
498
507
pub fn shrink_to_fit ( & mut self ) {
499
508
if self . len == 0 {
500
- unsafe { free ( self . ptr as * mut c_void ) } ;
501
- self . cap = 0 ;
502
- self . ptr = 0 as * mut T ;
509
+ if self . cap != 0 {
510
+ unsafe {
511
+ deallocate ( self . ptr as * mut u8 , self . cap * size_of :: < T > ( ) , min_align_of :: < T > ( ) )
512
+ }
513
+ self . cap = 0 ;
514
+ }
503
515
} else {
504
516
unsafe {
505
517
// Overflow check is unnecessary as the vector is already at least this large.
506
- self . ptr = realloc_raw ( self . ptr as * mut u8 , self . len * size_of :: < T > ( ) ) as * mut T ;
518
+ self . ptr = reallocate ( self . ptr as * mut u8 , self . len * size_of :: < T > ( ) ,
519
+ min_align_of :: < T > ( ) , self . cap * size_of :: < T > ( ) ) as * mut T ;
507
520
}
508
521
self . cap = self . len ;
509
522
}
@@ -547,14 +560,14 @@ impl<T> Vec<T> {
547
560
#[ inline]
548
561
pub fn push ( & mut self , value : T ) {
549
562
if self . len == self . cap {
550
- if self . cap == 0 { self . cap += 2 }
551
563
let old_size = self . cap * size_of :: < T > ( ) ;
552
- self . cap = self . cap * 2 ;
553
- let size = old_size * 2 ;
564
+ let size = max ( old_size, 2 * size_of :: < T > ( ) ) * 2 ;
554
565
if old_size > size { fail ! ( "capacity overflow" ) }
555
566
unsafe {
556
- self . ptr = realloc_raw ( self . ptr as * mut u8 , size) as * mut T ;
567
+ self . ptr = alloc_or_realloc ( self . ptr as * mut u8 , size, min_align_of :: < T > ( ) ,
568
+ self . cap * size_of :: < T > ( ) ) as * mut u8 as * mut T ;
557
569
}
570
+ self . cap = max ( self . cap , 2 ) * 2 ;
558
571
}
559
572
560
573
unsafe {
@@ -638,9 +651,10 @@ impl<T> Vec<T> {
638
651
pub fn move_iter ( self ) -> MoveItems < T > {
639
652
unsafe {
640
653
let iter = transmute ( self . as_slice ( ) . iter ( ) ) ;
641
- let ptr = self . ptr as * mut c_void ;
654
+ let ptr = self . ptr as * mut u8 ;
655
+ let cap = self . cap ;
642
656
forget ( self ) ;
643
- MoveItems { allocation : ptr, iter : iter }
657
+ MoveItems { allocation : ptr, cap : cap , iter : iter }
644
658
}
645
659
}
646
660
@@ -1386,11 +1400,13 @@ impl<T> Drop for Vec<T> {
1386
1400
fn drop ( & mut self ) {
1387
1401
// This is (and should always remain) a no-op if the fields are
1388
1402
// zeroed (when moving out, because of #[unsafe_no_drop_flag]).
1389
- unsafe {
1390
- for x in self . as_mut_slice ( ) . iter ( ) {
1391
- ptr:: read ( x) ;
1403
+ if self . cap != 0 {
1404
+ unsafe {
1405
+ for x in self . as_mut_slice ( ) . iter ( ) {
1406
+ ptr:: read ( x) ;
1407
+ }
1408
+ deallocate ( self . ptr as * mut u8 , self . cap * size_of :: < T > ( ) , min_align_of :: < T > ( ) )
1392
1409
}
1393
- free ( self . ptr as * mut c_void )
1394
1410
}
1395
1411
}
1396
1412
}
@@ -1409,7 +1425,8 @@ impl<T:fmt::Show> fmt::Show for Vec<T> {
1409
1425
1410
1426
/// An iterator that moves out of a vector.
1411
1427
pub struct MoveItems < T > {
1412
- allocation : * mut c_void , // the block of memory allocated for the vector
1428
+ allocation : * mut u8 , // the block of memory allocated for the vector
1429
+ cap : uint , // the capacity of the vector
1413
1430
iter : Items < ' static , T >
1414
1431
}
1415
1432
@@ -1440,9 +1457,11 @@ impl<T> DoubleEndedIterator<T> for MoveItems<T> {
1440
1457
impl < T > Drop for MoveItems < T > {
1441
1458
fn drop ( & mut self ) {
1442
1459
// destroy the remaining elements
1443
- for _x in * self { }
1444
- unsafe {
1445
- free ( self . allocation )
1460
+ if self . cap != 0 {
1461
+ for _x in * self { }
1462
+ unsafe {
1463
+ deallocate ( self . allocation , self . cap * size_of :: < T > ( ) , min_align_of :: < T > ( ) )
1464
+ }
1446
1465
}
1447
1466
}
1448
1467
}
0 commit comments