Store value/side-effect index lists inside CacheEncoder

These lists can be considered part of the encoder state, and bundling them
inside the encoder is certainly more convenient than passing them around
separately.
This commit is contained in:
Zalathar
2026-03-22 18:37:59 +11:00
parent 6f22f61305
commit de15ab0065
6 changed files with 64 additions and 70 deletions
-1
View File
@@ -4573,7 +4573,6 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
@@ -72,6 +72,15 @@
pub struct SerializedDepNodeIndex {}
}
impl SerializedDepNodeIndex {
/// Converts a current-session dep node index to a "serialized" index,
/// for the purpose of serializing data to be loaded by future sessions.
#[inline(always)]
pub fn from_curr_for_serialization(index: DepNodeIndex) -> Self {
SerializedDepNodeIndex::from_u32(index.as_u32())
}
}
const DEP_NODE_SIZE: usize = size_of::<SerializedDepNodeIndex>();
/// Amount of padding we need to add to the edge list data so that we can retrieve every
/// SerializedDepNodeIndex with a fixed-size read then mask.
+3 -5
View File
@@ -9,7 +9,7 @@
use rustc_span::{ExpnHash, ExpnId};
use crate::mir;
use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex};
use crate::query::on_disk_cache::CacheEncoder;
use crate::ty::{Ty, TyCtxt};
macro_rules! declare_hooks {
@@ -111,10 +111,8 @@ fn clone(&self) -> Self { *self }
/// Creates the MIR for a given `DefId`, including unreachable code.
hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>;
hook encode_query_values(
encoder: &mut CacheEncoder<'_, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex
) -> ();
/// Serializes all eligible query return values into the on-disk cache.
hook encode_query_values(encoder: &mut CacheEncoder<'_, 'tcx>) -> ();
}
#[cold]
@@ -9,7 +9,7 @@
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
use rustc_hir::definitions::DefPathHash;
use rustc_index::{Idx, IndexVec};
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -62,13 +62,13 @@ pub struct OnDiskCache {
// Caches that are populated lazily during decoding.
file_index_to_file: Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
// A map from dep-node to the position of the cached query result in
// `serialized_data`.
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
/// For query dep nodes that have a disk-cached return value, maps the node
/// index to the position of its serialized value in `serialized_data`.
query_values_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
// A map from dep-node to the position of any associated `QuerySideEffect` in
// `serialized_data`.
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
/// For `DepKind::SideEffect` dep nodes, maps the node index to the position
/// of its serialized [`QuerySideEffect`] in `serialized_data`.
side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
alloc_decoding_state: AllocDecodingState,
@@ -101,8 +101,8 @@ pub struct OnDiskCache {
#[derive(Encodable, Decodable)]
struct Footer {
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
query_result_index: EncodedDepNodeIndex,
side_effects_index: EncodedDepNodeIndex,
query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
// The location of all allocations.
// Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64
// without measurable overhead. This permits larger const allocations without ICEing.
@@ -114,8 +114,6 @@ struct Footer {
foreign_expn_data: UnhashMap<ExpnHash, u32>,
}
pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
struct SourceFileIndex(u32);
@@ -175,8 +173,8 @@ pub fn new(sess: &Session, data: Mmap, start_pos: usize) -> Result<Self, ()> {
file_index_to_stable_id: footer.file_index_to_stable_id,
file_index_to_file: Default::default(),
current_side_effects: Default::default(),
query_result_index: footer.query_result_index.into_iter().collect(),
prev_side_effects_index: footer.side_effects_index.into_iter().collect(),
query_values_index: footer.query_values_index.into_iter().collect(),
side_effects_index: footer.side_effects_index.into_iter().collect(),
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
syntax_contexts: footer.syntax_contexts,
expn_data: footer.expn_data,
@@ -191,8 +189,8 @@ pub fn new_empty() -> Self {
file_index_to_stable_id: Default::default(),
file_index_to_file: Default::default(),
current_side_effects: Default::default(),
query_result_index: Default::default(),
prev_side_effects_index: Default::default(),
query_values_index: Default::default(),
side_effects_index: Default::default(),
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
syntax_contexts: FxHashMap::default(),
expn_data: UnhashMap::default(),
@@ -241,30 +239,19 @@ pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResu
file_to_file_index,
hygiene_context: &hygiene_encode_context,
symbol_index_table: Default::default(),
query_values_index: Default::default(),
side_effects_index: Default::default(),
};
// Encode query results.
let mut query_result_index = EncodedDepNodeIndex::new();
// Encode query return values.
tcx.sess.time("encode_query_values", || {
let enc = &mut encoder;
let qri = &mut query_result_index;
tcx.encode_query_values(enc, qri);
tcx.encode_query_values(&mut encoder);
});
// Encode side effects.
let side_effects_index: EncodedDepNodeIndex = self
.current_side_effects
.borrow()
.iter()
.map(|(dep_node_index, side_effect)| {
let pos = AbsoluteBytePos::new(encoder.position());
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
encoder.encode_tagged(dep_node_index, side_effect);
(dep_node_index, pos)
})
.collect();
for (&dep_node_index, side_effect) in self.current_side_effects.borrow().iter() {
encoder.encode_side_effect(dep_node_index, side_effect);
}
let interpret_alloc_index = {
let mut interpret_alloc_index = Vec::new();
@@ -315,11 +302,13 @@ pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResu
// Encode the file footer.
let footer_pos = encoder.position() as u64;
let query_values_index = mem::take(&mut encoder.query_values_index);
let side_effects_index = mem::take(&mut encoder.side_effects_index);
encoder.encode_tagged(
TAG_FILE_FOOTER,
&Footer {
file_index_to_stable_id,
query_result_index,
query_values_index,
side_effects_index,
interpret_alloc_index,
syntax_contexts,
@@ -346,7 +335,7 @@ pub fn load_side_effect(
dep_node_index: SerializedDepNodeIndex,
) -> Option<QuerySideEffect> {
let side_effect: Option<QuerySideEffect> =
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
self.load_indexed(tcx, dep_node_index, &self.side_effects_index);
side_effect
}
@@ -359,16 +348,15 @@ pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: Query
debug_assert!(prev.is_none());
}
/// Return whether the cached query result can be decoded.
/// Returns true if there is a disk-cached query return value for the given node.
#[inline]
pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool {
self.query_result_index.contains_key(&dep_node_index)
self.query_values_index.contains_key(&dep_node_index)
// with_decoder is infallible, so we can stop here
}
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
/// Returns the disk-cached query return value for the given node, if there is one.
pub fn try_load_query_value<'tcx, T>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
@@ -376,7 +364,7 @@ pub fn try_load_query_result<'tcx, T>(
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index);
let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_values_index);
debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index));
opt_value
}
@@ -815,6 +803,9 @@ pub struct CacheEncoder<'a, 'tcx> {
hygiene_context: &'a HygieneEncodeContext,
// Used for both `Symbol`s and `ByteSymbol`s.
symbol_index_table: FxHashMap<u32, usize>,
query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
}
impl<'a, 'tcx> fmt::Debug for CacheEncoder<'a, 'tcx> {
@@ -835,7 +826,7 @@ fn source_file_index(&mut self, source_file: Arc<SourceFile>) -> SourceFileIndex
/// encode the specified tag, then the given value, then the number of
/// bytes taken up by tag and value. On decoding, we can then verify that
/// we get the expected tag and read the expected number of bytes.
pub fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
let start_pos = self.position();
tag.encode(self);
@@ -845,6 +836,20 @@ pub fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T,
((end_pos - start_pos) as u64).encode(self);
}
pub fn encode_query_value<V: Encodable<Self>>(&mut self, index: DepNodeIndex, value: &V) {
let index = SerializedDepNodeIndex::from_curr_for_serialization(index);
self.query_values_index.push((index, AbsoluteBytePos::new(self.position())));
self.encode_tagged(index, value);
}
fn encode_side_effect(&mut self, index: DepNodeIndex, side_effect: &QuerySideEffect) {
let index = SerializedDepNodeIndex::from_curr_for_serialization(index);
self.side_effects_index.push((index, AbsoluteBytePos::new(self.position())));
self.encode_tagged(index, side_effect);
}
// copy&paste impl from rustc_metadata
fn encode_symbol_or_byte_symbol(
&mut self,
-1
View File
@@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_serialize = { path = "../rustc_serialize" }
+5 -21
View File
@@ -2,18 +2,14 @@
use rustc_data_structures::unord::UnordMap;
use rustc_hir::limit::Limit;
use rustc_index::Idx;
use rustc_middle::bug;
#[expect(unused_imports, reason = "used by doc comments")]
use rustc_middle::dep_graph::DepKindVTable;
use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, DepNodeKey, SerializedDepNodeIndex};
use rustc_middle::query::erase::{Erasable, Erased};
use rustc_middle::query::on_disk_cache::{
AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
};
use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder};
use rustc_middle::query::{QueryCache, QueryJobId, QueryMode, QueryVTable, erase};
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::DUMMY_SP;
@@ -79,13 +75,9 @@ pub(crate) fn start_query<R>(
})
}
pub(crate) fn encode_query_values<'tcx>(
tcx: TyCtxt<'tcx>,
encoder: &mut CacheEncoder<'_, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex,
) {
pub(crate) fn encode_query_values<'tcx>(tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>) {
for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| {
encode_query_values_inner(tcx, query, encoder, query_result_index)
encode_query_values_inner(tcx, query, encoder)
});
}
@@ -93,7 +85,6 @@ fn encode_query_values_inner<'a, 'tcx, C, V>(
tcx: TyCtxt<'tcx>,
query: &'tcx QueryVTable<'tcx, C>,
encoder: &mut CacheEncoder<'a, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex,
) where
C: QueryCache<Value = Erased<V>>,
V: Erasable + Encodable<CacheEncoder<'a, 'tcx>>,
@@ -103,14 +94,7 @@ fn encode_query_values_inner<'a, 'tcx, C, V>(
assert!(all_inactive(&query.state));
query.cache.for_each(&mut |key, value, dep_node| {
if (query.will_cache_on_disk_for_key_fn)(tcx, *key) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
// Record position of the cache entry.
query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
// Encode the type check tables with the `SerializedDepNodeIndex`
// as tag.
encoder.encode_tagged(dep_node, &erase::restore_val::<V>(*value));
encoder.encode_query_value::<V>(dep_node, &erase::restore_val::<V>(*value));
}
});
}
@@ -214,7 +198,7 @@ pub(crate) fn try_load_from_disk<'tcx, V>(
// details.
let value = tcx
.dep_graph
.with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
.with_query_deserialization(|| on_disk_cache.try_load_query_value(tcx, prev_index));
prof_timer.finish_with_query_invocation_id(index.into());