Skip to content

Commit 5230574

Browse files
committed
Use dynamic dispatch for queries
1 parent 61e65ea commit 5230574

File tree

10 files changed

+425
-184
lines changed

10 files changed

+425
-184
lines changed

Cargo.lock

+11-1
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,7 @@ dependencies = [
10461046
"autocfg",
10471047
"cfg-if",
10481048
"crossbeam-utils",
1049-
"memoffset",
1049+
"memoffset 0.7.1",
10501050
"scopeguard",
10511051
]
10521052

@@ -2622,6 +2622,15 @@ dependencies = [
26222622
"autocfg",
26232623
]
26242624

2625+
[[package]]
2626+
name = "memoffset"
2627+
version = "0.8.0"
2628+
source = "registry+https://github.com/rust-lang/crates.io-index"
2629+
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
2630+
dependencies = [
2631+
"autocfg",
2632+
]
2633+
26252634
[[package]]
26262635
name = "minifier"
26272636
version = "0.2.2"
@@ -4556,6 +4565,7 @@ name = "rustc_query_impl"
45564565
version = "0.0.0"
45574566
dependencies = [
45584567
"measureme",
4568+
"memoffset 0.8.0",
45594569
"rustc-rayon-core",
45604570
"rustc_ast",
45614571
"rustc_data_structures",

compiler/rustc_interface/src/passes.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto
1717
use rustc_metadata::creader::CStore;
1818
use rustc_middle::arena::Arena;
1919
use rustc_middle::dep_graph::DepGraph;
20-
use rustc_middle::ty::query::{ExternProviders, Providers};
20+
use rustc_middle::ty::query::{ExternProviders, Providers, QuerySystem};
2121
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
2222
use rustc_mir_build as mir_build;
2323
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
@@ -687,9 +687,10 @@ pub fn create_global_ctxt<'tcx>(
687687
callback(sess, &mut local_providers, &mut extern_providers);
688688
}
689689

690-
let queries = queries.get_or_init(|| {
691-
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
692-
});
690+
let queries =
691+
queries.get_or_init(|| TcxQueries::new(&local_providers, query_result_on_disk_cache));
692+
693+
let query_system = QuerySystem::new(local_providers, extern_providers);
693694

