From 4856affd90df68b0b56dee73c431e9d9cdfc977a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 1 Sep 2022 20:43:12 -0500 Subject: Make `HandleCycleError` an enum instead of a macro-generated closure - Add a `HandleCycleError` enum to rustc_query_system, along with a `handle_cycle_error` function - Move `Value` to rustc_query_system, so `handle_cycle_error` can use it - Move the `Value` impls from rustc_query_impl to rustc_middle. This is necessary due to orphan rules. --- compiler/rustc_query_impl/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'compiler/rustc_query_impl/src/lib.rs') diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 8ea09880694..26d397f70e0 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -34,9 +34,6 @@ pub use rustc_query_system::query::{deadlock, QueryContext}; mod keys; use keys::Key; -mod values; -use self::values::Value; - pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; -- cgit 1.4.1-3-g733a5 From b164dbc2715aa15be5c9f363a00d71e0847b2e77 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 1 Sep 2022 22:20:17 -0500 Subject: Don't create a new `try_load_from_disk` closure for each query Instead, define a single function, parameterized only by the return type. --- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 3 ++- compiler/rustc_query_impl/src/plumbing.rs | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_query_impl/src/lib.rs') diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 50bd95834b1..55d23ba1c67 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -255,7 +255,7 @@ fn add_query_description_impl(query: &Query, impls: &mut proc_macro2::TokenStrea } const TRY_LOAD_FROM_DISK: Option, SerializedDepNodeIndex) -> Option> - = Some(|tcx, id| tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)); + = Some(crate::plumbing::try_load_from_disk::); } } else { quote! { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 26d397f70e0..8148f8e017c 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -17,7 +17,7 @@ extern crate rustc_middle; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; -use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex}; +use rustc_middle::dep_graph::{self, DepKindStruct}; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine}; use rustc_middle::ty::{self, TyCtxt}; @@ -34,6 +34,7 @@ pub use rustc_query_system::query::{deadlock, QueryContext}; mod keys; use keys::Key; +use rustc_query_system::dep_graph::SerializedDepNodeIndex; pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1e375deb20d..48539d580c7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,6 +3,7 @@ //! manage the caches, and so forth. use crate::keys::Key; +use crate::on_disk_cache::CacheDecoder; use crate::{on_disk_cache, Queries}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lock; @@ -19,6 +20,7 @@ use rustc_query_system::query::{ QuerySideEffects, QueryStackFrame, }; use rustc_query_system::Value; +use rustc_serialize::Decodable; use std::any::Any; use std::num::NonZeroU64; use thin_vec::ThinVec; @@ -253,6 +255,18 @@ macro_rules! get_provider { }; } +macro_rules! should_ever_cache_on_disk { + ([]) => {{ + None + }}; + ([(cache) $($rest:tt)*]) => {{ + Some($crate::plumbing::try_load_from_disk::) + }}; + ([$other:tt $($modifiers:tt)*]) => { + should_ever_cache_on_disk!([$($modifiers)*]) + }; +} + pub(crate) fn create_query_frame< 'tcx, K: Copy + Key + for<'a> HashStable>, @@ -313,6 +327,16 @@ where } } +pub(crate) fn try_load_from_disk<'tcx, V>( + tcx: QueryCtxt<'tcx>, + id: SerializedDepNodeIndex, +) -> Option +where + V: for<'a> Decodable>, +{ + tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id) +} + fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryDescription>, -- cgit 1.4.1-3-g733a5 From 0a9d7dbca23bb05fab13c1dc75a87cdb2bf69ff5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 6 Sep 2022 19:09:32 -0500 Subject: Remove unnecessary `TRY_LOAD_FROM_DISK` constant --- compiler/rustc_query_impl/src/lib.rs | 1 - compiler/rustc_query_impl/src/plumbing.rs | 5 +---- compiler/rustc_query_system/src/query/config.rs | 5 +---- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_query_impl/src/lib.rs') diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 8148f8e017c..c87d26b3950 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -34,7 +34,6 @@ pub use rustc_query_system::query::{deadlock, QueryContext}; mod keys; use keys::Key; -use rustc_query_system::dep_graph::SerializedDepNodeIndex; pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index e38de2a0e40..6e0649cc471 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -412,9 +412,6 @@ macro_rules! define_queries { impl<'tcx> QueryDescription> for queries::$name<'tcx> { rustc_query_description! { $name } - const TRY_LOAD_FROM_DISK: Option, SerializedDepNodeIndex) -> Option> - = should_ever_cache_on_disk!([$($modifiers)*]); - type Cache = query_storage::$name<'tcx>; #[inline(always)] @@ -445,7 +442,7 @@ macro_rules! define_queries { hash_result: hash_result!([$($modifiers)*]), handle_cycle_error: handle_cycle_error!([$($modifiers)*]), compute, - try_load_from_disk: if cache_on_disk { Self::TRY_LOAD_FROM_DISK } else { None }, + try_load_from_disk: if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None }, } } diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 340deb88915..c4549cc9eb4 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -29,8 +29,7 @@ pub struct QueryVTable { pub compute: fn(CTX::DepContext, K) -> V, pub hash_result: Option, &V) -> Fingerprint>, pub handle_cycle_error: HandleCycleError, - // NOTE: this is not quite the same as `Q::TRY_LOAD_FROM_DISK`; it can also be `None` if - // `cache_on_disk` returned false for this key. + // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query pub try_load_from_disk: Option Option>, } @@ -48,8 +47,6 @@ impl QueryVTable { } pub trait QueryDescription: QueryConfig { - const TRY_LOAD_FROM_DISK: Option Option>; - type Cache: QueryCache; fn describe(tcx: CTX, key: Self::Key) -> String; -- cgit 1.4.1-3-g733a5 From 7a8369096c27312b1beda84c8f5c2ab207d8a3c7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 13 Sep 2022 18:32:22 -0500 Subject: Use function pointers instead of macro-unrolled loops in rustc_query_impl By making these standalone functions, we a) allow making them extensible in the future with a new `QueryStruct` b) greatly decrease the amount of code in each individual function, avoiding exponential blowup in llvm --- compiler/rustc_query_impl/src/lib.rs | 2 + compiler/rustc_query_impl/src/plumbing.rs | 124 ++++++++++++++------- compiler/rustc_query_impl/src/profiling_support.rs | 25 ++--- 3 files changed, 95 insertions(+), 56 deletions(-) (limited to 'compiler/rustc_query_impl/src/lib.rs') 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..a4d9d07bc8a 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, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>, +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -420,6 +409,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 +554,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 +621,11 @@ impl<'tcx> Queries<'tcx> { extern_providers: ExternProviders, on_disk_cache: Option>, ) -> 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 +640,7 @@ macro_rules! define_queries_struct { pub struct Queries<'tcx> { local_providers: Box, extern_providers: Box, + query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, pub on_disk_cache: Option>, @@ -600,18 +657,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, } @@ -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! } } -- cgit 1.4.1-3-g733a5