diff options
Diffstat (limited to 'compiler/rustc_query_impl/src/plumbing.rs')
| -rw-r--r-- | compiler/rustc_query_impl/src/plumbing.rs | 142 |
1 files changed, 104 insertions, 38 deletions
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d819f4774d5..2b3850bc0df 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,7 +3,8 @@ //! manage the caches, and so forth. use crate::keys::Key; -use crate::on_disk_cache::CacheDecoder; +use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; +use crate::profiling_support::QueryKeyStringCache; use crate::{on_disk_cache, Queries}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; @@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> { pub(super) fn encode_query_results( self, - encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>, - query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex, ) { - macro_rules! expand_if_cached { - ([] $encode:expr) => {}; - ([(cache) $($rest:tt)*] $encode:expr) => { - $encode - }; - ([$other:tt $($modifiers:tt)*] $encode:expr) => { - expand_if_cached!([$($modifiers)*] $encode) - }; - } - - macro_rules! encode_queries { - ( - $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => { - $( - expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>( - self, - encoder, - query_result_index - )); - )* + for query in &self.queries.query_structs { + if let Some(encode) = query.encode_query_results { + encode(self, encoder, query_result_index); } } - - rustc_query_append!(encode_queries!); } pub fn try_print_query_stack( @@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> { } } +#[derive(Clone, Copy)] +pub(crate) struct QueryStruct<'tcx> { + pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>, + pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache), + pub encode_query_results: + Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>, +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -380,6 +369,24 @@ where Q::Key: DepNodeParams<TyCtxt<'tcx>>, Q::Value: Value<TyCtxt<'tcx>>, { + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + dep_node.kind != DepKind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + if let Some(key) = Q::Key::recover(tcx, &dep_node) { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); @@ -420,6 +427,18 @@ where } } +macro_rules! expand_if_cached { + ([], $tokens:expr) => {{ + None + }}; + ([(cache) $($rest:tt)*], $tokens:expr) => {{ + Some($tokens) + }}; + ([$other:tt $($modifiers:tt)*], $tokens:expr) => { + expand_if_cached!([$($modifiers)*], $tokens) + }; +} + // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_query_append`. macro_rules! define_queries { @@ -553,6 +572,59 @@ macro_rules! define_queries { })* } + mod query_structs { + use rustc_middle::ty::TyCtxt; + use $crate::plumbing::{QueryStruct, QueryCtxt}; + use $crate::profiling_support::QueryKeyStringCache; + use rustc_query_system::query::{QueryDescription, QueryMap}; + + pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> { + fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> { + None + } + fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {} + + QueryStruct { + try_collect_active_jobs: noop_try_collect_active_jobs, + alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings, + encode_query_results: None, + } + } + + pub(super) use dummy_query_struct as Null; + pub(super) use dummy_query_struct as Red; + pub(super) use dummy_query_struct as TraitSelect; + pub(super) use dummy_query_struct as CompileCodegenUnit; + pub(super) use dummy_query_struct as CompileMonoItem; + + $( + pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct { + try_collect_active_jobs: |tcx, qmap| { + let make_query = |tcx, key| { + let kind = rustc_middle::dep_graph::DepKind::$name; + let name = stringify!($name); + $crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name) + }; + tcx.queries.$name.try_collect_active_jobs( + tcx, + make_query, + qmap, + ) + }, + alloc_self_profile_query_strings: |tcx, string_cache| { + $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( + tcx, + stringify!($name), + &tcx.query_caches.$name, + string_cache, + ) + }, + encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index| + $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index) + ), + }})* + } + pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] { arena.alloc_from_iter(make_dep_kind_array!(query_callbacks)) } @@ -567,9 +639,11 @@ impl<'tcx> Queries<'tcx> { extern_providers: ExternProviders, on_disk_cache: Option<OnDiskCache<'tcx>>, ) -> Self { + use crate::query_structs; Queries { local_providers: Box::new(local_providers), extern_providers: Box::new(extern_providers), + query_structs: make_dep_kind_array!(query_structs).to_vec(), on_disk_cache, jobs: AtomicU64::new(1), ..Queries::default() @@ -584,6 +658,7 @@ macro_rules! define_queries_struct { pub struct Queries<'tcx> { local_providers: Box<Providers>, extern_providers: Box<ExternProviders>, + query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, pub on_disk_cache: Option<OnDiskCache<'tcx>>, @@ -600,18 +675,9 @@ macro_rules! define_queries_struct { let tcx = QueryCtxt { tcx, queries: self }; let mut jobs = QueryMap::default(); - $( - let make_query = |tcx, key| { - let kind = dep_graph::DepKind::$name; - let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name) - }; - self.$name.try_collect_active_jobs( - tcx, - make_query, - &mut jobs, - )?; - )* + for query in &self.query_structs { + (query.try_collect_active_jobs)(tcx, &mut jobs); + } Some(jobs) } |
