Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_incremental/src/persist/file_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::diagnostics;
const FILE_MAGIC: &[u8] = b"RSIC";

/// Change this if the header format changes.
const HEADER_FORMAT_VERSION: u16 = 0;
const HEADER_FORMAT_VERSION: u16 = 1;

pub(crate) fn write_file_header(stream: &mut FileEncoder<'_>, sess: &Session) {
stream.emit_raw_bytes(FILE_MAGIC);
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use rustc_data_structures::stable_hash::{StableHasher, StableOrd};
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathHash;
use rustc_macros::{Decodable, Encodable, StableHash};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::Symbol;

use super::{DepNodeIndex, KeyFingerprintStyle, SerializedDepNodeIndex};
Expand Down Expand Up @@ -152,6 +153,25 @@ impl fmt::Debug for DepNode {
}
}

// `DepKind` is encoded as its `u16` discriminant, which is only meaningful to
// the compiler build that assigned it, so anything containing an encoded
// `DepNode` must be discarded on version mismatch.
impl<E: Encoder> Encodable<E> for DepNode {
fn encode(&self, e: &mut E) {
e.emit_u16(self.kind.as_u16());
self.key_fingerprint.encode(e);
}
}

impl<D: Decoder> Decodable<D> for DepNode {
fn decode(d: &mut D) -> Self {
DepNode {
kind: DepKind::from_u16(d.read_u16()),
key_fingerprint: PackedFingerprint::decode(d),
}
}
}

/// This struct stores function pointers and other metadata for a particular DepKind.
///
/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
Expand Down
30 changes: 23 additions & 7 deletions compiler/rustc_middle/src/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_span::{
SourceFile, Span, SpanDecoder, SpanEncoder, Spanned, StableSourceFileId, Symbol,
};

use crate::dep_graph::{DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex};
use crate::dep_graph::{DepNode, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex};
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use crate::mir::{self, interpret};
use crate::mono::MonoItem;
Expand Down Expand Up @@ -330,8 +330,10 @@ impl OnDiskCache {
tcx: TyCtxt<'_>,
dep_node_index: SerializedDepNodeIndex,
) -> Option<QuerySideEffect> {
// Side-effect nodes are exempt from the `(kind, key_fingerprint)`
// uniqueness guarantee, so their values are tagged with the index.
let side_effect: Option<QuerySideEffect> =
self.load_indexed(tcx, dep_node_index, &self.side_effects_index);
self.load_indexed(tcx, dep_node_index, &self.side_effects_index, dep_node_index);
side_effect
}

Expand All @@ -347,24 +349,29 @@ impl OnDiskCache {
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
node: DepNode,
) -> Option<T>
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
self.load_indexed(tcx, dep_node_index, &self.query_values_index)
// See `encode_query_value` for why values are tagged with the node
// itself instead of its index.
self.load_indexed(tcx, dep_node_index, &self.query_values_index, node)
}

fn load_indexed<'tcx, T>(
fn load_indexed<'tcx, T, Tag>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
expected_tag: Tag,
) -> Option<T>
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
Tag: for<'a> Decodable<CacheDecoder<'a, 'tcx>> + Eq + fmt::Debug,
{
let pos = index.get(&dep_node_index).cloned()?;
let value = self.with_decoder(tcx, pos, |decoder| decode_tagged(decoder, dep_node_index));
let value = self.with_decoder(tcx, pos, |decoder| decode_tagged(decoder, expected_tag));
Some(value)
}

Expand Down Expand Up @@ -825,11 +832,20 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
((end_pos - start_pos) as u64).encode(self);
}

pub fn encode_query_value<V: Encodable<Self>>(&mut self, index: DepNodeIndex, value: &V) {
pub fn encode_query_value<V: Encodable<Self>>(
&mut self,
index: DepNodeIndex,
node: DepNode,
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);
// The tag lets the load path check that the bytes at this position
// belong to the node it asked for. Unlike the index the position is
// looked up by, the node identifies the value across sessions: indices
// are reassigned per session, `(kind, key_fingerprint)` is stable.
self.encode_tagged(node, value);
}

