Skip to content

Commit

Permalink
Auto merge of #81874 - tesuji:spec_slice_fill, r=matthewjasper
Browse files Browse the repository at this point in the history
Specialize slice::fill with Copy type and u8/i8/bool

I don't expect rustperf could measure any perf improvements with this changes
since `slice::fill` is newly added.

Godbolt link for this change: <https://rust.godbolt.org/z/r3fzee>.

r? `@matthewjasper` since this patch added new specialization.
  • Loading branch information
bors committed Feb 27, 2021
2 parents 8e863eb + 010e194 commit ec7f8d9
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
9 changes: 2 additions & 7 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod iter;
mod raw;
mod rotate;
mod sort;
mod specialize;

#[stable(feature = "rust1", since = "1.0.0")]
pub use iter::{Chunks, ChunksMut, Windows};
Expand Down Expand Up @@ -2866,13 +2867,7 @@ impl<T> [T] {
where
T: Clone,
{
if let Some((last, elems)) = self.split_last_mut() {
for el in elems {
el.clone_from(&value);
}

*last = value
}
specialize::SpecFill::spec_fill(self, value);
}

/// Fills `self` with elements returned by calling a closure repeatedly.
Expand Down
58 changes: 58 additions & 0 deletions library/core/src/slice/specialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::ptr::write_bytes;

pub(super) trait SpecFill<T> {
fn spec_fill(&mut self, value: T);
}

impl<T: Clone> SpecFill<T> for [T] {
default fn spec_fill(&mut self, value: T) {
if let Some((last, elems)) = self.split_last_mut() {
for el in elems {
el.clone_from(&value);
}

*last = value
}
}
}

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);
}
}
}

0 comments on commit ec7f8d9

Please sign in to comment.