Skip to content

Commit 4e5405f

Browse files
checkpointing
The new calls to `hash` need to be `hash_stable`, but I think the new encoding implementation is fine.
1 parent e6b64a2 commit 4e5405f

3 files changed

Lines changed: 124 additions & 69 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4288,6 +4288,7 @@ dependencies = [
42884288
"rustc_macros",
42894289
"rustc_middle",
42904290
"rustc_proc_macro",
4291+
"rustc_query_system",
42914292
"rustc_serialize",
42924293
"rustc_session",
42934294
"rustc_span",

compiler/rustc_metadata/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ rustc_middle = { path = "../rustc_middle" }
2525
# We must use the proc_macro version that we will compile proc-macros against,
2626
# not the one from our own sysroot.
2727
rustc_proc_macro = { path = "../rustc_proc_macro" }
28+
rustc_query_system = { path = "../rustc_query_system" }
2829
rustc_serialize = { path = "../rustc_serialize" }
2930
rustc_session = { path = "../rustc_session" }
3031
rustc_span = { path = "../rustc_span" }

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 122 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::sync::Arc;
77

88
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
99
use rustc_data_structures::memmap::{Mmap, MmapMut};
10-
use rustc_data_structures::sync::{par_for_each_in, par_join};
10+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
11+
use rustc_data_structures::sync::{join, par_for_each_in};
1112
use rustc_data_structures::temp_dir::MaybeTempDir;
1213
use rustc_data_structures::thousands::usize_with_underscores;
1314
use rustc_feature::Features;
@@ -26,6 +27,7 @@ use rustc_middle::ty::AssocContainer;
2627
use rustc_middle::ty::codec::TyEncoder;
2728
use rustc_middle::ty::fast_reject::{self, TreatParams};
2829
use rustc_middle::{bug, span_bug};
30+
use rustc_query_system::ich::StableHashingContext;
2931
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
3032
use rustc_session::config::{CrateType, OptLevel, TargetModifier};
3133
use rustc_span::hygiene::HygieneEncodeContext;
@@ -39,8 +41,14 @@ use crate::eii::EiiMapEncodedKeyValue;
3941
use crate::errors::{FailCreateFileEncoder, FailWriteFile};
4042
use crate::rmeta::*;
4143

42-
pub(super) struct EncodeContext<'a, 'tcx> {
44+
// Struct to enable split borrows.
45+
struct ContextEncoder<'a> {
4346
opaque: opaque::FileEncoder,
47+
stable_hasher: StableHasher,
48+
hcx: StableHashingContext<'a>,
49+
}
50+
51+
pub(super) struct EncodeContext<'a, 'tcx> {
4452
tcx: TyCtxt<'tcx>,
4553
feat: &'tcx rustc_feature::Features,
4654
tables: TableBuilders,
@@ -67,6 +75,8 @@ pub(super) struct EncodeContext<'a, 'tcx> {
6775
hygiene_ctxt: &'a HygieneEncodeContext,
6876
// Used for both `Symbol`s and `ByteSymbol`s.
6977
symbol_index_table: FxHashMap<u32, usize>,
78+
79+
encoder: ContextEncoder<'a>,
7080
}
7181

7282
/// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
@@ -80,14 +90,49 @@ macro_rules! empty_proc_macro {
8090
};
8191
}
8292

83-
macro_rules! encoder_methods {
93+
macro_rules! context_encoder_methods {
8494
($($name:ident($ty:ty);)*) => {
8595
$(fn $name(&mut self, value: $ty) {
96+
value.hash_stable(&mut self.hcx, &mut self.stable_hasher);
8697
self.opaque.$name(value)
8798
})*
8899
}
89100
}
90101

102+
impl<'a> Encoder for ContextEncoder<'a> {
103+
context_encoder_methods! {
104+
emit_usize(usize);
105+
emit_u128(u128);
106+
emit_u64(u64);
107+
emit_u32(u32);
108+
emit_u16(u16);
109+
emit_u8(u8);
110+
111+
emit_isize(isize);
112+
emit_i128(i128);
113+
emit_i64(i64);
114+
emit_i32(i32);
115+
emit_i16(i16);
116+
117+
emit_raw_bytes(&[u8]);
118+
}
119+
}
120+
121+
impl<'a> ContextEncoder<'a> {
122+
#[inline]
123+
fn position(&self) -> usize {
124+
self.opaque.position()
125+
}
126+
}
127+
128+
macro_rules! encoder_methods {
129+
($($name:ident($ty:ty);)*) => {
130+
$(fn $name(&mut self, value: $ty) {
131+
self.encoder.$name(value)
132+
})*
133+
}
134+
}
135+
91136
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
92137
encoder_methods! {
93138
emit_usize(usize);
@@ -149,6 +194,11 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
149194
}
150195

151196
fn encode_def_id(&mut self, def_id: DefId) {
197+
HashStable::<StableHashingContext<'_>>::hash_stable(
198+
&def_id,
199+
&mut self.encoder.hcx,
200+
&mut self.encoder.stable_hasher,
201+
);
152202
def_id.krate.encode(self);
153203
def_id.index.encode(self);
154204
}
@@ -177,25 +227,25 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
177227
let last_location = *o.get();
178228
// This cannot underflow. Metadata is written with increasing position(), so any
179229
// previously saved offset must be smaller than the current position.
180-
let offset = self.opaque.position() - last_location;
230+
let offset = self.encoder.position() - last_location;
181231
if offset < last_location {
182232
let needed = bytes_needed(offset);
183233
SpanTag::indirect(true, needed as u8).encode(self);
184-
self.opaque.write_with(|dest| {
234+
self.encoder.opaque.write_with(|dest| {
185235
*dest = offset.to_le_bytes();
186236
needed
187237
});
188238
} else {
189239
let needed = bytes_needed(last_location);
190240
SpanTag::indirect(false, needed as u8).encode(self);
191-
self.opaque.write_with(|dest| {
241+
self.encoder.opaque.write_with(|dest| {
192242
*dest = last_location.to_le_bytes();
193243
needed
194244
});
195245
}
196246
}
197247
Entry::Vacant(v) => {
198-
let position = self.opaque.position();
248+
let position = self.encoder.position();
199249
v.insert(position);
200250
// Data is encoded with a SpanTag prefix (see below).
201251
span.data().encode(self);
@@ -372,7 +422,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
372422
const CLEAR_CROSS_CRATE: bool = true;
373423

374424
fn position(&self) -> usize {
375-
self.opaque.position()
425+
self.encoder.position()
376426
}
377427

378428
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
@@ -489,21 +539,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
489539
) {
490540
// if symbol/byte symbol is predefined, emit tag and symbol index
491541
if Symbol::is_predefined(index) {
492-
self.opaque.emit_u8(SYMBOL_PREDEFINED);
493-
self.opaque.emit_u32(index);
542+
self.encoder.emit_u8(SYMBOL_PREDEFINED);
543+
self.encoder.emit_u32(index);
494544
} else {
495545
// otherwise write it as string or as offset to it
496546
match self.symbol_index_table.entry(index) {
497547
Entry::Vacant(o) => {
498-
self.opaque.emit_u8(SYMBOL_STR);
499-
let pos = self.opaque.position();
548+
self.encoder.emit_u8(SYMBOL_STR);
549+
let pos = self.encoder.position();
500550
o.insert(pos);
501551
emit_str_or_byte_str(self);
502552
}
503553
Entry::Occupied(o) => {
504554
let x = *o.get();
505-
self.emit_u8(SYMBOL_OFFSET);
506-
self.emit_usize(x);
555+
self.encoder.emit_u8(SYMBOL_OFFSET);
556+
self.encoder.emit_usize(x);
507557
}
508558
}
509559
}
@@ -598,7 +648,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
598648
adapted.set_some(on_disk_index, self.lazy(adapted_source_file));
599649
}
600650

601-
adapted.encode(&mut self.opaque)
651+
adapted.encode(&mut self.encoder.opaque)
602652
}
603653

604654
fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
@@ -682,7 +732,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
682732
// encode_def_path_table.
683733
let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
684734

685-
let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
735+
let tables = stat!("tables", || self.tables.encode(&mut self.encoder.opaque));
686736

687737
let debugger_visualizers =
688738
stat!("debugger-visualizers", || self.encode_debugger_visualizers());
@@ -783,19 +833,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
783833
if tcx.sess.opts.unstable_opts.meta_stats {
784834
use std::fmt::Write;
785835

786-
self.opaque.flush();
836+
let opaque = &mut self.encoder.opaque;
837+
opaque.flush();
787838

788839
// Rewind and re-read all the metadata to count the zero bytes we wrote.
789-
let pos_before_rewind = self.opaque.file().stream_position().unwrap();
840+
let pos_before_rewind = opaque.file().stream_position().unwrap();
790841
let mut zero_bytes = 0;
791-
self.opaque.file().rewind().unwrap();
792-
let file = std::io::BufReader::new(self.opaque.file());
842+
opaque.file().rewind().unwrap();
843+
let file = std::io::BufReader::new(opaque.file());
793844
for e in file.bytes() {
794845
if e.unwrap() == 0 {
795846
zero_bytes += 1;
796847
}
797848
}
798-
assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
849+
assert_eq!(opaque.file().stream_position().unwrap(), pos_before_rewind);
799850

800851
stats.sort_by_key(|&(_, usize)| usize);
801852
stats.reverse(); // bigger items first
@@ -1967,9 +2018,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19672018
);
19682019

19692020
(
1970-
syntax_contexts.encode(&mut self.opaque),
1971-
expn_data_table.encode(&mut self.opaque),
1972-
expn_hash_table.encode(&mut self.opaque),
2021+
syntax_contexts.encode(&mut self.encoder.opaque),
2022+
expn_data_table.encode(&mut self.encoder.opaque),
2023+
expn_hash_table.encode(&mut self.encoder.opaque),
19732024
)
19742025
}
19752026

@@ -2482,12 +2533,12 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
24822533
let root = ecx.encode_crate_root();
24832534

24842535
// Flush buffer to ensure backing file has the correct size.
2485-
ecx.opaque.flush();
2536+
ecx.encoder.opaque.flush();
24862537
// Record metadata size for self-profiling
24872538
tcx.prof.artifact_size(
24882539
"crate_metadata",
24892540
"crate_metadata",
2490-
ecx.opaque.file().metadata().unwrap().len(),
2541+
ecx.encoder.opaque.file().metadata().unwrap().len(),
24912542
);
24922543

24932544
root.position.get()
@@ -2502,53 +2553,55 @@ fn with_encode_metadata_header(
25022553
path: &Path,
25032554
f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize,
25042555
) {
2505-
let mut encoder = opaque::FileEncoder::new(path)
2506-
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
2507-
encoder.emit_raw_bytes(METADATA_HEADER);
2508-
2509-
// Will be filled with the root position after encoding everything.
2510-
encoder.emit_raw_bytes(&0u64.to_le_bytes());
2511-
2512-
let source_map_files = tcx.sess.source_map().files();
2513-
let source_file_cache = (Arc::clone(&source_map_files[0]), 0);
2514-
let required_source_files = Some(FxIndexSet::default());
2515-
drop(source_map_files);
2516-
2517-
let hygiene_ctxt = HygieneEncodeContext::default();
2518-
2519-
let mut ecx = EncodeContext {
2520-
opaque: encoder,
2521-
tcx,
2522-
feat: tcx.features(),
2523-
tables: Default::default(),
2524-
lazy_state: LazyState::NoNode,
2525-
span_shorthands: Default::default(),
2526-
type_shorthands: Default::default(),
2527-
predicate_shorthands: Default::default(),
2528-
source_file_cache,
2529-
interpret_allocs: Default::default(),
2530-
required_source_files,
2531-
is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
2532-
hygiene_ctxt: &hygiene_ctxt,
2533-
symbol_index_table: Default::default(),
2534-
};
2556+
tcx.with_stable_hashing_context(|hcx| {
2557+
let mut encoder = opaque::FileEncoder::new(path)
2558+
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
2559+
encoder.emit_raw_bytes(METADATA_HEADER);
2560+
2561+
// Will be filled with the root position after encoding everything.
2562+
encoder.emit_raw_bytes(&0u64.to_le_bytes());
2563+
2564+
let source_map_files = tcx.sess.source_map().files();
2565+
let source_file_cache = (Arc::clone(&source_map_files[0]), 0);
2566+
let required_source_files = Some(FxIndexSet::default());
2567+
drop(source_map_files);
2568+
2569+
let hygiene_ctxt = HygieneEncodeContext::default();
2570+
2571+
let mut ecx = EncodeContext {
2572+
tcx,
2573+
feat: tcx.features(),
2574+
tables: Default::default(),
2575+
lazy_state: LazyState::NoNode,
2576+
span_shorthands: Default::default(),
2577+
type_shorthands: Default::default(),
2578+
predicate_shorthands: Default::default(),
2579+
source_file_cache,
2580+
interpret_allocs: Default::default(),
2581+
required_source_files,
2582+
is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
2583+
hygiene_ctxt: &hygiene_ctxt,
2584+
symbol_index_table: Default::default(),
2585+
encoder: ContextEncoder { opaque: encoder, stable_hasher: StableHasher::new(), hcx },
2586+
};
25352587

2536-
// Encode the rustc version string in a predictable location.
2537-
rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
2588+
// Encode the rustc version string in a predictable location.
2589+
rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
25382590

2539-
let root_position = f(&mut ecx);
2591+
let root_position = f(&mut ecx);
25402592

2541-
// Make sure we report any errors from writing to the file.
2542-
// If we forget this, compilation can succeed with an incomplete rmeta file,
2543-
// causing an ICE when the rmeta file is read by another compilation.
2544-
if let Err((path, err)) = ecx.opaque.finish() {
2545-
tcx.dcx().emit_fatal(FailWriteFile { path: &path, err });
2546-
}
2593+
// Make sure we report any errors from writing to the file.
2594+
// If we forget this, compilation can succeed with an incomplete rmeta file,
2595+
// causing an ICE when the rmeta file is read by another compilation.
2596+
if let Err((path, err)) = ecx.encoder.opaque.finish() {
2597+
tcx.dcx().emit_fatal(FailWriteFile { path: &path, err });
2598+
}
25472599

2548-
let file = ecx.opaque.file();
2549-
if let Err(err) = encode_root_position(file, root_position) {
2550-
tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err });
2551-
}
2600+
let file = ecx.encoder.opaque.file();
2601+
if let Err(err) = encode_root_position(file, root_position) {
2602+
tcx.dcx().emit_fatal(FailWriteFile { path: ecx.encoder.opaque.path(), err });
2603+
}
2604+
})
25522605
}
25532606

25542607
fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {

0 commit comments

Comments
 (0)