diff options
| author | bors <bors@rust-lang.org> | 2014-05-10 23:21:44 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-05-10 23:21:44 -0700 |
| commit | adb8b0b230d5e5c79b4f873825b3d3cff8d1bc8f (patch) | |
| tree | 770b50ee78ec3b79feeaf70f73f50f1166bed980 /src/libstd/vec.rs | |
| parent | 11571cd9c1cde63c3b46ca65e608b84647785ac8 (diff) | |
| parent | 81fadbbc4182c5a34e0d2ff698471abfc1ec0e33 (diff) | |
| download | rust-adb8b0b230d5e5c79b4f873825b3d3cff8d1bc8f.tar.gz rust-adb8b0b230d5e5c79b4f873825b3d3cff8d1bc8f.zip | |
auto merge of #14006 : thestinger/rust/jemalloc, r=alexcrichton
Closes #11807
Diffstat (limited to 'src/libstd/vec.rs')
| -rw-r--r-- | src/libstd/vec.rs | 89 |
1 files changed, 61 insertions, 28 deletions
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index da01da26709..aa10be1d1be 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -12,13 +12,12 @@ use cast::{forget, transmute}; use clone::Clone; -use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd}; +use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd, max}; use container::{Container, Mutable}; use default::Default; use fmt; use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator, range}; -use libc::{free, c_void}; -use mem::{size_of, move_val_init}; +use mem::{min_align_of, move_val_init, size_of}; use mem; use num; use num::{CheckedMul, CheckedAdd}; @@ -26,9 +25,9 @@ use ops::{Add, Drop}; use option::{None, Option, Some, Expect}; use ptr::RawPtr; use ptr; -use rt::global_heap::{malloc_raw, realloc_raw}; use raw::Slice; use RawVec = raw::Vec; +use rt::heap::{allocate, reallocate, deallocate}; use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector}; use slice::{MutableTotalOrdVector, OwnedVector, Vector}; use slice::{MutableVectorAllocating}; @@ -92,11 +91,12 @@ impl<T> Vec<T> { /// let vec: Vec<int> = Vec::with_capacity(10); /// ``` pub fn with_capacity(capacity: uint) -> Vec<T> { + if size_of::<T>() == 0 { return Vec { len: 0, cap: ::uint::MAX, ptr: 0 as *mut T } } if capacity == 0 { Vec::new() } else { let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow"); - let ptr = unsafe { malloc_raw(size) }; + let ptr = unsafe { allocate(size, min_align_of::<T>()) }; Vec { len: 0, cap: capacity, ptr: ptr as *mut T } } } @@ -401,6 +401,23 @@ impl<T> Container for Vec<T> { } } +// FIXME: #13996: need a way to mark the return value as `noalias` +#[inline(never)] +unsafe fn alloc_or_realloc<T>(ptr: *mut T, size: uint, old_size: uint) -> *mut T { + if old_size == 0 { + allocate(size, min_align_of::<T>()) as *mut T + } else { + reallocate(ptr as *mut u8, size, min_align_of::<T>(), old_size) as *mut T + } +} + +#[inline] +unsafe fn dealloc<T>(ptr: *mut T, len: uint) { + if size_of::<T>() != 0 { + deallocate(ptr as *mut u8, len * size_of::<T>(), min_align_of::<T>()) + } +} + impl<T> Vec<T> { /// Returns the number of elements the vector can hold without /// reallocating. @@ -477,33 +494,38 @@ impl<T> Vec<T> { /// assert_eq!(vec.capacity(), 11); /// ``` pub fn reserve_exact(&mut self, capacity: uint) { + if size_of::<T>() == 0 { return } if capacity > self.cap { let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow"); - self.cap = capacity; unsafe { - self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T; + self.ptr = alloc_or_realloc(self.ptr, size, self.cap * size_of::<T>()); } + self.cap = capacity; } } - /// Shrink the capacity of the vector to match the length + /// Shrink the capacity of the vector as much as possible /// /// # Example /// /// ```rust /// let mut vec = vec!(1, 2, 3); /// vec.shrink_to_fit(); - /// assert_eq!(vec.capacity(), vec.len()); /// ``` pub fn shrink_to_fit(&mut self) { + if size_of::<T>() == 0 { return } if self.len == 0 { - unsafe { free(self.ptr as *mut c_void) }; - self.cap = 0; - self.ptr = 0 as *mut T; + if self.cap != 0 { + unsafe { + dealloc(self.ptr, self.cap) + } + self.cap = 0; + } } else { unsafe { // Overflow check is unnecessary as the vector is already at least this large. - self.ptr = realloc_raw(self.ptr as *mut u8, self.len * size_of::<T>()) as *mut T; + self.ptr = reallocate(self.ptr as *mut u8, self.len * size_of::<T>(), + min_align_of::<T>(), self.cap * size_of::<T>()) as *mut T; } self.cap = self.len; } @@ -546,15 +568,20 @@ impl<T> Vec<T> { /// ``` #[inline] pub fn push(&mut self, value: T) { + if size_of::<T>() == 0 { + // zero-size types consume no memory, so we can't rely on the address space running out + self.len = self.len.checked_add(&1).expect("length overflow"); + unsafe { forget(value); } + return + } if self.len == self.cap { - if self.cap == 0 { self.cap += 2 } let old_size = self.cap * size_of::<T>(); - self.cap = self.cap * 2; - let size = old_size * 2; + let size = max(old_size, 2 * size_of::<T>()) * 2; if old_size > size { fail!("capacity overflow") } unsafe { - self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T; + self.ptr = alloc_or_realloc(self.ptr, size, self.cap * size_of::<T>()); } + self.cap = max(self.cap, 2) * 2; } unsafe { @@ -638,9 +665,10 @@ impl<T> Vec<T> { pub fn move_iter(self) -> MoveItems<T> { unsafe { let iter = transmute(self.as_slice().iter()); - let ptr = self.ptr as *mut c_void; + let ptr = self.ptr; + let cap = self.cap; forget(self); - MoveItems { allocation: ptr, iter: iter } + MoveItems { allocation: ptr, cap: cap, iter: iter } } } @@ -1386,11 +1414,13 @@ impl<T> Drop for Vec<T> { fn drop(&mut self) { // This is (and should always remain) a no-op if the fields are // zeroed (when moving out, because of #[unsafe_no_drop_flag]). - unsafe { - for x in self.as_mut_slice().iter() { - ptr::read(x); + if self.cap != 0 { + unsafe { + for x in self.as_mut_slice().iter() { + ptr::read(x); + } + dealloc(self.ptr, self.cap) } - free(self.ptr as *mut c_void) } } } @@ -1409,7 +1439,8 @@ impl<T:fmt::Show> fmt::Show for Vec<T> { /// An iterator that moves out of a vector. pub struct MoveItems<T> { - allocation: *mut c_void, // the block of memory allocated for the vector + allocation: *mut T, // the block of memory allocated for the vector + cap: uint, // the capacity of the vector iter: Items<'static, T> } @@ -1440,9 +1471,11 @@ impl<T> DoubleEndedIterator<T> for MoveItems<T> { impl<T> Drop for MoveItems<T> { fn drop(&mut self) { // destroy the remaining elements - for _x in *self {} - unsafe { - free(self.allocation) + if self.cap != 0 { + for _x in *self {} + unsafe { + dealloc(self.allocation, self.cap); + } } } } @@ -1493,7 +1526,7 @@ impl<T> FromVec<T> for ~[T] { let vp = v.as_mut_ptr(); unsafe { - let ret = malloc_raw(size) as *mut RawVec<()>; + let ret = allocate(size, 8) as *mut RawVec<()>; (*ret).fill = len * mem::nonzero_size_of::<T>(); (*ret).alloc = len * mem::nonzero_size_of::<T>(); |
