Skip to content

Commit aaf6e06

Browse files
committed
use jemalloc to implement Vec<T>
1 parent 03a5eb4 commit aaf6e06

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

src/libstd/rt/heap.rs

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// FIXME: #13994: port to the sized deallocation API when available
12+
// FIXME: #13996: need a way to mark the `allocate` and `reallocate` return values as `noalias`
13+
1114
use intrinsics::{abort, cttz32};
1215
use libc::{c_int, c_void, size_t};
1316
use ptr::RawPtr;

src/libstd/vec.rs

+46-27
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,22 @@
1212
1313
use cast::{forget, transmute};
1414
use clone::Clone;
15-
use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd};
15+
use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd, max};
1616
use container::{Container, Mutable};
1717
use default::Default;
1818
use fmt;
1919
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};
2221
use mem;
2322
use num;
2423
use num::{CheckedMul, CheckedAdd};
2524
use ops::{Add, Drop};
2625
use option::{None, Option, Some, Expect};
2726
use ptr::RawPtr;
2827
use ptr;
29-
use rt::global_heap::{malloc_raw, realloc_raw};
3028
use raw::Slice;
3129
use RawVec = raw::Vec;
30+
use rt::heap::{allocate, reallocate, deallocate};
3231
use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
3332
use slice::{MutableTotalOrdVector, OwnedVector, Vector};
3433
use slice::{MutableVectorAllocating};
@@ -96,7 +95,7 @@ impl<T> Vec<T> {
9695
Vec::new()
9796
} else {
9897
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>()) };
10099
Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
101100
}
102101
}
@@ -401,6 +400,16 @@ impl<T> Container for Vec<T> {
401400
}
402401
}
403402

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+
404413
impl<T> Vec<T> {
405414
/// Returns the number of elements the vector can hold without
406415
/// reallocating.
@@ -479,31 +488,35 @@ impl<T> Vec<T> {
479488
pub fn reserve_exact(&mut self, capacity: uint) {
480489
if capacity > self.cap {
481490
let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
482-
self.cap = capacity;
483491
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;
485494
}
495+
self.cap = capacity;
486496
}
487497
}
488498

489-
/// Shrink the capacity of the vector to match the length
499+
/// Shrink the capacity of the vector as much as possible
490500
///
491501
/// # Example
492502
///
493503
/// ```rust
494504
/// let mut vec = vec!(1, 2, 3);
495505
/// vec.shrink_to_fit();
496-
/// assert_eq!(vec.capacity(), vec.len());
497506
/// ```
498507
pub fn shrink_to_fit(&mut self) {
499508
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+
}
503515
} else {
504516
unsafe {
505517
// 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;
507520
}
508521
self.cap = self.len;
509522
}
@@ -547,14 +560,14 @@ impl<T> Vec<T> {
547560
#[inline]
548561
pub fn push(&mut self, value: T) {
549562
if self.len == self.cap {
550-
if self.cap == 0 { self.cap += 2 }
551563
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;
554565
if old_size > size { fail!("capacity overflow") }
555566
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;
557569
}
570+
self.cap = max(self.cap, 2) * 2;
558571
}
559572

560573
unsafe {
@@ -638,9 +651,10 @@ impl<T> Vec<T> {
638651
pub fn move_iter(self) -> MoveItems<T> {
639652
unsafe {
640653
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;
642656
forget(self);
643-
MoveItems { allocation: ptr, iter: iter }
657+
MoveItems { allocation: ptr, cap: cap, iter: iter }
644658
}
645659
}
646660

@@ -1386,11 +1400,13 @@ impl<T> Drop for Vec<T> {
13861400
fn drop(&mut self) {
13871401
// This is (and should always remain) a no-op if the fields are
13881402
// 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>())
13921409
}
1393-
free(self.ptr as *mut c_void)
13941410
}
13951411
}
13961412
}
@@ -1409,7 +1425,8 @@ impl<T:fmt::Show> fmt::Show for Vec<T> {
14091425

14101426
/// An iterator that moves out of a vector.
14111427
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
14131430
iter: Items<'static, T>
14141431
}
14151432

@@ -1440,9 +1457,11 @@ impl<T> DoubleEndedIterator<T> for MoveItems<T> {
14401457
impl<T> Drop for MoveItems<T> {
14411458
fn drop(&mut self) {
14421459
// 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+
}
14461465
}
14471466
}
14481467
}

0 commit comments

Comments
 (0)