Skip to content

Commit 45cd205

Browse files
committed
Auto merge of #153685 - Zalathar:for-each-query, r=<try>
Introduce `for_each_query_vtable!` to move more code out of query macros
2 parents b49ecc9 + dcad3d3 commit 45cd205

5 files changed

Lines changed: 124 additions & 93 deletions

File tree

compiler/rustc_query_impl/src/execution.rs

Lines changed: 28 additions & 1 deletion
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,6 +30,33 @@ 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`.

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: 58 additions & 86 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,6 +146,16 @@ where
146146
QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle)
147147
}
148148

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+
149159
pub(crate) fn encode_query_results<'a, 'tcx, C, V>(
150160
tcx: TyCtxt<'tcx>,
151161
query: &'tcx QueryVTable<'tcx, C>,
@@ -172,6 +182,16 @@ pub(crate) fn encode_query_results<'a, 'tcx, C, V>(
172182
});
173183
}
174184

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+
175195
pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache>(
176196
query: &'tcx QueryVTable<'tcx, C>,
177197
tcx: TyCtxt<'tcx>,
@@ -512,95 +532,47 @@ 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+
/// The syntax of this macro is specifically intended to look like plain
544+
/// Rust code, so that rustfmt will format it.
550545
///
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-
)*
546+
/// To avoid too much nested-macro complication, filter conditions are
547+
/// implemented by hand as needed.
548+
macro_rules! for_each_query_vtable {
549+
// Call with all queries.
550+
(ALL, $tcx:expr, $closure:expr) => {{
551+
let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx;
552+
$(
553+
let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> =
554+
&tcx.query_system.query_vtables.$name;
555+
$closure(query);
556+
)*
557+
}};
558+
559+
// Only call with queries that can potentially cache to disk.
560+
//
561+
// This allows the use of trait bounds that only need to be satisfied
562+
// by the subset of queries that actually cache to disk.
563+
(CACHE_ON_DISK, $tcx:expr, $closure:expr) => {{
564+
let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx;
565+
$(
566+
#[cfg($cache_on_disk)]
567+
{
568+
let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> =
569+
&tcx.query_system.query_vtables.$name;
570+
$closure(query);
571+
}
572+
)*
573+
}}
591574
}
592575

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-
}
576+
pub(crate) use for_each_query_vtable;
605577
}
606578
}

compiler/rustc_query_impl/src/profiling_support.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,39 @@ 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+
15+
/// All self-profiling events generated by the query engine use
16+
/// virtual `StringId`s for their `event_id`. This method makes all
17+
/// those virtual `StringId`s point to actual strings.
18+
///
19+
/// If we are recording only summary data, the ids will point to
20+
/// just the query names. If we are recording query keys too, we
21+
/// allocate the corresponding strings here.
22+
pub(crate) fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
23+
if !tcx.prof.enabled() {
24+
return;
25+
}
26+
27+
let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings");
28+
29+
let mut string_cache = QueryKeyStringCache::new();
30+
31+
for_each_query_vtable!(ALL, tcx, |query: &QueryVTable<'_, _>| {
32+
alloc_self_profile_query_strings_for_query_cache(
33+
tcx,
34+
query.name,
35+
&query.cache,
36+
&mut string_cache,
37+
);
38+
});
39+
40+
tcx.sess.prof.store_query_cache_hits();
41+
}
42+
1243
pub(crate) struct QueryKeyStringCache {
1344
def_id_cache: FxHashMap<DefId, StringId>,
1445
}

0 commit comments

Comments
 (0)