Skip to content

Commit c4a338a

Browse files
committed
Introduce for_each_query_vtable! to move more code out of query macros
1 parent b49ecc9 commit c4a338a

5 files changed

Lines changed: 129 additions & 97 deletions

File tree

compiler/rustc_query_impl/src/execution.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use rustc_middle::ty::TyCtxt;
1616
use rustc_middle::verify_ich::incremental_verify_ich;
1717
use rustc_span::{DUMMY_SP, Span};
1818

19-
use crate::collect_active_jobs_from_all_queries;
2019
use crate::dep_graph::{DepNode, DepNodeIndex};
20+
use crate::for_each_query_vtable;
2121
use crate::job::{QueryJobInfo, QueryJobMap, find_cycle_in_stack, report_cycle};
2222
use crate::plumbing::{current_query_job, next_job_id, start_query};
2323

@@ -30,14 +30,41 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool {
3030
state.active.lock_shards().all(|shard| shard.is_empty())
3131
}
3232

33+
/// Returns a map of currently active query jobs, collected from all queries.
34+
///
35+
/// If `require_complete` is `true`, this function locks all shards of the
36+
/// query results to produce a complete map, which always returns `Ok`.
37+
/// Otherwise, it may return an incomplete map as an error if any shard
38+
/// lock cannot be acquired.
39+
///
40+
/// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
41+
/// especially when called from within a deadlock handler, unless a
42+
/// complete map is needed and no deadlock is possible at this call site.
43+
pub fn collect_active_jobs_from_all_queries<'tcx>(
44+
tcx: TyCtxt<'tcx>,
45+
require_complete: bool,
46+
) -> Result<QueryJobMap<'tcx>, QueryJobMap<'tcx>> {
47+
let mut job_map_out = QueryJobMap::default();
48+
let mut complete = true;
49+
50+
for_each_query_vtable!(ALL, tcx, |query| {
51+
let res = gather_active_jobs(query, tcx, require_complete, &mut job_map_out);
52+
if res.is_none() {
53+
complete = false;
54+
}
55+
});
56+
57+
if complete { Ok(job_map_out) } else { Err(job_map_out) }
58+
}
59+
3360
/// Internal plumbing for collecting the set of active jobs for this query.
3461
///
3562
/// Should only be called from `collect_active_jobs_from_all_queries`.
3663
///
3764
/// (We arbitrarily use the word "gather" when collecting the jobs for
3865
/// each individual query, so that we have distinct function names to
3966
/// grep for.)
40-
pub(crate) fn gather_active_jobs<'tcx, C>(
67+
fn gather_active_jobs<'tcx, C>(
4168
query: &'tcx QueryVTable<'tcx, C>,
4269
tcx: TyCtxt<'tcx>,
4370
require_complete: bool,

compiler/rustc_query_impl/src/job.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::ty::TyCtxt;
1414
use rustc_session::Session;
1515
use rustc_span::{DUMMY_SP, Span};
1616

17-
use crate::collect_active_jobs_from_all_queries;
17+
use crate::execution::collect_active_jobs_from_all_queries;
1818

1919
/// Map from query job IDs to job information collected by
2020
/// `collect_active_jobs_from_all_queries`.

compiler/rustc_query_impl/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
use rustc_data_structures::sync::AtomicU64;
1212
use rustc_middle::dep_graph;
1313
use rustc_middle::queries::{self, ExternProviders, Providers};
14-
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
14+
use rustc_middle::query::on_disk_cache::OnDiskCache;
1515
use rustc_middle::query::plumbing::{QuerySystem, QueryVTable};
1616
use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode};
1717
use rustc_middle::ty::TyCtxt;
1818
use rustc_span::Span;
1919

2020
pub use crate::dep_kind_vtables::make_dep_kind_vtables;
21+
pub use crate::execution::collect_active_jobs_from_all_queries;
2122
use crate::from_cycle_error::FromCycleError;
2223
pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack};
23-
use crate::profiling_support::QueryKeyStringCache;
2424

2525
#[macro_use]
2626
mod plumbing;
@@ -65,7 +65,8 @@ pub fn query_system<'tcx>(
6565
rustc_middle::rustc_with_all_queries! { define_queries! }
6666

