1
Fork 0

Rollup merge of #49496 - glandium:master, r=sfackler

Add more vec![... ; n] optimizations

vec![0; n], via implementations of SpecFromElem, has an optimization that uses with_capacity_zeroed instead of with_capacity, which will use calloc instead of malloc, and avoid an extra memset.

This PR adds the same optimization for ptr::null, ptr::null_mut, and None, when their in-memory representation is zeroes.
This commit is contained in:
kennytm 2018-04-05 16:51:21 +08:00 committed by GitHub
commit 23689cc8e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1594,12 +1594,10 @@ impl SpecFromElem for u8 {
} }
} }
macro_rules! impl_spec_from_elem { impl<T: Clone + IsZero> SpecFromElem for T {
($t: ty, $is_zero: expr) => {
impl SpecFromElem for $t {
#[inline] #[inline]
fn from_elem(elem: $t, n: usize) -> Vec<$t> { fn from_elem(elem: T, n: usize) -> Vec<T> {
if $is_zero(elem) { if elem.is_zero() {
return Vec { return Vec {
buf: RawVec::with_capacity_zeroed(n), buf: RawVec::with_capacity_zeroed(n),
len: n, len: n,
@ -1610,24 +1608,55 @@ macro_rules! impl_spec_from_elem {
v v
} }
} }
};
unsafe trait IsZero {
/// Whether this value is zero
fn is_zero(&self) -> bool;
} }
impl_spec_from_elem!(i8, |x| x == 0); macro_rules! impl_is_zero {
impl_spec_from_elem!(i16, |x| x == 0); ($t: ty, $is_zero: expr) => {
impl_spec_from_elem!(i32, |x| x == 0); unsafe impl IsZero for $t {
impl_spec_from_elem!(i64, |x| x == 0); #[inline]
impl_spec_from_elem!(i128, |x| x == 0); fn is_zero(&self) -> bool {
impl_spec_from_elem!(isize, |x| x == 0); $is_zero(*self)
}
}
}
}
impl_spec_from_elem!(u16, |x| x == 0); impl_is_zero!(i8, |x| x == 0);
impl_spec_from_elem!(u32, |x| x == 0); impl_is_zero!(i16, |x| x == 0);
impl_spec_from_elem!(u64, |x| x == 0); impl_is_zero!(i32, |x| x == 0);
impl_spec_from_elem!(u128, |x| x == 0); impl_is_zero!(i64, |x| x == 0);
impl_spec_from_elem!(usize, |x| x == 0); impl_is_zero!(i128, |x| x == 0);
impl_is_zero!(isize, |x| x == 0);
impl_is_zero!(u16, |x| x == 0);
impl_is_zero!(u32, |x| x == 0);
impl_is_zero!(u64, |x| x == 0);
impl_is_zero!(u128, |x| x == 0);
impl_is_zero!(usize, |x| x == 0);
impl_is_zero!(char, |x| x == '\0');
impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
unsafe impl<T: ?Sized> IsZero for *const T {
#[inline]
fn is_zero(&self) -> bool {
(*self).is_null()
}
}
unsafe impl<T: ?Sized> IsZero for *mut T {
#[inline]
fn is_zero(&self) -> bool {
(*self).is_null()
}
}
impl_spec_from_elem!(f32, |x: f32| x.to_bits() == 0);
impl_spec_from_elem!(f64, |x: f64| x.to_bits() == 0);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Common trait implementations for Vec // Common trait implementations for Vec