Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6831868

Browse files
committedFeb 16, 2024
Recreate DefIds when a cached query gets replayed
1 parent d103bd4 commit 6831868

File tree

6 files changed

+92
-22
lines changed

6 files changed

+92
-22
lines changed
 

‎compiler/rustc_middle/src/query/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,7 @@ rustc_queries! {
17181718
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
17191719
separate_provide_extern
17201720
feedable
1721+
cache_on_disk_if { def_id.is_local() }
17211722
}
17221723

17231724
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {

‎compiler/rustc_middle/src/ty/context.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ use rustc_hir::lang_items::LangItem;
5555
use rustc_hir::{HirId, Node, TraitCandidate};
5656
use rustc_index::IndexVec;
5757
use rustc_macros::HashStable;
58-
use rustc_query_system::dep_graph::DepNodeIndex;
58+
use rustc_query_system::dep_graph::{DepNodeIndex, TaskDepsRef};
5959
use rustc_query_system::ich::StableHashingContext;
60+
use rustc_query_system::query::DefIdInfo;
6061
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
6162
use rustc_session::config::CrateType;
6263
use rustc_session::cstore::{CrateStoreDyn, Untracked};
@@ -1087,9 +1088,28 @@ impl<'tcx> TyCtxt<'tcx> {
10871088

10881089
// This function modifies `self.definitions` using a side-effect.
10891090
// We need to ensure that these side effects are re-run by the incr. comp. engine.
1090-
// Depending on the forever-red node will tell the graph that the calling query
1091-
// needs to be re-evaluated.
1092-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
1091+
tls::with_context_opt(|icx| {
1092+
let icx = icx.unwrap();
1093+
let Some(side_effects) = &icx.side_effects else {
1094+
assert!(matches!(icx.task_deps, TaskDepsRef::Ignore), "{:?}", icx.task_deps);
1095+
return;
1096+
};
1097+
let info = DefIdInfo { parent, data };
1098+
match icx.task_deps {
1099+
TaskDepsRef::Allow(_)
1100+
| TaskDepsRef::EvalAlways
1101+
| TaskDepsRef::Ignore
1102+
| TaskDepsRef::Forbid => {
1103+
side_effects.lock().definitions.push(DefIdInfo { parent, data });
1104+
}
1105+
TaskDepsRef::Replay { prev_side_effects, created_def_ids } => {
1106+
let prev_info = &prev_side_effects.definitions
1107+
[created_def_ids.load(std::sync::atomic::Ordering::Relaxed)];
1108+
created_def_ids.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
1109+
assert_eq!(*prev_info, info);
1110+
}
1111+
}
1112+
});
10931113

10941114
let feed = self.feed_local_def_id(def_id);
10951115
feed.def_kind(def_kind);

‎compiler/rustc_query_impl/src/plumbing.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use rustc_middle::ty::{self, print::with_no_queries, TyCtxt};
2121
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
2222
use rustc_query_system::ich::StableHashingContext;
2323
use rustc_query_system::query::{
24-
force_query, QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects,
25-
QueryStackFrame,
24+
force_query, DefIdInfo, QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap,
25+
QuerySideEffects, QueryStackFrame,
2626
};
2727
use rustc_query_system::{LayoutOfDepth, QueryOverflow};
2828
use rustc_serialize::Decodable;
@@ -174,11 +174,15 @@ impl QueryContext for QueryCtxt<'_> {
174174
#[tracing::instrument(level = "trace", skip(self))]
175175
fn apply_side_effects(self, side_effects: QuerySideEffects) {
176176
let dcx = self.dep_context().sess().dcx();
177-
let QuerySideEffects { diagnostics } = side_effects;
177+
let QuerySideEffects { diagnostics, definitions } = side_effects;
178178

179179
for diagnostic in diagnostics {
180180
dcx.emit_diagnostic(diagnostic);
181181
}
182+
183+
for DefIdInfo { parent, data } in definitions {
184+
self.tcx.untracked().definitions.write().create_def(parent, data);
185+
}
182186
}
183187
}
184188

‎compiler/rustc_query_system/src/dep_graph/graph.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
use super::query::DepGraphQuery;
2+
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
3+
use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId};
4+
use crate::dep_graph::edges::EdgesVec;
5+
use crate::ich::StableHashingContext;
6+
use crate::query::{QueryContext, QuerySideEffects};
17
use rustc_data_structures::fingerprint::Fingerprint;
28
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
39
use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef};
410
use rustc_data_structures::sharded::{self, Sharded};
511
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
612
use rustc_data_structures::steal::Steal;
7-
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc};
13+
use rustc_data_structures::sync::{AtomicU32, AtomicU64, AtomicUsize, Lock, Lrc};
814
use rustc_data_structures::unord::UnordMap;
915
use rustc_index::IndexVec;
1016
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
@@ -15,13 +21,6 @@ use std::hash::Hash;
1521
use std::marker::PhantomData;
1622
use std::sync::atomic::Ordering;
1723

