Skip to content

Generalize and inline slice::fill specializations #83245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}
}
}