6767
pub fn provide(providers: &mut rustc_middle::util::Providers) {
68-
providers.hooks.alloc_self_profile_query_strings = alloc_self_profile_query_strings;
69-
providers.hooks.query_key_hash_verify_all = query_key_hash_verify_all;
70-
providers.hooks.encode_all_query_results = encode_all_query_results;
68+
providers.hooks.alloc_self_profile_query_strings =
69+
profiling_support::alloc_self_profile_query_strings;
70+
providers.hooks.query_key_hash_verify_all = plumbing::query_key_hash_verify_all;
71+
providers.hooks.encode_all_query_results = plumbing::encode_all_query_results;
7172
}

compiler/rustc_query_impl/src/plumbing.rs

Lines changed: 61 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use rustc_span::def_id::LOCAL_CRATE;
3333
use crate::error::{QueryOverflow, QueryOverflowNote};
3434
use crate::execution::{all_inactive, force_query};
3535
use crate::job::find_dep_kind_root;
36-
use crate::{GetQueryVTable, collect_active_jobs_from_all_queries};
36+
use crate::{GetQueryVTable, collect_active_jobs_from_all_queries, for_each_query_vtable};
3737

3838
fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) {
3939
let job_map =
@@ -146,7 +146,17 @@ where
146146
QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle)
147147
}
148148

149-
pub(crate) fn encode_query_results<'a, 'tcx, C, V>(
149+
pub(crate) fn encode_all_query_results<'tcx>(
150+
tcx: TyCtxt<'tcx>,
151+
encoder: &mut CacheEncoder<'_, 'tcx>,
152+
query_result_index: &mut EncodedDepNodeIndex,
153+
) {
154+
for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| {
155+
encode_query_results(tcx, query, encoder, query_result_index)
156+
});
157+
}
158+
159+
fn encode_query_results<'a, 'tcx, C, V>(
150160
tcx: TyCtxt<'tcx>,
151161
query: &'tcx QueryVTable<'tcx, C>,
152162
encoder: &mut CacheEncoder<'a, 'tcx>,
@@ -172,7 +182,17 @@ pub(crate) fn encode_query_results<'a, 'tcx, C, V>(
172182
});
173183
}
174184

175-
pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache>(
185+
pub(crate) fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
186+
if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) {
187+
tcx.sess.time("query_key_hash_verify_all", || {
188+
for_each_query_vtable!(ALL, tcx, |query| {
189+
query_key_hash_verify(query, tcx);
190+
});
191+
});
192+
}
193+
}
194+
195+
fn query_key_hash_verify<'tcx, C: QueryCache>(
176196
query: &'tcx QueryVTable<'tcx, C>,
177197
tcx: TyCtxt<'tcx>,
178198
) {
@@ -512,95 +532,48 @@ macro_rules! define_queries {
512532
}
513533
}
514534

