about summary refs log tree commit diff
path: root/compiler/rustc_query_impl
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_query_impl')
-rw-r--r--compiler/rustc_query_impl/src/keys.rs17
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs142
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs25
4 files changed, 128 insertions, 58 deletions
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs
index 31de83ee141..cdbf734cdbe 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_query_impl/src/keys.rs
@@ -1,7 +1,7 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::hir_id::HirId;
+use rustc_hir::hir_id::{HirId, OwnerId};
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::mir;
 use rustc_middle::traits;
@@ -105,6 +105,19 @@ impl Key for CrateNum {
     }
 }
 
+impl Key for OwnerId {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.to_def_id().default_span(tcx)
+    }
+    fn key_as_def_id(&self) -> Option<DefId> {
+        Some(self.to_def_id())
+    }
+}
+
 impl Key for LocalDefId {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
@@ -276,7 +289,7 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
     }
 }
 
-impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
+impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         (self.0).def.did.krate == LOCAL_CRATE
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index c87d26b3950..8e018d3e4a4 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -1,6 +1,8 @@
 //! Support for serializing the dep-graph and reloading it.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
+#![feature(const_mut_refs)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(once_cell)]
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)
             }
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 98ec3bc0977..2cc311d48c8 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -1,3 +1,4 @@
+use crate::QueryCtxt;
 use measureme::{StringComponent, StringId};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::SelfProfiler;
@@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache;
 use std::fmt::Debug;
 use std::io::Write;
 
-struct QueryKeyStringCache {
+pub(crate) struct QueryKeyStringCache {
     def_id_cache: FxHashMap<DefId, StringId>,
 }
 
@@ -226,7 +227,7 @@ where
 /// Allocate the self-profiling query strings for a single query cache. This
 /// method is called from `alloc_self_profile_query_strings` which knows all
 /// the queries via macro magic.
-fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
+pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
     tcx: TyCtxt<'tcx>,
     query_name: &'static str,
     query_cache: &C,
@@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
 /// If we are recording only summary data, the ids will point to
 /// just the query names. If we are recording query keys too, we
 /// allocate the corresponding strings here.
-pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
+pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) {
     if !tcx.prof.enabled() {
         return;
     }
 
     let mut string_cache = QueryKeyStringCache::new();
+    let queries = QueryCtxt::from_tcx(tcx);
 
-    macro_rules! alloc_once {
-        (
-        $($(#[$attr:meta])*
-            [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-            $(
-                alloc_self_profile_query_strings_for_query_cache(
-                    tcx,
-                    stringify!($name),
-                    &tcx.query_caches.$name,
-                    &mut string_cache,
-                );
-            )+
-        }
+    for query in &queries.queries.query_structs {
+        (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
     }
-
-    rustc_query_append! { alloc_once! }
 }