fn encode_side_effect(&mut self, index: DepNodeIndex, side_effect: &QuerySideEffect) {
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_errors::Diag;
use rustc_hir::def_id::LocalDefId;
use rustc_span::Span;

use crate::dep_graph::{DepKind, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex};
use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex};
use crate::ich::StableHashState;
use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
use crate::query::on_disk_cache::OnDiskCache;
Expand Down Expand Up @@ -93,8 +93,11 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
/// Function pointer that tries to load a query value from disk.
///
/// This should only be called after a successful check of [`Self::will_cache_on_disk_for_key`].
pub try_load_from_disk_fn:
fn(tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) -> Option<C::Value>,
pub try_load_from_disk_fn: fn(
tcx: TyCtxt<'tcx>,
prev_index: SerializedDepNodeIndex,
node: DepNode,
) -> Option<C::Value>,

/// Function pointer that hashes this query's result values.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
// First try to load the result from the on-disk cache. Some things are never cached on disk.
let try_value = if query.will_cache_on_disk_for_key(key) {
let prof_timer = tcx.prof.incr_cache_loading();
let value = (query.try_load_from_disk_fn)(tcx, prev_index);
let value = (query.try_load_from_disk_fn)(tcx, prev_index, *dep_node);
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
value
} else {
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ 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(*key) {
encoder.encode_query_value::<V>(dep_node, &erase::restore_val::<V>(*value));
let node = DepNode::construct(tcx, query.dep_kind, key);
encoder.encode_query_value::<V>(dep_node, node, &erase::restore_val::<V>(*value));
}
});
}
Expand Down Expand Up @@ -169,7 +170,8 @@ pub(crate) fn promote_from_disk_inner<'tcx, C: QueryCache>(
tcx.dep_graph.data().expect("should always be present in incremental mode");

let prof_timer = tcx.prof.incr_cache_loading();
let value = ensure_sufficient_stack(|| (query.try_load_from_disk_fn)(tcx, prev_index));
let value =
ensure_sufficient_stack(|| (query.try_load_from_disk_fn)(tcx, prev_index, dep_node));
prof_timer.finish_with_query_invocation_id(dep_node_index.into());

let Some(value) = value else {
Expand Down Expand Up @@ -197,6 +199,7 @@ pub(crate) fn promote_from_disk_inner<'tcx, C: QueryCache>(
pub(crate) fn try_load_from_disk<'tcx, V>(
tcx: TyCtxt<'tcx>,
prev_index: SerializedDepNodeIndex,
node: DepNode,
) -> Option<V>
where
V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
Expand All @@ -206,5 +209,6 @@ where
// The call to `with_query_deserialization` enforces that no new `DepNodes`
// are created during deserialization. See the docs of that method for more
// details.
tcx.dep_graph.with_query_deserialization(|| on_disk_cache.try_load_query_value(tcx, prev_index))
tcx.dep_graph
.with_query_deserialization(|| on_disk_cache.try_load_query_value(tcx, prev_index, node))
}
6 changes: 3 additions & 3 deletions compiler/rustc_query_impl/src/query_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,17 @@ macro_rules! define_queries {
invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace,

#[cfg($cache_on_disk)]
try_load_from_disk_fn: |tcx, prev_index| {
try_load_from_disk_fn: |tcx, prev_index, node| {
use rustc_middle::queries::$name::{ProvidedValue, provided_to_erased};

let loaded_value: ProvidedValue<'tcx> =
$crate::plumbing::try_load_from_disk(tcx, prev_index)?;
$crate::plumbing::try_load_from_disk(tcx, prev_index, node)?;

// Arena-alloc the value if appropriate, and erase it.
Some(provided_to_erased(tcx, loaded_value))
},
#[cfg(not($cache_on_disk))]
try_load_from_disk_fn: |_tcx, _prev_index| None,
try_load_from_disk_fn: |_tcx, _prev_index, _node| None,

#[cfg($handle_cycle_error)]
handle_cycle_error_fn: |tcx, key, cycle, err| {
Expand Down
Loading