18-
use super::query::DepGraphQuery;
19-
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
20-
use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId};
21-
use crate::dep_graph::edges::EdgesVec;
22-
use crate::ich::StableHashingContext;
23-
use crate::query::{QueryContext, QuerySideEffects};
24-
2524
#[cfg(debug_assertions)]
2625
use {super::debug::EdgeFilter, std::env};
2726

@@ -218,6 +217,15 @@ impl<D: Deps> DepGraph<D> {
218217
D::with_deps(TaskDepsRef::Ignore, op)
219218
}
220219

220+
pub(crate) fn with_replay<R>(
221+
&self,
222+
prev_side_effects: &QuerySideEffects,
223+
created_def_ids: &AtomicUsize,
224+
op: impl FnOnce() -> R,
225+
) -> R {
226+
D::with_deps(TaskDepsRef::Replay { prev_side_effects, created_def_ids }, op)
227+
}
228+
221229
/// Used to wrap the deserialization of a query result from disk,
222230
/// This method enforces that no new `DepNodes` are created during
223231
/// query result deserialization.
@@ -272,6 +280,7 @@ impl<D: Deps> DepGraph<D> {
272280
}
273281

274282
#[inline(always)]
283+
/// A helper for `codegen_cranelift`.
275284
pub fn with_task<Ctxt: HasDepContext<Deps = D>, A: Debug, R>(
276285
&self,
277286
key: DepNode,
@@ -468,6 +477,12 @@ impl<D: Deps> DepGraph<D> {
468477
return;
469478
}
470479
TaskDepsRef::Ignore => return,
480+
// We don't need to record dependencies when rerunning a query
481+
// because we have no disk cache entry to load. The dependencies
482+
// are preserved.
483+
// FIXME: assert that the dependencies don't change instead of
484+
// recording them.
485+
TaskDepsRef::Replay { .. } => return,
471486
TaskDepsRef::Forbid => {
472487
panic!("Illegal read of: {dep_node_index:?}")
473488
}
@@ -573,6 +588,7 @@ impl<D: Deps> DepGraph<D> {
573588
edges.push(DepNodeIndex::FOREVER_RED_NODE);
574589
}
575590
TaskDepsRef::Ignore => {}
591+
TaskDepsRef::Replay { .. } => {}
576592
TaskDepsRef::Forbid => {
577593
panic!("Cannot summarize when dependencies are not recorded.")
578594
}
@@ -1323,6 +1339,16 @@ pub enum TaskDepsRef<'a> {
13231339
/// to ensure that the decoding process doesn't itself
13241340
/// require the execution of any queries.
13251341
Forbid,
1342+
/// Side effects from the previous run made available to
1343+
/// queries when they are reexecuted because their result was not
1344+
/// available in the cache. The query removes entries from the
1345+
/// side effect table. The table must be empty
1346+
Replay {
1347+
prev_side_effects: &'a QuerySideEffects,
1348+
/// Every new `DefId` is pushed here so we can check
1349+
/// that they match the cached ones.
1350+
created_def_ids: &'a AtomicUsize,
1351+
},
13261352
}
13271353