694695
sess.time("setup_global_ctxt", || {
695696
gcx_cell.get_or_init(move || {
@@ -701,6 +702,7 @@ pub fn create_global_ctxt<'tcx>(
701702
untracked,
702703
dep_graph,
703704
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
705+
query_system,
704706
queries.as_dyn(),
705707
rustc_query_impl::query_callbacks(arena),
706708
)

compiler/rustc_middle/src/ty/context.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ use std::iter;
7878
use std::mem;
7979
use std::ops::{Bound, Deref};
8080

81+
use super::query::QuerySystem;
82+
8183
const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
8284

8385
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
@@ -681,6 +683,7 @@ impl<'tcx> TyCtxt<'tcx> {
681683
untracked: Untracked,
682684
dep_graph: DepGraph,
683685
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
686+
query_system: QuerySystem<'tcx>,
684687
queries: &'tcx dyn query::QueryEngine<'tcx>,
685688
query_kinds: &'tcx [DepKindStruct<'tcx>],
686689
) -> GlobalCtxt<'tcx> {
@@ -706,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
706709
untracked,
707710
on_disk_cache,
708711
queries,
709-
query_system: Default::default(),
712+
query_system,
710713
query_kinds,
711714
ty_rcache: Default::default(),
712715
pred_rcache: Default::default(),

compiler/rustc_middle/src/ty/query.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,24 @@ use std::sync::Arc;
7171
pub(crate) use rustc_query_system::query::QueryJobId;
7272
use rustc_query_system::query::*;
7373

74-
#[derive(Default)]
7574
pub struct QuerySystem<'tcx> {
75+
pub local_providers: Box<Providers>,
76+
pub extern_providers: Box<ExternProviders>,
7677
pub arenas: QueryArenas<'tcx>,
7778
pub caches: QueryCaches<'tcx>,
7879
}
7980

81+
impl<'tcx> QuerySystem<'tcx> {
82+
pub fn new(local_providers: Providers, extern_providers: ExternProviders) -> Self {
83+
QuerySystem {
84+
local_providers: Box::new(local_providers),
85+
extern_providers: Box::new(extern_providers),
86+
arenas: Default::default(),
87+
caches: Default::default(),
88+
}
89+
}
90+
}
91+
8092
#[derive(Copy, Clone)]
8193
pub struct TyCtxtAt<'tcx> {
8294
pub tcx: TyCtxt<'tcx>,

compiler/rustc_query_impl/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77

88

99
[dependencies]
10+
memoffset = { version = "0.8.0", features = ["unstable_const"] }
1011
measureme = "10.0.0"
1112
rustc_ast = { path = "../rustc_ast" }
1213
rustc_data_structures = { path = "../rustc_data_structures" }

compiler/rustc_query_impl/src/lib.rs

+184-9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
44
// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
55
#![feature(const_mut_refs)]
6+
#![feature(const_refs_to_cell)]
67
#![feature(min_specialization)]
78
#![feature(never_type)]
89
#![feature(once_cell)]
910
#![feature(rustc_attrs)]
1011
#![recursion_limit = "256"]
11-
#![allow(rustc::potential_query_instability)]
12+
#![allow(rustc::potential_query_instability, unused_parens)]
1213
#![deny(rustc::untranslatable_diagnostic)]
1314
#![deny(rustc::diagnostic_outside_of_impl)]
1415

@@ -17,37 +18,211 @@ extern crate rustc_macros;
1718
#[macro_use]
1819
extern crate rustc_middle;
1920

20-
use rustc_data_structures::sync::AtomicU64;
21+
use memoffset::offset_of;
22+
use rustc_data_structures::fingerprint::Fingerprint;
23+
use rustc_data_structures::stable_hasher::HashStable;
2124
use rustc_middle::arena::Arena;
2225
use rustc_middle::dep_graph::{self, DepKindStruct};
2326
use rustc_middle::query::Key;
27+
use rustc_middle::ty::query::QueryCaches;
2428
use rustc_middle::ty::query::{
2529
query_keys, query_provided, query_provided_to_value, query_storage, query_values,
2630
};
27-
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
31+
use rustc_middle::ty::query::{Providers, QueryEngine};
2832
use rustc_middle::ty::TyCtxt;
33+
use rustc_query_system::dep_graph::DepNodeParams;
34+
use rustc_query_system::ich::StableHashingContext;
2935
use rustc_span::Span;
36+
use std::fmt;
37+
use std::marker::PhantomData;
3038

3139
#[macro_use]
3240
mod plumbing;
33-
pub use plumbing::QueryCtxt;
41+
pub use plumbing::{Queries, QueryCtxt};
3442
use rustc_query_system::query::*;
3543
#[cfg(parallel_compiler)]
3644
pub use rustc_query_system::query::{deadlock, QueryContext};
3745

3846
pub use rustc_query_system::query::QueryConfig;
47+
use rustc_query_system::HandleCycleError;
3948

4049
mod on_disk_cache;
4150
pub use on_disk_cache::OnDiskCache;
4251

4352
mod profiling_support;
4453
pub use self::profiling_support::alloc_self_profile_query_strings;
4554

46-
rustc_query_append! { define_queries! }
55+
trait Bool {
56+
fn value() -> bool;
57+
}
58+
59+
struct True;
60+
61+
impl Bool for True {
62+
fn value() -> bool {
63+
true
64+
}
65+
}
66+
struct False;
67+
68+
impl Bool for False {
69+
fn value() -> bool {
70+
false
71+
}
72+
}
73+
struct DynamicQuery<'tcx, C: QueryCache> {
74+
name: &'static str,
75+
cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
76+
execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
77+
compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
78+
try_load_from_disk:
79+
fn(qcx: QueryCtxt<'tcx>, idx: &C::Key) -> TryLoadFromDisk<QueryCtxt<'tcx>, C::Value>,
80+
query_state: usize,
81+
query_cache: usize,
82+
eval_always: bool,
83+
dep_kind: rustc_middle::dep_graph::DepKind,
84+
handle_cycle_error: HandleCycleError,
85+
hash_result: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
86+
}
87+
88+
struct DynamicConfig<'tcx, C: QueryCache, Anon, DepthLimit, Feedable> {
89+
dynamic: &'tcx DynamicQuery<'tcx, C>,
90+
data: PhantomData<(Anon, DepthLimit, Feedable)>,
91+
}
92+
93+
impl<'tcx, C: QueryCache, Anon, DepthLimit, Feedable> Copy
94+
for DynamicConfig<'tcx, C, Anon, DepthLimit, Feedable>
95+
{
96+
}
97+
impl<'tcx, C: QueryCache, Anon, DepthLimit, Feedable> Clone
98+
for DynamicConfig<'tcx, C, Anon, DepthLimit, Feedable>
99+
{
100+
fn clone(&self) -> Self {
101+
DynamicConfig { dynamic: self.dynamic, data: PhantomData }
102+
}
103+
}
104+
105+
impl<'tcx, C: QueryCache, Anon, DepthLimit, Feedable> fmt::Debug
106+
for DynamicConfig<'tcx, C, Anon, DepthLimit, Feedable>
107+
{
108+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109+
write!(f, "DynamicConfig<{}>", self.dynamic.name)
110+
}
111+
}
112+
113+
impl<'tcx, C: QueryCache, Anon: Bool, DepthLimit: Bool, Feedable: Bool> QueryConfig<QueryCtxt<'tcx>>
114+
for DynamicConfig<'tcx, C, Anon, DepthLimit, Feedable>
115+
where
116+
for<'a> C::Key: HashStable<StableHashingContext<'a>>,
117+
{
118+
type Key = C::Key;
119+
type Value = C::Value;
120+
type Cache = C;
121+
122+
#[inline(always)]
123+
fn name(self) -> &'static str {
124+
self.dynamic.name
125+
}
126+
127+
#[inline(always)]
128+
fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
129+
(self.dynamic.cache_on_disk)(tcx, key)
130+
}
131+
132+
#[inline(always)]
133+
fn query_state<'a>(
134+
self,
135+
tcx: QueryCtxt<'tcx>,
136+
) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
137+
where
138+
QueryCtxt<'tcx>: 'a,
139+
{
140+
unsafe {
141+
&*((&tcx.queries.query_states as *const QueryStates<'tcx> as *const u8)
142+
.offset(self.dynamic.query_state as isize) as *const _)
143+
}
144+
}
47145

48-
impl<'tcx> Queries<'tcx> {
49-
// Force codegen in the dyn-trait transformation in this crate.
50-
pub fn as_dyn(&'tcx self) -> &'tcx dyn QueryEngine<'tcx> {
51-
self
146+
#[inline(always)]
147+
fn query_cache<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
148+
where
149+
'tcx: 'a,
150+
{
151+
unsafe {
152+
&*((&tcx.query_system.caches as *const QueryCaches<'tcx> as *const u8)
153+
.offset(self.dynamic.query_cache as isize) as *const _)
154+
}
155+
}
156+
157+
#[inline(always)]
158+
fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
159+
(self.dynamic.execute_query)(tcx, key)
160+
}
161+
162+
#[inline(always)]
163+
fn compute(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
164+
(self.dynamic.compute)(tcx, key)
165+
}
166+
167+
#[inline(always)]
168+
fn try_load_from_disk(
169+
self,
170+
qcx: QueryCtxt<'tcx>,
171+
key: &Self::Key,
172+
) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self::Value> {
173+
(self.dynamic.try_load_from_disk)(qcx, key)
174+
}
175+
176+
#[inline(always)]
177+
fn anon(self) -> bool {
178+
Anon::value()
179+
}
180+
181+
#[inline(always)]
182+
fn eval_always(self) -> bool {
183+
self.dynamic.eval_always
184+
}
185+
186+
#[inline(always)]
187+
fn depth_limit(self) -> bool {
188+
DepthLimit::value()
189+
}
190+
191+
#[inline(always)]
192+
fn feedable(self) -> bool {
193+
Feedable::value()
194+
}
195+
196+
#[inline(always)]
197+
fn dep_kind(self) -> rustc_middle::dep_graph::DepKind {
198+
self.dynamic.dep_kind
199+
}
200+
201+
#[inline(always)]
202+
fn handle_cycle_error(self) -> rustc_query_system::HandleCycleError {
203+
self.dynamic.handle_cycle_error
204+
}
205+
206+
#[inline(always)]
207+
fn hash_result(self) -> rustc_query_system::query::HashResult<Self::Value> {
208+
self.dynamic.hash_result
52209
}
53210
}
211+
212+
trait QueryToConfig<'tcx>: 'tcx
213+
where
214+
for<'a> <Self::Cache as QueryCache>::Key: HashStable<StableHashingContext<'a>>,
215+
{
216+
type Cache: QueryCache;
217+
type Key: DepNodeParams<TyCtxt<'tcx>>;
218+
219+
type Anon: Bool;
220+
type DepthLimit: Bool;
221+
type Feedable: Bool;
222+
223+
fn config(
224+
qcx: QueryCtxt<'tcx>,
225+
) -> DynamicConfig<'tcx, Self::Cache, Self::Anon, Self::DepthLimit, Self::Feedable>;
226+
}
227+
228+
rustc_query_append! { define_queries! }

0 commit comments

Comments
 (0)