Skip to content

Commit 68513cb

Browse files
committed
Use MaybeUninit
1 parent 9a6e8b3 commit 68513cb

File tree

7 files changed

+47
-18
lines changed

7 files changed

+47
-18
lines changed

compiler/rustc_query_system/src/dep_graph/serialized.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,8 @@ impl NodeInfo {
454454

455455
let bytes_per_index = header.bytes_per_index();
456456
for node_index in edges.iter() {
457-
e.write_with(|dest| {
458-
*dest = node_index.as_u32().to_le_bytes();
457+
e.write_with::<4>(|dest| {
458+
dest.write_copy_of_slice(&node_index.as_u32().to_le_bytes());
459459
bytes_per_index
460460
});
461461
}
@@ -492,8 +492,8 @@ impl NodeInfo {
492492
let bytes_per_index = header.bytes_per_index();
493493
for node_index in edges {
494494
let node_index = colors.current(node_index).unwrap();
495-
e.write_with(|dest| {
496-
*dest = node_index.as_u32().to_le_bytes();
495+
e.write_with::<4>(|dest| {
496+
dest.write_copy_of_slice(&node_index.as_u32().to_le_bytes());
497497
bytes_per_index
498498
});
499499
}

compiler/rustc_query_system/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(core_intrinsics)]
55
#![feature(dropck_eyepatch)]
66
#![feature(let_chains)]
7+
#![feature(maybe_uninit_write_slice)]
78
#![feature(min_specialization)]
89
// tidy-alphabetical-end
910

compiler/rustc_serialize/src/leb128.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// This code is very hot and uses lots of arithmetic, avoid overflow checks for performance.
22
// See https://github.com/rust-lang/rust/pull/119440#issuecomment-1874255727
3+
use std::mem::MaybeUninit;
4+
35
use crate::int_overflow::DebugStrictAdd;
46
use crate::opaque::MemDecoder;
57
use crate::serialize::Decoder;
@@ -18,20 +20,23 @@ pub const fn largest_max_leb128_len() -> usize {
1820
macro_rules! impl_write_unsigned_leb128 {
1921
($fn_name:ident, $int_ty:ty) => {
2022
#[inline]
21-
pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
23+
pub fn $fn_name(
24+
out: &mut [MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
25+
mut value: $int_ty,
26+
) -> usize {
2227
let mut i = 0;
2328

2429
loop {
2530
if value < 0x80 {
2631
unsafe {
27-
*out.get_unchecked_mut(i) = value as u8;
32+
out.get_unchecked_mut(i).write(value as u8);
2833
}
2934

3035
i = i.debug_strict_add(1);
3136
break;
3237
} else {
3338
unsafe {
34-
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
39+
out.get_unchecked_mut(i).write(((value & 0x7f) | 0x80) as u8);
3540
}
3641

3742
value >>= 7;
@@ -87,7 +92,10 @@ impl_read_unsigned_leb128!(read_usize_leb128, usize);
8792
macro_rules! impl_write_signed_leb128 {
8893
($fn_name:ident, $int_ty:ty) => {
8994
#[inline]
90-
pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
95+
pub fn $fn_name(
96+
out: &mut [MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
97+
mut value: $int_ty,
98+
) -> usize {
9199
let mut i = 0;
92100

93101
loop {
@@ -101,7 +109,7 @@ macro_rules! impl_write_signed_leb128 {
101109
}
102110

103111
unsafe {
104-
*out.get_unchecked_mut(i) = byte;
112+
out.get_unchecked_mut(i).write(byte);
105113
}
106114

107115
i = i.debug_strict_add(1);

compiler/rustc_serialize/src/leb128/tests.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::mem::MaybeUninit;
2+
13
use super::*;
24
use crate::Decoder;
35
use crate::opaque::{MAGIC_END_BYTES, MemDecoder};
@@ -21,10 +23,10 @@ macro_rules! impl_test_unsigned_leb128 {
2123

2224
let mut stream = Vec::new();
2325

24-
let mut buf = Default::default();
26+
let mut buf = [const { MaybeUninit::<u8>::uninit() }; max_leb128_len::<$int_ty>()];
2527
for &x in &values {
2628
let n = $write_fn_name(&mut buf, x);
27-
stream.extend(&buf[..n]);
29+
stream.extend(unsafe { buf[..n].assume_init_ref() });
2830
}
2931
let stream_end = stream.len();
3032
stream.extend(MAGIC_END_BYTES);
@@ -70,10 +72,10 @@ macro_rules! impl_test_signed_leb128 {
7072

7173
let mut stream = Vec::new();
7274

73-
let mut buf = Default::default();
75+
let mut buf = [const { MaybeUninit::<u8>::uninit() }; max_leb128_len::<$int_ty>()];
7476
for &x in &values {
7577
let n = $write_fn_name(&mut buf, x);
76-
stream.extend(&buf[..n]);
78+
stream.extend(unsafe { buf[..n].assume_init_ref() });
7779
}
7880
let stream_end = stream.len();
7981
stream.extend(MAGIC_END_BYTES);

compiler/rustc_serialize/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
)]
1212
#![doc(rust_logo)]
1313
#![feature(core_intrinsics)]
14+
#![feature(maybe_uninit_slice)]
15+
#![feature(maybe_uninit_write_slice)]
1416
#![feature(min_specialization)]
1517
#![feature(never_type)]
1618
#![feature(rustdoc_internals)]

compiler/rustc_serialize/src/opaque.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fs::File;
22
use std::io::{self, Write};
33
use std::marker::PhantomData;
4+
use std::mem::{MaybeUninit, transmute};
45
use std::ops::Range;
56
use std::path::{Path, PathBuf};
67

@@ -168,6 +169,15 @@ impl FileEncoder {
168169
self.buffered = self.buffered.debug_strict_add(written);
169170
}
170171

172+
/// This is a variant of `write_with` which gives out a `MaybeUninit` slice.
173+
#[inline]
174+
fn write_with_uninit<const N: usize>(
175+
&mut self,
176+
visitor: impl FnOnce(&mut [MaybeUninit<u8>; N]) -> usize,
177+
) {
178+
self.write_with(|buf: &mut [u8; N]| visitor(unsafe { transmute(buf) }))
179+
}
180+
171181
#[cold]
172182
#[inline(never)]
173183
fn panic_invalid_write<const N: usize>(written: usize) {
@@ -210,7 +220,7 @@ macro_rules! write_leb128 {
210220
($this_fn:ident, $int_ty:ty, $write_leb_fn:ident) => {
211221
#[inline]
212222
fn $this_fn(&mut self, v: $int_ty) {
213-
self.write_with(|buf| leb128::$write_leb_fn(buf, v))
223+
self.write_with_uninit(|buf| leb128::$write_leb_fn(buf, v))
214224
}
215225
};
216226
}

compiler/rustc_serialize/src/opaque/mem_encoder.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::mem::MaybeUninit;
2+
13
use super::IntEncodedWithFixedSize;
24
use crate::{Encodable, Encoder, leb128};
35

@@ -31,12 +33,16 @@ impl MemEncoder {
3133
/// architectures support fixed-size writes up to 8 bytes with one instruction, so while this
3234
/// does in some sense do wasted work, we come out ahead.
3335
#[inline]
34-
pub fn write_with<const N: usize>(&mut self, visitor: impl FnOnce(&mut [u8; N]) -> usize) {
36+
pub fn write_with<const N: usize>(
37+
&mut self,
38+
visitor: impl FnOnce(&mut [MaybeUninit<u8>; N]) -> usize,
39+
) {
3540
self.data.reserve(N);
3641

3742
let old_len = self.data.len();
3843
// SAFETY: fix
39-
let buf = unsafe { &mut *(self.data.as_mut_ptr().add(old_len) as *mut [u8; N]) };
44+
let buf =
45+
unsafe { &mut *(self.data.as_mut_ptr().add(old_len) as *mut [MaybeUninit<u8>; N]) };
4046
let written = visitor(buf);
4147
if written > N {
4248
Self::panic_invalid_write::<N>(written);
@@ -53,8 +59,8 @@ impl MemEncoder {
5359
/// Helper for calls where [`MemEncoder::write_with`] always writes the whole array.
5460
#[inline]
5561
pub fn write_array<const N: usize>(&mut self, buf: [u8; N]) {
56-
self.write_with(|dest| {
57-
*dest = buf;
62+
self.write_with::<N>(|dest| {
63+
dest.write_copy_of_slice(&buf);
5864
N
5965
})
6066
}

0 commit comments

Comments
 (0)