Skip to content

Commit d5bd169

Browse files
committed
Add my encoding debugging rig
1 parent eaff1af commit d5bd169

File tree

5 files changed

+74
-9
lines changed

5 files changed

+74
-9
lines changed

compiler/rustc_query_system/src/dep_graph/edges.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Deref for EdgesVec {
4141

4242
#[inline]
4343
fn deref(&self) -> &Self::Target {
44-
self.edges.as_slice()
44+
&*self.edges
4545
}
4646
}
4747

compiler/rustc_query_system/src/dep_graph/serialized.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,30 @@ impl NodeInfo {
397397
if header.len().is_none() {
398398
e.emit_usize(self.edges.len());
399399
}
400-
401400
let bytes_per_index = header.bytes_per_index();
402-
for node_index in self.edges.iter() {
403-
e.write_with(|dest| {
404-
*dest = node_index.as_u32().to_le_bytes();
405-
bytes_per_index
401+
let mut edges = &*self.edges;
402+
loop {
403+
e.write_with_spare(|dest| {
404+
if dest.len() < 4 {
405+
return 0;
406+
}
407+
let usable_len = dest.len() - 4;
408+
let (edges_to_encode, remaining) =
409+
edges.split_at((usable_len / bytes_per_index).min(edges.len()));
410+
for (i, node_index) in edges_to_encode.iter().enumerate() {
411+
let start = i * bytes_per_index;
412+
let d: &mut [u8; 4] =
413+
unsafe { dest.get_unchecked_mut(start..start + 4).try_into().unwrap() };
414+
*d = node_index.as_u32().to_le_bytes();
415+
}
416+
edges = remaining;
417+
edges_to_encode.len() * bytes_per_index
406418
});
419+
420+
if edges.is_empty() {
421+
break;
422+
}
423+
e.flush();
407424
}
408425
}
409426
}

compiler/rustc_query_system/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(hash_raw_entry)]
44
#![feature(min_specialization)]
55
#![feature(let_chains)]
6+
#![feature(array_windows)]
67
#![allow(rustc::potential_query_instability, internal_features)]
78

89
#[macro_use]

compiler/rustc_serialize/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![feature(min_specialization)]
1616
#![feature(never_type)]
1717
#![feature(ptr_sub_ptr)]
18+
#![feature(let_chains)]
1819
#![cfg_attr(test, feature(test))]
1920
#![allow(rustc::internal)]
2021

compiler/rustc_serialize/src/opaque.rs

+49-3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub struct FileEncoder {
3838
path: PathBuf,
3939
#[cfg(debug_assertions)]
4040
finished: bool,
41+
panic_at_offset: Option<usize>,
42+
flush_every_write: bool,
4143
}
4244

4345
impl FileEncoder {
@@ -48,6 +50,9 @@ impl FileEncoder {
4850
let file =
4951
File::options().read(true).write(true).create(true).truncate(true).open(&path)?;
5052

53+
let panic_at_offset = std::env::var_os("RUSTC_FILE_ENCODER_PANIC_AT_OFFSET")
54+
.map(|v| v.to_str().unwrap().parse::<usize>().unwrap());
55+
5156
Ok(FileEncoder {
5257
buf: vec![0u8; BUF_SIZE].into_boxed_slice().try_into().unwrap(),
5358
path: path.as_ref().into(),
@@ -57,6 +62,8 @@ impl FileEncoder {
5762
res: Ok(()),
5863
#[cfg(debug_assertions)]
5964
finished: false,
65+
panic_at_offset,
66+
flush_every_write: panic_at_offset.is_some_and(|v| v <= BUF_SIZE),
6067
})
6168
}
6269

@@ -75,6 +82,19 @@ impl FileEncoder {
7582
{
7683
self.finished = false;
7784
}
85+
86+
if let Some(panic_offset) = self.panic_at_offset {
87+
// If we are within the buffer size of the offset we're to panic at, we need to start
88+
// flushing every write so that we don't panic late.
89+
if panic_offset - self.flushed <= BUF_SIZE {
90+
self.flush_every_write = true;
91+
}
92+
// If the offset we want to panic at is in the range we're about to write, panic.
93+
if (self.flushed..self.flushed + self.buffered).contains(&panic_offset) {
94+
panic!()
95+
}
96+
}
97+
7898
if self.res.is_ok() {
7999
self.res = self.file.write_all(&self.buf[..self.buffered]);
80100
}
@@ -107,6 +127,12 @@ impl FileEncoder {
107127
if self.res.is_ok() {
108128
self.res = self.file.write_all(buf);
109129
}
130+
// This write bypasses the buffer, so we need to duplicate the check logic here
131+
if let Some(panic_offset) = self.panic_at_offset {
132+
if (self.flushed..self.flushed + buf.len()).contains(&panic_offset) {
133+
panic!()
134+
}
135+
}
110136
self.flushed += buf.len();
111137
}
112138
}
@@ -117,7 +143,9 @@ impl FileEncoder {
117143
{
118144
self.finished = false;
119145
}
120-
if let Some(dest) = self.buffer_empty().get_mut(..buf.len()) {
146+
if !self.flush_every_write
147+
&& let Some(dest) = self.buffer_empty().get_mut(..buf.len())
148+
{
121149
dest.copy_from_slice(buf);
122150
self.buffered += buf.len();
123151
} else {
@@ -146,21 +174,39 @@ impl FileEncoder {
146174
self.finished = false;
147175
}
148176
let flush_threshold = const { BUF_SIZE.checked_sub(N).unwrap() };
149-
if std::intrinsics::unlikely(self.buffered > flush_threshold) {
177+
if std::intrinsics::unlikely(self.flush_every_write || self.buffered > flush_threshold) {
150178
self.flush();
151179
}
152180
// SAFETY: We checked above that that N < self.buffer_empty().len(),
153181
// and if isn't, flush ensures that our empty buffer is now BUF_SIZE.
154182
// We produce a post-mono error if N > BUF_SIZE.
155183
let buf = unsafe { self.buffer_empty().first_chunk_mut::<N>().unwrap_unchecked() };
156184
let written = visitor(buf);
157-
// We have to ensure that an errant visitor cannot cause self.buffered to exeed BUF_SIZE.
185+
// We have to ensure that an errant visitor cannot cause self.buffered to exceed BUF_SIZE.
158186
if written > N {
159187
Self::panic_invalid_write::<N>(written);
160188
}
161189
self.buffered += written;
162190
}
163191

192+
#[inline]
193+
pub fn write_with_spare(&mut self, visitor: impl FnOnce(&mut [u8]) -> usize) {
194+
#[cold]
195+
#[inline(never)]
196+
fn panic_invalid_write_spare() {
197+
panic!(
198+
"FileEncoder::write_with_spare cannot be used to write more bytes than the current buffer size!"
199+
);
200+
}
201+
202+
let buf = self.buffer_empty();
203+
let written = visitor(buf);
204+
if written > buf.len() {
205+
panic_invalid_write_spare();
206+
}
207+
self.buffered += written;
208+
}
209+
164210
#[cold]
165211
#[inline(never)]
166212
fn panic_invalid_write<const N: usize>(written: usize) {

0 commit comments

Comments
 (0)