515-
/// Returns a map of currently active query jobs, collected from all queries.
535+
/// Given a filter condition (e.g. `ALL` or `CACHE_ON_DISK`), a `tcx`,
536+
/// and a closure expression that accepts `&QueryVTable`, this macro
537+
/// calls that closure with each query vtable that satisfies the filter
538+
/// condition.
516539
///
517-
/// If `require_complete` is `true`, this function locks all shards of the
518-
/// query results to produce a complete map, which always returns `Ok`.
519-
/// Otherwise, it may return an incomplete map as an error if any shard
520-
/// lock cannot be acquired.
540+
/// This needs to be a macro, because the vtables can have different
541+
/// key/value/cache types for different queries.
521542
///
522-
/// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
523-
/// especially when called from within a deadlock handler, unless a
524-
/// complete map is needed and no deadlock is possible at this call site.
525-
pub fn collect_active_jobs_from_all_queries<'tcx>(
526-
tcx: TyCtxt<'tcx>,
527-
require_complete: bool,
528-
) -> Result<QueryJobMap<'tcx>, QueryJobMap<'tcx>> {
529-
let mut job_map_out = QueryJobMap::default();
530-
let mut complete = true;
531-
532-
$(
533-
let res = crate::execution::gather_active_jobs(
534-
&tcx.query_system.query_vtables.$name,
535-
tcx,
536-
require_complete,
537-
&mut job_map_out,
538-
);
539-
if res.is_none() {
540-
complete = false;
541-
}
542-
)*
543-
544-
if complete { Ok(job_map_out) } else { Err(job_map_out) }
545-
}
546-
547-
/// All self-profiling events generated by the query engine use
548-
/// virtual `StringId`s for their `event_id`. This method makes all
549-
/// those virtual `StringId`s point to actual strings.
543+
/// This macro's argument syntax is specifically intended to look like
544+
/// plain Rust code, so that `for_each_query_vtable!(..)` calls will be
545+
/// formatted by rustfmt.
550546
///
551-
/// If we are recording only summary data, the ids will point to
552-
/// just the query names. If we are recording query keys too, we
553-
/// allocate the corresponding strings here.
554-
pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
555-
if !tcx.prof.enabled() {
556-
return;
557-
}
558-
559-
let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings");
560-
561-
let mut string_cache = QueryKeyStringCache::new();
562-
563-
$(
564-
$crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
565-
tcx,
566-
stringify!($name),
567-
&tcx.query_system.query_vtables.$name.cache,
568-
&mut string_cache,
569-
);
570-
)*
571-
572-
tcx.sess.prof.store_query_cache_hits();
573-
}
574-
575-
fn encode_all_query_results<'tcx>(
576-
tcx: TyCtxt<'tcx>,
577-
encoder: &mut CacheEncoder<'_, 'tcx>,
578-
query_result_index: &mut EncodedDepNodeIndex,
579-
) {
580-
$(
581-
#[cfg($cache_on_disk)]
582-
{
583-
$crate::plumbing::encode_query_results(
584-
tcx,
585-
&tcx.query_system.query_vtables.$name,
586-
encoder,
587-
query_result_index,
588-
)
589-
}
590-
)*
547+
/// To avoid too much nested-macro complication, filter conditions are
548+
/// implemented by hand as needed.
549+
macro_rules! for_each_query_vtable {
550+
// Call with all queries.
551+
(ALL, $tcx:expr, $closure:expr) => {{
552+
let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx;
553+
$(
554+
let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> =
555+
&tcx.query_system.query_vtables.$name;
556+
$closure(query);
557+
)*
558+
}};
559+
560+
// Only call with queries that can potentially cache to disk.
561+
//
562+
// This allows the use of trait bounds that only need to be satisfied
563+
// by the subset of queries that actually cache to disk.
564+
(CACHE_ON_DISK, $tcx:expr, $closure:expr) => {{
565+
let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx;
566+
$(
567+
#[cfg($cache_on_disk)]
568+
{
569+
let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> =
570+
&tcx.query_system.query_vtables.$name;
571+
$closure(query);
572+
}
573+
)*
574+
}}
591575
}
592576

593-
pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
594-
if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) {
595-
tcx.sess.time("query_key_hash_verify_all", || {
596-
$(
597-
$crate::plumbing::query_key_hash_verify(
598-
&tcx.query_system.query_vtables.$name,
599-
tcx
600-
);
601-
)*
602-
})
603-
}
604-
}
577+
pub(crate) use for_each_query_vtable;
605578
}
606579
}

compiler/rustc_query_impl/src/profiling_support.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ use rustc_data_structures::profiling::SelfProfiler;
77
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId};
88
use rustc_hir::definitions::DefPathData;
99
use rustc_middle::query::QueryCache;
10+
use rustc_middle::query::plumbing::QueryVTable;
1011
use rustc_middle::ty::TyCtxt;
1112

13+
use crate::for_each_query_vtable;
14+
1215
pub(crate) struct QueryKeyStringCache {
1316
def_id_cache: FxHashMap<DefId, StringId>,
1417
}
@@ -172,10 +175,38 @@ where
172175
}
173176
}
174177

178+
/// All self-profiling events generated by the query engine use
179+
/// virtual `StringId`s for their `event_id`. This method makes all
180+
/// those virtual `StringId`s point to actual strings.
181+
///
182+
/// If we are recording only summary data, the ids will point to
183+
/// just the query names. If we are recording query keys too, we
184+
/// allocate the corresponding strings here.
185+
pub(crate) fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
186+
if !tcx.prof.enabled() {
187+
return;
188+
}
189+
190+
let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings");
191+
192+
let mut string_cache = QueryKeyStringCache::new();
193+
194+
for_each_query_vtable!(ALL, tcx, |query: &QueryVTable<'_, _>| {
195+
alloc_self_profile_query_strings_for_query_cache(
196+
tcx,
197+
query.name,
198+
&query.cache,
199+
&mut string_cache,
200+
);
201+
});
202+
203+
tcx.sess.prof.store_query_cache_hits();
204+
}
205+
175206
/// Allocate the self-profiling query strings for a single query cache. This
176207
/// method is called from `alloc_self_profile_query_strings` which knows all
177208
/// the queries via macro magic.
178-
pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
209+
fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
179210
tcx: TyCtxt<'tcx>,
180211
query_name: &'static str,
181212
query_cache: &C,

0 commit comments

Comments
 (0)