13281354
#[derive(Debug)]

‎compiler/rustc_query_system/src/query/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc_data_structures::stable_hasher::Hash64;
2323
use rustc_data_structures::sync::Lock;
2424
use rustc_errors::Diagnostic;
2525
use rustc_hir::def::DefKind;
26-
use rustc_span::def_id::DefId;
26+
use rustc_span::def_id::{DefId, LocalDefId};
2727
use rustc_span::Span;
2828
use thin_vec::ThinVec;
2929

@@ -90,20 +90,30 @@ pub struct QuerySideEffects {
9090
/// These diagnostics will be re-emitted if we mark
9191
/// the query as green.
9292
pub diagnostics: ThinVec<Diagnostic>,
93+
/// Stores any `DefId`s that were created during query execution.
94+
/// These `DefId`s will be re-created when we mark the query as green.
95+
pub definitions: ThinVec<DefIdInfo>,
96+
}
97+
98+
#[derive(Debug, Clone, Encodable, Decodable, PartialEq)]
99+
pub struct DefIdInfo {
100+
pub parent: LocalDefId,
101+
pub data: rustc_hir::definitions::DefPathData,
93102
}
94103

95104
impl QuerySideEffects {
96105
/// Returns true if there might be side effects.
97106
#[inline]
98107
pub fn maybe_any(&self) -> bool {
99-
let QuerySideEffects { diagnostics } = self;
108+
let QuerySideEffects { diagnostics, definitions } = self;
100109
// Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped
101110
// if `maybe_any` is known to be false.
102-
diagnostics.has_capacity()
111+
diagnostics.has_capacity() || definitions.has_capacity()
103112
}
104113
pub fn append(&mut self, other: QuerySideEffects) {
105-
let QuerySideEffects { diagnostics } = self;
114+
let QuerySideEffects { diagnostics, definitions } = self;
106115
diagnostics.extend(other.diagnostics);
116+
definitions.extend(other.definitions);
107117
}
108118
}
109119

‎compiler/rustc_query_system/src/query/plumbing.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
1616
use rustc_data_structures::fx::FxHashMap;
1717
use rustc_data_structures::sharded::Sharded;
1818
use rustc_data_structures::stack::ensure_sufficient_stack;
19-
use rustc_data_structures::sync::Lock;
19+
use rustc_data_structures::sync::{AtomicUsize, Lock};
2020
#[cfg(parallel_compiler)]
2121
use rustc_data_structures::{outline, sync};
2222
use rustc_errors::{DiagnosticBuilder, FatalError, StashKey};
@@ -502,7 +502,7 @@ where
502502
let dep_node =
503503
dep_node_opt.get_or_insert_with(|| query.construct_dep_node(*qcx.dep_context(), &key));
504504

505-
// The diagnostics for this query will be promoted to the current session during
505+
// The side_effects for this query will be promoted to the current session during
506506
// `try_mark_green()`, so we can ignore them here.
507507
if let Some(ret) = qcx.start_query(job_id, false, None, || {
508508
try_load_from_disk_and_cache_in_memory(query, dep_graph_data, qcx, &key, dep_node)
@@ -620,8 +620,17 @@ where
620620
// recompute.
621621
let prof_timer = qcx.dep_context().profiler().query_provider();
622622

623+
let prev_side_effects = qcx.load_side_effects(prev_dep_node_index);
624+
let created_def_ids = AtomicUsize::new(0);
623625
// The dep-graph for this computation is already in-place.
624-
let result = qcx.dep_context().dep_graph().with_ignore(|| query.compute(qcx, *key));
626+
let result =
627+
qcx.dep_context()
628+
.dep_graph()
629+
.with_replay(&prev_side_effects, &created_def_ids, || query.compute(qcx, *key));
630+
631+
assert_eq!(created_def_ids.into_inner(), prev_side_effects.definitions.len());
632+
// We already checked at `DefId` creation time, that the created `DefId`s have the same parent and `DefPathData`
633+
// as the cached ones.
625634

626635
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
627636

0 commit comments

Comments
 (0)
Failed to load comments.