Skip to content

Commit 55e52f3

Browse files
committed
Implement Vec::from_elem specialization for all Copy types
If the input element is zero, `Vec::from_elem` can just invoke `calloc` for any `Copy` type. If the input is non-zero, but its size is 1, it can allocate and then `memset` the buffer.
1 parent 5997806 commit 55e52f3

File tree

2 files changed

+32
-46
lines changed

2 files changed

+32
-46
lines changed

src/libcollections/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#![feature(box_patterns)]
3636
#![feature(box_syntax)]
3737
#![cfg_attr(not(test), feature(char_escape_debug))]
38-
#![cfg_attr(not(test), feature(core_float))]
3938
#![feature(core_intrinsics)]
4039
#![feature(dropck_eyepatch)]
4140
#![feature(exact_size_is_empty)]

src/libcollections/vec.rs

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ use core::hash::{self, Hash};
7777
use core::intrinsics::{arith_offset, assume};
7878
use core::iter::{FromIterator, FusedIterator, TrustedLen};
7979
use core::mem;
80-
#[cfg(not(test))]
81-
use core::num::Float;
8280
use core::ops::{InPlace, Index, IndexMut, Place, Placer};
8381
use core::ops;
8482
use core::ptr;
@@ -1388,59 +1386,48 @@ impl<T: Clone> SpecFromElem for T {
13881386
}
13891387
}
13901388

1391-
impl SpecFromElem for u8 {
1392-
#[inline]
1393-
fn from_elem(elem: u8, n: usize) -> Vec<u8> {
1394-
if elem == 0 {
1389+
unsafe fn chunked_or<T, U: ops::BitOr<Output = U> + Copy>(x: T) -> U {
1390+
let p = &x as *const T as *const U;
1391+
let len = mem::size_of::<T>() / mem::size_of::<U>();
1392+
slice::from_raw_parts(p, len).iter().fold(mem::zeroed(), |state, &x| state | x)
1393+
}
1394+
1395+
fn is_zero<T: Copy>(x: T) -> bool {
1396+
unsafe {
1397+
match mem::align_of::<T>() {
1398+
n if n % 16 == 0 => 0u128 == chunked_or(x),
1399+
n if n % 8 == 0 => 0u64 == chunked_or(x),
1400+
n if n % 4 == 0 => 0u32 == chunked_or(x),
1401+
n if n % 2 == 0 => 0u16 == chunked_or(x),
1402+
_ => 0u8 == chunked_or(x),
1403+
}
1404+
}
1405+
}
1406+
1407+
impl<T: Copy> SpecFromElem for T {
1408+
default fn from_elem(elem: Self, n: usize) -> Vec<Self> {
1409+
if is_zero(elem) {
13951410
return Vec {
13961411
buf: RawVec::with_capacity_zeroed(n),
13971412
len: n,
13981413
}
13991414
}
1400-
unsafe {
1401-
let mut v = Vec::with_capacity(n);
1402-
ptr::write_bytes(v.as_mut_ptr(), elem, n);
1403-
v.set_len(n);
1404-
v
1405-
}
1406-
}
1407-
}
14081415

1409-
macro_rules! impl_spec_from_elem {
1410-
($t: ty, $is_zero: expr) => {
1411-
impl SpecFromElem for $t {
1412-
#[inline]
1413-
fn from_elem(elem: $t, n: usize) -> Vec<$t> {
1414-
if $is_zero(elem) {
1415-
return Vec {
1416-
buf: RawVec::with_capacity_zeroed(n),
1417-
len: n,
1418-
}
1419-
}
1420-
let mut v = Vec::with_capacity(n);
1421-
v.extend_with_element(n, elem);
1422-
v
1416+
let mut v = Vec::with_capacity(n);
1417+
if mem::size_of::<T>() == 1 {
1418+
unsafe {
1419+
// let elem: u8 = mem::transmute(elem);
1420+
let elem: u8 = *(&elem as *const T as *const u8);
1421+
ptr::write_bytes(v.as_mut_ptr(), elem, n);
1422+
v.set_len(n);
14231423
}
1424+
} else {
1425+
v.extend_with_element(n, elem);
14241426
}
1425-
};
1427+
v
1428+
}
14261429
}
14271430

1428-
impl_spec_from_elem!(i8, |x| x == 0);
1429-
impl_spec_from_elem!(i16, |x| x == 0);
1430-
impl_spec_from_elem!(i32, |x| x == 0);
1431-
impl_spec_from_elem!(i64, |x| x == 0);
1432-
impl_spec_from_elem!(i128, |x| x == 0);
1433-
impl_spec_from_elem!(isize, |x| x == 0);
1434-
1435-
impl_spec_from_elem!(u16, |x| x == 0);
1436-
impl_spec_from_elem!(u32, |x| x == 0);
1437-
impl_spec_from_elem!(u64, |x| x == 0);
1438-
impl_spec_from_elem!(u128, |x| x == 0);
1439-
impl_spec_from_elem!(usize, |x| x == 0);
1440-
1441-
impl_spec_from_elem!(f32, |x: f32| x == 0. && x.is_sign_positive());
1442-
impl_spec_from_elem!(f64, |x: f64| x == 0. && x.is_sign_positive());
1443-
14441431
////////////////////////////////////////////////////////////////////////////////
14451432
// Common trait implementations for Vec
14461433
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)