Skip to content

Commit 0059012

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

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,15 +11,15 @@
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
pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack};
22-
use crate::profiling_support::QueryKeyStringCache;
2323

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

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

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
) {
@@ -510,95 +530,48 @@ macro_rules! define_queries {
510530
}
511531
}
512532

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

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

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)