Skip to content

Commit 1191bb1

Browse files
committed
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.
2 parents 7432273 + 0df837f commit 1191bb1

File tree

1 file changed

+55
-26
lines changed

1 file changed

+55
-26
lines changed

src/liballoc/vec.rs

+55-26
Original file line numberDiff line numberDiff line change
@@ -1594,40 +1594,69 @@ impl SpecFromElem for u8 {
15941594
}
15951595
}
15961596

1597-
macro_rules! impl_spec_from_elem {
1597+
impl<T: Clone + IsZero> SpecFromElem for T {
1598+
#[inline]
1599+
fn from_elem(elem: T, n: usize) -> Vec<T> {
1600+
if elem.is_zero() {
1601+
return Vec {
1602+
buf: RawVec::with_capacity_zeroed(n),
1603+
len: n,
1604+
}
1605+
}
1606+
let mut v = Vec::with_capacity(n);
1607+
v.extend_with(n, ExtendElement(elem));
1608+
v
1609+
}
1610+
}
1611+
1612+
unsafe trait IsZero {
1613+
/// Whether this value is zero
1614+
fn is_zero(&self) -> bool;
1615+
}
1616+
1617+
macro_rules! impl_is_zero {
15981618
($t: ty, $is_zero: expr) => {
1599-
impl SpecFromElem for $t {
1619+
unsafe impl IsZero for $t {
16001620
#[inline]
1601-
fn from_elem(elem: $t, n: usize) -> Vec<$t> {
1602-
if $is_zero(elem) {
1603-
return Vec {
1604-
buf: RawVec::with_capacity_zeroed(n),
1605-
len: n,
1606-
}
1607-
}
1608-
let mut v = Vec::with_capacity(n);
1609-
v.extend_with(n, ExtendElement(elem));
1610-
v
1621+
fn is_zero(&self) -> bool {
1622+
$is_zero(*self)
16111623
}
16121624
}
1613-
};
1625+
}
16141626
}
16151627

1616-
impl_spec_from_elem!(i8, |x| x == 0);
1617-
impl_spec_from_elem!(i16, |x| x == 0);
1618-
impl_spec_from_elem!(i32, |x| x == 0);
1619-
impl_spec_from_elem!(i64, |x| x == 0);
1620-
impl_spec_from_elem!(i128, |x| x == 0);
1621-
impl_spec_from_elem!(isize, |x| x == 0);
1628+
impl_is_zero!(i8, |x| x == 0);
1629+
impl_is_zero!(i16, |x| x == 0);
1630+
impl_is_zero!(i32, |x| x == 0);
1631+
impl_is_zero!(i64, |x| x == 0);
1632+
impl_is_zero!(i128, |x| x == 0);
1633+
impl_is_zero!(isize, |x| x == 0);
1634+
1635+
impl_is_zero!(u16, |x| x == 0);
1636+
impl_is_zero!(u32, |x| x == 0);
1637+
impl_is_zero!(u64, |x| x == 0);
1638+
impl_is_zero!(u128, |x| x == 0);
1639+
impl_is_zero!(usize, |x| x == 0);
1640+
1641+
impl_is_zero!(char, |x| x == '\0');
1642+
1643+
impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
1644+
impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
16221645

1623-
impl_spec_from_elem!(u16, |x| x == 0);
1624-
impl_spec_from_elem!(u32, |x| x == 0);
1625-
impl_spec_from_elem!(u64, |x| x == 0);
1626-
impl_spec_from_elem!(u128, |x| x == 0);
1627-
impl_spec_from_elem!(usize, |x| x == 0);
1646+
unsafe impl<T: ?Sized> IsZero for *const T {
1647+
#[inline]
1648+
fn is_zero(&self) -> bool {
1649+
(*self).is_null()
1650+
}
1651+
}
1652+
1653+
unsafe impl<T: ?Sized> IsZero for *mut T {
1654+
#[inline]
1655+
fn is_zero(&self) -> bool {
1656+
(*self).is_null()
1657+
}
1658+
}
16281659

1629-
impl_spec_from_elem!(f32, |x: f32| x.to_bits() == 0);
1630-
impl_spec_from_elem!(f64, |x: f64| x.to_bits() == 0);
16311660

16321661
////////////////////////////////////////////////////////////////////////////////
16331662
// Common trait implementations for Vec

0 commit comments

Comments
 (0)