提交 cc939ac3 编写于 作者: M Mike Hommey

Add vec![ptr::null{,_mut}(); n] optimization, like vec![0; n]

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 adds the same optimization for vec![ptr::null(); n] and
vec![ptr::null_mut(); n], assuming their bit value is 0 (which is true
on all currently supported platforms).

This does so by adding an intermediate trait IsZero, which looks very
much like nonzero::Zeroable, but that one is on the way out, and doesn't
apply to pointers anyways.

Adding such a trait allows to avoid repeating the logic using
with_capacity_zeroed or with_capacity, or making the macro more complex
to support generics.
上级 06fa27d7
......@@ -1567,40 +1567,67 @@ fn from_elem(elem: u8, n: usize) -> Vec<u8> {
}
}
macro_rules! impl_spec_from_elem {
impl<T: Clone + IsZero> SpecFromElem for T {
#[inline]
fn from_elem(elem: T, n: usize) -> Vec<T> {
if elem.is_zero() {
return Vec {
buf: RawVec::with_capacity_zeroed(n),
len: n,
}
}
let mut v = Vec::with_capacity(n);
v.extend_with(n, ExtendElement(elem));
v
}
}
unsafe trait IsZero {
/// Whether this value is zero
fn is_zero(&self) -> bool;
}
macro_rules! impl_is_zero {
($t: ty, $is_zero: expr) => {
impl SpecFromElem for $t {
unsafe impl IsZero for $t {
#[inline]
fn from_elem(elem: $t, n: usize) -> Vec<$t> {
if $is_zero(elem) {
return Vec {
buf: RawVec::with_capacity_zeroed(n),
len: n,
}
}
let mut v = Vec::with_capacity(n);
v.extend_with(n, ExtendElement(elem));
v
fn is_zero(&self) -> bool {
$is_zero(*self)
}
}
};
}
}
impl_spec_from_elem!(i8, |x| x == 0);
impl_spec_from_elem!(i16, |x| x == 0);
impl_spec_from_elem!(i32, |x| x == 0);
impl_spec_from_elem!(i64, |x| x == 0);
impl_spec_from_elem!(i128, |x| x == 0);
impl_spec_from_elem!(isize, |x| x == 0);
impl_is_zero!(i8, |x| x == 0);
impl_is_zero!(i16, |x| x == 0);
impl_is_zero!(i32, |x| x == 0);
impl_is_zero!(i64, |x| x == 0);
impl_is_zero!(i128, |x| x == 0);
impl_is_zero!(isize, |x| x == 0);
impl_spec_from_elem!(u16, |x| x == 0);
impl_spec_from_elem!(u32, |x| x == 0);
impl_spec_from_elem!(u64, |x| x == 0);
impl_spec_from_elem!(u128, |x| x == 0);
impl_spec_from_elem!(usize, |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!(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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册