diff options
| author | bors <bors@rust-lang.org> | 2021-02-27 14:54:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-02-27 14:54:31 +0000 |
| commit | ec7f8d94df0251532c47330abcb7988d77a1f818 (patch) | |
| tree | 9a857e74ba61ba0d08636e11271b69f7efde0105 | |
| parent | 8e863eb59a10fb0900d7377524a0dc7bf44b9ae3 (diff) | |
| parent | 010e194d6e7e0349518fb2bdb4c4a09a395dfce5 (diff) | |
| download | rust-ec7f8d94df0251532c47330abcb7988d77a1f818.tar.gz rust-ec7f8d94df0251532c47330abcb7988d77a1f818.zip | |
Auto merge of #81874 - tesuji:spec_slice_fill, r=matthewjasper
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.
| -rw-r--r-- | library/core/src/slice/mod.rs | 9 | ||||
| -rw-r--r-- | library/core/src/slice/specialize.rs | 58 |
2 files changed, 60 insertions, 7 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 80c2631c245..b2c5c292f45 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -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}; @@ -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. diff --git a/library/core/src/slice/specialize.rs b/library/core/src/slice/specialize.rs new file mode 100644 index 00000000000..16a9588989c --- /dev/null +++ b/library/core/src/slice/specialize.rs @@ -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); + } + } +} |
