Skip to content

Commit 1010038

Browse files
committed
Auto merge of rust-lang#83245 - the8472:generalize-slice-fill, r=m-ou-se
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
2 parents aef1140 + d7fdd90 commit 1010038

File tree

2 files changed

+26
-36
lines changed

2 files changed

+26
-36
lines changed

library/core/benches/slice.rs

+13
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,16 @@ rotate!(rotate_16_usize_4, 16, |i| [i; 4]);
114114
rotate!(rotate_16_usize_5, 16, |i| [i; 5]);
115115
rotate!(rotate_64_usize_4, 64, |i| [i; 4]);
116116
rotate!(rotate_64_usize_5, 64, |i| [i; 5]);
117+
118+
#[bench]
119+
fn fill_byte_sized(b: &mut Bencher) {
120+
#[derive(Copy, Clone)]
121+
struct NewType(u8);
122+
123+
let mut ary = [NewType(0); 1024];
124+
125+
b.iter(|| {
126+
let slice = &mut ary[..];
127+
black_box(slice.fill(black_box(NewType(42))));
128+
});
129+
}

library/core/src/slice/specialize.rs

+13-36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::mem::{size_of, transmute_copy};
12
use crate::ptr::write_bytes;
23

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

1920
impl<T: Copy> SpecFill<T> for [T] {
20-
default fn spec_fill(&mut self, value: T) {
21-
for item in self.iter_mut() {
22-
*item = value;
23-
}
24-
}
25-
}
26-
27-
impl SpecFill<u8> for [u8] {
28-
fn spec_fill(&mut self, value: u8) {
29-
// SAFETY: this is slice of u8
30-
unsafe {
31-
let ptr = self.as_mut_ptr();
32-
let len = self.len();
33-
write_bytes(ptr, value, len);
34-
}
35-
}
36-
}
37-
38-
impl SpecFill<i8> for [i8] {
39-
fn spec_fill(&mut self, value: i8) {
40-
// SAFETY: this is slice of i8
41-
unsafe {
42-
let ptr = self.as_mut_ptr();
43-
let len = self.len();
44-
write_bytes(ptr, value as u8, len);
45-
}
46-
}
47-
}
48-
49-
impl SpecFill<bool> for [bool] {
50-
fn spec_fill(&mut self, value: bool) {
51-
// SAFETY: this is slice of bool
52-
unsafe {
53-
let ptr = self.as_mut_ptr();
54-
let len = self.len();
55-
write_bytes(ptr, value as u8, len);
21+
fn spec_fill(&mut self, value: T) {
22+
if size_of::<T>() == 1 {
23+
// SAFETY: The size_of check above ensures that values are 1 byte wide, as required
24+
// for the transmute and write_bytes
25+
unsafe {
26+
let value: u8 = transmute_copy(&value);
27+
write_bytes(self.as_mut_ptr(), value, self.len());
28+
}
29+
} else {
30+
for item in self.iter_mut() {
31+
*item = value;
32+
}
5633
}
5734
}
5835
}

0 commit comments

Comments
 (0)