Skip to content

Commit

Permalink
Auto merge of rust-lang#83245 - the8472:generalize-slice-fill, r=m-ou-se
Browse files Browse the repository at this point in the history
Generalize and inline slice::fill specializations

This makes the memset specialization applicable to more types. And since the code now lives in a generic method it is also eligible for cross-crate inlining which  should fix rust-lang#83235
  • Loading branch information
bors committed Mar 27, 2021
2 parents aef1140 + d7fdd90 commit 1010038
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 36 deletions.
13 changes: 13 additions & 0 deletions library/core/benches/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,16 @@ rotate!(rotate_16_usize_4, 16, |i| [i; 4]);
rotate!(rotate_16_usize_5, 16, |i| [i; 5]);
rotate!(rotate_64_usize_4, 64, |i| [i; 4]);
rotate!(rotate_64_usize_5, 64, |i| [i; 5]);

#[bench]
fn fill_byte_sized(b: &mut Bencher) {
#[derive(Copy, Clone)]
struct NewType(u8);

let mut ary = [NewType(0); 1024];

b.iter(|| {
let slice = &mut ary[..];
black_box(slice.fill(black_box(NewType(42))));
});
}
49 changes: 13 additions & 36 deletions library/core/src/slice/specialize.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::mem::{size_of, transmute_copy};
use crate::ptr::write_bytes;

pub(super) trait SpecFill<T> {
Expand All @@ -17,42 +18,18 @@ impl<T: Clone> SpecFill<T> for [T] {
}

impl<T: Copy> SpecFill<T> for [T] {
default fn spec_fill(&mut self, value: T) {
for item in self.iter_mut() {
*item = value;
}
}
}

impl SpecFill<u8> for [u8] {
fn spec_fill(&mut self, value: u8) {
// SAFETY: this is slice of u8
unsafe {
let ptr = self.as_mut_ptr();
let len = self.len();
write_bytes(ptr, value, len);
}
}
}

impl SpecFill<i8> for [i8] {
fn spec_fill(&mut self, value: i8) {
// SAFETY: this is slice of i8
unsafe {
let ptr = self.as_mut_ptr();
let len = self.len();
write_bytes(ptr, value as u8, len);
}
}
}

impl SpecFill<bool> for [bool] {
fn spec_fill(&mut self, value: bool) {
// SAFETY: this is slice of bool
unsafe {
let ptr = self.as_mut_ptr();
let len = self.len();
write_bytes(ptr, value as u8, len);
fn spec_fill(&mut self, value: T) {
if size_of::<T>() == 1 {
// SAFETY: The size_of check above ensures that values are 1 byte wide, as required
// for the transmute and write_bytes
unsafe {
let value: u8 = transmute_copy(&value);
write_bytes(self.as_mut_ptr(), value, self.len());
}
} else {
for item in self.iter_mut() {
*item = value;
}
}
}
}

0 comments on commit 1010038

Please sign in to comment.