Skip to content

Commit 7a83690

Browse files
committed
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
1 parent 4652f5e commit 7a83690

File tree

3 files changed

+95
-56
lines changed

3 files changed

+95
-56
lines changed

compiler/rustc_query_impl/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Support for serializing the dep-graph and reloading it.
22
33
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
4+
// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
5+
#![feature(const_mut_refs)]
46
#![feature(min_specialization)]
57
#![feature(never_type)]
68
#![feature(once_cell)]

compiler/rustc_query_impl/src/plumbing.rs

+86-38
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
//! manage the caches, and so forth.
44
55
use crate::keys::Key;
6-
use crate::on_disk_cache::CacheDecoder;
6+
use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
7+
use crate::profiling_support::QueryKeyStringCache;
78
use crate::{on_disk_cache, Queries};
89
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
910
use rustc_data_structures::sync::{AtomicU64, Lock};
@@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> {
173174

174175
pub(super) fn encode_query_results(
175176
self,
176-
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
177-
query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
177+
encoder: &mut CacheEncoder<'_, 'tcx>,
178+
query_result_index: &mut EncodedDepNodeIndex,
178179
) {
179-
macro_rules! expand_if_cached {
180-
([] $encode:expr) => {};
181-
([(cache) $($rest:tt)*] $encode:expr) => {
182-
$encode
183-
};
184-
([$other:tt $($modifiers:tt)*] $encode:expr) => {
185-
expand_if_cached!([$($modifiers)*] $encode)
186-
};
187-
}
188-
189-
macro_rules! encode_queries {
190-
(
191-
$($(#[$attr:meta])*
192-
[$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => {
193-
$(
194-
expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>(
195-
self,
196-
encoder,
197-
query_result_index
198-
));
199-
)*
180+
for query in &self.queries.query_structs {
181+
if let Some(encode) = query.encode_query_results {
182+
encode(self, encoder, query_result_index);
200183
}
201184
}
202-
203-
rustc_query_append!(encode_queries!);
204185
}
205186

206187
pub fn try_print_query_stack(
@@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> {
213194
}
214195
}
215196

197+
#[derive(Clone, Copy)]
198+
pub(crate) struct QueryStruct<'tcx> {
199+
pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>,
200+
pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
201+
pub encode_query_results:
202+
Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
203+
}
204+
216205
macro_rules! handle_cycle_error {
217206
([]) => {{
218207
rustc_query_system::HandleCycleError::Error
@@ -420,6 +409,18 @@ where
420409
}
421410
}
422411

412+
macro_rules! expand_if_cached {
413+
([], $tokens:expr) => {{
414+
None
415+
}};
416+
([(cache) $($rest:tt)*], $tokens:expr) => {{
417+
Some($tokens)
418+
}};
419+
([$other:tt $($modifiers:tt)*], $tokens:expr) => {
420+
expand_if_cached!([$($modifiers)*], $tokens)
421+
};
422+
}
423+
423424
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
424425
// invoked by `rustc_query_append`.
425426
macro_rules! define_queries {
@@ -553,6 +554,59 @@ macro_rules! define_queries {
553554
})*
554555
}
555556

557+
mod query_structs {
558+
use rustc_middle::ty::TyCtxt;
559+
use $crate::plumbing::{QueryStruct, QueryCtxt};
560+
use $crate::profiling_support::QueryKeyStringCache;
561+
use rustc_query_system::query::{QueryDescription, QueryMap};
562+
563+
pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
564+
fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
565+
None
566+
}
567+
fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
568+
569+
QueryStruct {
570+
try_collect_active_jobs: noop_try_collect_active_jobs,
571+
alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
572+
encode_query_results: None,
573+
}
574+
}
575+
576+
pub(super) use dummy_query_struct as Null;
577+
pub(super) use dummy_query_struct as Red;
578+
pub(super) use dummy_query_struct as TraitSelect;
579+
pub(super) use dummy_query_struct as CompileCodegenUnit;
580+
pub(super) use dummy_query_struct as CompileMonoItem;
581+
582+
$(
583+
pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
584+
try_collect_active_jobs: |tcx, qmap| {
585+
let make_query = |tcx, key| {
586+
let kind = rustc_middle::dep_graph::DepKind::$name;
587+
let name = stringify!($name);
588+
$crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name)
589+
};
590+
tcx.queries.$name.try_collect_active_jobs(
591+
tcx,
592+
make_query,
593+
qmap,
594+
)
595+
},
596+
alloc_self_profile_query_strings: |tcx, string_cache| {
597+
$crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
598+
tcx,
599+
stringify!($name),
600+
&tcx.query_caches.$name,
601+
string_cache,
602+
)
603+
},
604+
encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
605+
$crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
606+
),
607+
}})*
608+
}
609+
556610
pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
557611
arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
558612
}
@@ -567,9 +621,11 @@ impl<'tcx> Queries<'tcx> {
567621
extern_providers: ExternProviders,
568622
on_disk_cache: Option<OnDiskCache<'tcx>>,
569623
) -> Self {
624+
use crate::query_structs;
570625
Queries {
571626
local_providers: Box::new(local_providers),
572627
extern_providers: Box::new(extern_providers),
628+
query_structs: make_dep_kind_array!(query_structs).to_vec(),
573629
on_disk_cache,
574630
jobs: AtomicU64::new(1),
575631
..Queries::default()
@@ -584,6 +640,7 @@ macro_rules! define_queries_struct {
584640
pub struct Queries<'tcx> {
585641
local_providers: Box<Providers>,
586642
extern_providers: Box<ExternProviders>,
643+
query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,
587644

588645
pub on_disk_cache: Option<OnDiskCache<'tcx>>,
589646

@@ -600,18 +657,9 @@ macro_rules! define_queries_struct {
600657
let tcx = QueryCtxt { tcx, queries: self };
601658
let mut jobs = QueryMap::default();
602659

603-
$(
604-
let make_query = |tcx, key| {
605-
let kind = dep_graph::DepKind::$name;
606-
let name = stringify!($name);
607-
$crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
608-
};
609-
self.$name.try_collect_active_jobs(
610-
tcx,
611-
make_query,
612-
&mut jobs,
613-
)?;
614-
)*
660+
for query in &self.query_structs {
661+
(query.try_collect_active_jobs)(tcx, &mut jobs);
662+
}
615663

616664
Some(jobs)
617665
}

compiler/rustc_query_impl/src/profiling_support.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::QueryCtxt;
12
use measureme::{StringComponent, StringId};
23
use rustc_data_structures::fx::FxHashMap;
34
use rustc_data_structures::profiling::SelfProfiler;
@@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache;
89
use std::fmt::Debug;
910
use std::io::Write;
1011

11-
struct QueryKeyStringCache {
12+
pub(crate) struct QueryKeyStringCache {
1213
def_id_cache: FxHashMap<DefId, StringId>,
1314
}
1415

@@ -226,7 +227,7 @@ where
226227
/// Allocate the self-profiling query strings for a single query cache. This
227228
/// method is called from `alloc_self_profile_query_strings` which knows all
228229
/// the queries via macro magic.
229-
fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
230+
pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
230231
tcx: TyCtxt<'tcx>,
231232
query_name: &'static str,
232233
query_cache: &C,
@@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
298299
/// If we are recording only summary data, the ids will point to
299300
/// just the query names. If we are recording query keys too, we
300301
/// allocate the corresponding strings here.
301-
pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
302+
pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) {
302303
if !tcx.prof.enabled() {
303304
return;
304305
}
305306

306307
let mut string_cache = QueryKeyStringCache::new();
308+
let queries = QueryCtxt::from_tcx(tcx);
307309

308-
macro_rules! alloc_once {
309-
(
310-
$($(#[$attr:meta])*
311-
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
312-
$(
313-
alloc_self_profile_query_strings_for_query_cache(
314-
tcx,
315-
stringify!($name),
316-
&tcx.query_caches.$name,
317-
&mut string_cache,
318-
);
319-
)+
320-
}
310+
for query in &queries.queries.query_structs {
311+
(query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
321312
}
322-
323-
rustc_query_append! { alloc_once! }
324313
}

0 commit comments

Comments
 (0)