Skip to content

Commit 3223b0b

Browse files
committed
Auto merge of rust-lang#115542 - saethlin:fileencoder-is-bufwriter, r=WaffleLapkin
Simplify/Optimize FileEncoder FileEncoder is basically a BufWriter except that it exposes access to the not-written-to-yet region of the buffer so that some users can write directly to the buffer. This strategy is awesome because it lets us avoid calling memcpy for small copies, but the previous strategy was based on the writer accessing a `&mut [MaybeUninit<u8>; N]` and returning a `&[u8]` which is an API which currently mandates the use of unsafe code, making that interface in general not that appealing. So this PR cleans up the FileEncoder implementation and builds on that general idea of direct buffer access in order to prevent `memcpy` calls in a few key places when encoding the dep graph and rmeta tables. The interface used here is now 100% safe, but with the caveat that internally we need to avoid trusting the number of bytes that the provided function claims to have written. The original primary objective of this PR was to clean up the FileEncoder implementation so that the fix for the following issues would be easy to implement. The fix for these issues is to correctly update self.buffered even when writes fail, which I think it's easy to verify manually is now done, because all the FileEncoder methods are small. Fixes rust-lang#115298 Fixes rust-lang#114671 Fixes rust-lang#114045 Fixes rust-lang#108100 Fixes rust-lang#106787
2 parents ad36b5a + 6cee6b0 commit 3223b0b

File tree

7 files changed

+114
-214
lines changed

7 files changed

+114
-214
lines changed

compiler/rustc_metadata/src/rmeta/table.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_hir::def::{CtorKind, CtorOf};
55
use rustc_index::Idx;
66
use rustc_middle::ty::{ParameterizedOverTcx, UnusedGenericParams};
77
use rustc_serialize::opaque::FileEncoder;
8-
use rustc_serialize::Encoder as _;
98
use rustc_span::hygiene::MacroKind;
109
use std::marker::PhantomData;
1110
use std::num::NonZeroUsize;
@@ -468,7 +467,10 @@ impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBui
468467

469468
let width = self.width;
470469
for block in &self.blocks {
471-
buf.emit_raw_bytes(&block[..width]);
470+
buf.write_with(|dest| {
471+
*dest = *block;
472+
width
473+
});
472474
}
473475

474476
LazyTable::from_position_and_encoded_size(

compiler/rustc_query_system/src/dep_graph/serialized.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -404,16 +404,18 @@ struct NodeInfo<K: DepKind> {
404404
impl<K: DepKind> Encodable<FileEncoder> for NodeInfo<K> {
405405
fn encode(&self, e: &mut FileEncoder) {
406406
let header = SerializedNodeHeader::new(self);
407-
e.emit_raw_bytes(&header.bytes);
407+
e.write_array(header.bytes);
408408

409409
if header.len().is_none() {
410410
e.emit_usize(self.edges.len());
411411
}
412412

413413
let bytes_per_index = header.bytes_per_index();
414414
for node_index in self.edges.iter() {
415-
let bytes = node_index.as_u32().to_le_bytes();
416-
e.emit_raw_bytes(&bytes[..bytes_per_index]);
415+
e.write_with(|dest| {
416+
*dest = node_index.as_u32().to_le_bytes();
417+
bytes_per_index
418+
});
417419
}
418420
}
419421
}

compiler/rustc_serialize/src/leb128.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,28 @@ pub const fn largest_max_leb128_len() -> usize {
1515
macro_rules! impl_write_unsigned_leb128 {
1616
($fn_name:ident, $int_ty:ty) => {
1717
#[inline]
18-
pub fn $fn_name(
19-
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
20-
mut value: $int_ty,
21-
) -> &[u8] {
18+
pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
2219
let mut i = 0;
2320

2421
loop {
2522
if value < 0x80 {
2623
unsafe {
27-
*out.get_unchecked_mut(i).as_mut_ptr() = value as u8;
24+
*out.get_unchecked_mut(i) = value as u8;
2825
}
2926

3027
i += 1;
3128
break;
3229
} else {
3330
unsafe {
34-
*out.get_unchecked_mut(i).as_mut_ptr() = ((value & 0x7f) | 0x80) as u8;
31+
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
3532
}
3633

3734
value >>= 7;
3835
i += 1;
3936
}
4037
}
4138

42-
unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
39+
i
4340
}
4441
};
4542
}
@@ -87,10 +84,7 @@ impl_read_unsigned_leb128!(read_usize_leb128, usize);
8784
macro_rules! impl_write_signed_leb128 {
8885
($fn_name:ident, $int_ty:ty) => {
8986
#[inline]
90-
pub fn $fn_name(
91-
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
92-
mut value: $int_ty,
93-
) -> &[u8] {
87+
pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
9488
let mut i = 0;
9589

9690
loop {
@@ -104,7 +98,7 @@ macro_rules! impl_write_signed_leb128 {
10498
}
10599

106100
unsafe {
107-
*out.get_unchecked_mut(i).as_mut_ptr() = byte;
101+
*out.get_unchecked_mut(i) = byte;
108102
}
109103

110104
i += 1;
@@ -114,7 +108,7 @@ macro_rules! impl_write_signed_leb128 {
114108
}
115109
}
116110

117-
unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
111+
i
118112
}
119113
};
120114
}

compiler/rustc_serialize/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Core encoding and decoding interfaces.
1717
#![feature(new_uninit)]
1818
#![feature(allocator_api)]
1919
#![feature(ptr_sub_ptr)]
20+
#![feature(slice_first_last_chunk)]
21+
#![feature(inline_const)]
22+
#![feature(const_option)]
2023
#![cfg_attr(test, feature(test))]
2124
#![allow(rustc::internal)]
2225
#![deny(rustc::untranslatable_diagnostic)]

0 commit comments

Comments
 (0)