summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_query_impl
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_query_impl')
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_impl/src/lib.rs15
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs42
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs197
4 files changed, 182 insertions, 74 deletions
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 3e8a88c7e..b107a3f03 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -16,7 +16,7 @@ rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_query_system = { path = "../rustc_query_system" }
-rustc-rayon-core = { version = "0.4.0", optional = true }
+rustc-rayon-core = { version = "0.5.0", optional = true }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index d7708a3bc..7001a1eed 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -5,7 +5,6 @@
#![feature(const_mut_refs)]
#![feature(min_specialization)]
#![feature(never_type)]
-#![feature(once_cell)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
@@ -19,13 +18,16 @@ extern crate rustc_middle;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
-use rustc_middle::dep_graph::{self, DepKindStruct};
-use rustc_middle::query::Key;
+use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
+use rustc_middle::query::erase::{erase, restore, Erase};
+use rustc_middle::query::AsLocalKey;
use rustc_middle::ty::query::{
query_keys, query_provided, query_provided_to_value, query_storage, query_values,
};
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
use rustc_middle::ty::TyCtxt;
+use rustc_query_system::dep_graph::SerializedDepNodeIndex;
+use rustc_query_system::Value;
use rustc_span::Span;
#[macro_use]
@@ -43,6 +45,13 @@ pub use on_disk_cache::OnDiskCache;
mod profiling_support;
pub use self::profiling_support::alloc_self_profile_query_strings;
+/// This is implemented per query and restoring query values from their erased state.
+trait QueryConfigRestored<'tcx>: QueryConfig<QueryCtxt<'tcx>> + Default {
+ type RestoredValue;
+
+ fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue;
+}
+
rustc_query_append! { define_queries! }
impl<'tcx> Queries<'tcx> {
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 46e34462c..30477c7bd 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::{self, interpret};
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext;
-use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
+use rustc_query_system::query::{QueryCache, QuerySideEffects};
use rustc_serialize::{
opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
Decodable, Decoder, Encodable, Encoder,
@@ -388,6 +388,12 @@ impl<'sess> OnDiskCache<'sess> {
debug_assert!(prev.is_none());
}
+ /// Return whether the cached query result can be decoded.
+ pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool {
+ self.query_result_index.contains_key(&dep_node_index)
+ // with_decoder is infallible, so we can stop here
+ }
+
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
@@ -398,7 +404,9 @@ impl<'sess> OnDiskCache<'sess> {
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
- self.load_indexed(tcx, dep_node_index, &self.query_result_index)
+ let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index);
+ debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index));
+ opt_value
}
/// Stores side effect emitted during computation of an anonymous query.
@@ -428,8 +436,8 @@ impl<'sess> OnDiskCache<'sess> {
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
let pos = index.get(&dep_node_index).cloned()?;
-
- self.with_decoder(tcx, pos, |decoder| Some(decode_tagged(decoder, dep_node_index)))
+ let value = self.with_decoder(tcx, pos, |decoder| decode_tagged(decoder, dep_node_index));
+ Some(value)
}
fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(
@@ -1038,8 +1046,6 @@ impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
emit_i8(i8);
emit_bool(bool);
- emit_f64(f64);
- emit_f32(f32);
emit_char(char);
emit_str(&str);
emit_raw_bytes(&[u8]);
@@ -1056,24 +1062,24 @@ impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for [u8] {
}
}
-pub fn encode_query_results<'a, 'tcx, CTX, Q>(
- tcx: CTX,
+pub(crate) fn encode_query_results<'a, 'tcx, Q>(
+ query: Q,
+ qcx: QueryCtxt<'tcx>,
encoder: &mut CacheEncoder<'a, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex,
) where
- CTX: QueryContext + 'tcx,
- Q: super::QueryConfig<CTX>,
- Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
+ Q: super::QueryConfigRestored<'tcx>,
+ Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
{
- let _timer = tcx
- .dep_context()
+ let _timer = qcx
+ .tcx
.profiler()
- .verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::<Q>());
+ .verbose_generic_activity_with_arg("encode_query_results_for", query.name());
- assert!(Q::query_state(tcx).all_inactive());
- let cache = Q::query_cache(tcx);
+ assert!(query.query_state(qcx).all_inactive());
+ let cache = query.query_cache(qcx);
cache.iter(&mut |key, value, dep_node| {
- if Q::cache_on_disk(*tcx.dep_context(), &key) {
+ if query.cache_on_disk(qcx.tcx, &key) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
// Record position of the cache entry.
@@ -1081,7 +1087,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
// Encode the type check tables with the `SerializedDepNodeIndex`
// as tag.
- encoder.encode_tagged(dep_node, value);
+ encoder.encode_tagged(dep_node, &Q::restore(*value));
}
});
}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index a8592bd70..afbead7d1 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -19,7 +19,7 @@ use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
};
-use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value};
+use rustc_query_system::{LayoutOfDepth, QueryOverflow};
use rustc_serialize::Decodable;
use rustc_session::Limit;
use rustc_span::def_id::LOCAL_CRATE;
@@ -263,30 +263,30 @@ macro_rules! feedable {
}
macro_rules! hash_result {
- ([]) => {{
- Some(dep_graph::hash_result)
+ ([][$V:ty]) => {{
+ Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
}};
- ([(no_hash) $($rest:tt)*]) => {{
+ ([(no_hash) $($rest:tt)*][$V:ty]) => {{
None
}};
- ([$other:tt $($modifiers:tt)*]) => {
- hash_result!([$($modifiers)*])
+ ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+ hash_result!([$($modifiers)*][$($args)*])
};
}
-macro_rules! get_provider {
- ([][$tcx:expr, $name:ident, $key:expr]) => {{
- $tcx.queries.local_providers.$name
+macro_rules! call_provider {
+ ([][$qcx:expr, $name:ident, $key:expr]) => {{
+ ($qcx.queries.local_providers.$name)($qcx.tcx, $key)
}};
- ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
- if $key.query_crate_is_local() {
- $tcx.queries.local_providers.$name
+ ([(separate_provide_extern) $($rest:tt)*][$qcx:expr, $name:ident, $key:expr]) => {{
+ if let Some(key) = $key.as_local_key() {
+ ($qcx.queries.local_providers.$name)($qcx.tcx, key)
} else {
- $tcx.queries.extern_providers.$name
+ ($qcx.queries.extern_providers.$name)($qcx.tcx, $key)
}
}};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
- get_provider!([$($modifiers)*][$($args)*])
+ call_provider!([$($modifiers)*][$($args)*])
};
}
@@ -350,18 +350,25 @@ pub(crate) fn create_query_frame<
QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
}
-fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
+fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
where
Q: QueryConfig<QueryCtxt<'tcx>>,
- Q::Key: DepNodeParams<TyCtxt<'tcx>>,
{
debug_assert!(tcx.dep_graph.is_green(&dep_node));
let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
});
- if Q::cache_on_disk(tcx, &key) {
- let _ = Q::execute_query(tcx, key);
+ if query.cache_on_disk(tcx, &key) {
+ let _ = query.execute_query(tcx, key);
+ }
+}
+
+pub(crate) fn loadable_from_disk<'tcx>(tcx: QueryCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
+ if let Some(cache) = tcx.on_disk_cache().as_ref() {
+ cache.loadable_from_disk(id)
+ } else {
+ false
}
}
@@ -375,11 +382,9 @@ where
tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
}
-fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
+fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
where
Q: QueryConfig<QueryCtxt<'tcx>>,
- Q::Key: DepNodeParams<TyCtxt<'tcx>>,
- Q::Value: Value<TyCtxt<'tcx>, DepKind>,
{
// We must avoid ever having to call `force_from_dep_node()` for a
// `DepNode::codegen_unit`:
@@ -403,7 +408,7 @@ where
#[cfg(debug_assertions)]
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
let tcx = QueryCtxt::from_tcx(tcx);
- force_query::<Q, _, DepKind>(tcx, key, dep_node);
+ force_query(query, tcx, key, dep_node);
true
} else {
false
@@ -412,7 +417,7 @@ where
pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
where
- Q: QueryConfig<QueryCtxt<'tcx>>,
+ Q: QueryConfig<QueryCtxt<'tcx>> + Default,
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
{
let fingerprint_style = Q::Key::fingerprint_style();
@@ -431,8 +436,10 @@ where
is_anon,
is_eval_always,
fingerprint_style,
- force_from_dep_node: Some(force_from_dep_node::<Q>),
- try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::<Q>),
+ force_from_dep_node: Some(|tcx, dep_node| force_from_dep_node(Q::default(), tcx, dep_node)),
+ try_load_from_on_disk_cache: Some(|tcx, dep_node| {
+ try_load_from_on_disk_cache(Q::default(), tcx, dep_node)
+ }),
}
}
@@ -462,54 +469,70 @@ macro_rules! define_queries {
mod queries {
use std::marker::PhantomData;
- $(pub struct $name<'tcx> {
- data: PhantomData<&'tcx ()>
- })*
+ $(
+ #[derive(Copy, Clone, Default)]
+ pub struct $name<'tcx> {
+ data: PhantomData<&'tcx ()>
+ }
+ )*
}
$(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
type Key = query_keys::$name<'tcx>;
- type Value = query_values::$name<'tcx>;
- const NAME: &'static str = stringify!($name);
+ type Value = Erase<query_values::$name<'tcx>>;
+
+ #[inline(always)]
+ fn name(self) -> &'static str {
+ stringify!($name)
+ }
+
+ #[inline]
+ fn format_value(self) -> fn(&Self::Value) -> String {
+ |value| format!("{:?}", restore::<query_values::$name<'tcx>>(*value))
+ }
#[inline]
- fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
+ fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
::rustc_middle::query::cached::$name(tcx, key)
}
type Cache = query_storage::$name<'tcx>;
#[inline(always)]
- fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
+ fn query_state<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
where QueryCtxt<'tcx>: 'a
{
&tcx.queries.$name
}
#[inline(always)]
- fn query_cache<'a>(tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
+ fn query_cache<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
where 'tcx:'a
{
&tcx.query_system.caches.$name
}
- fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
- tcx.$name(key)
+ fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
+ erase(tcx.$name(key))
}
#[inline]
#[allow(unused_variables)]
- fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
+ fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
query_provided_to_value::$name(
qcx.tcx,
- get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
+ call_provider!([$($modifiers)*][qcx, $name, key])
)
}
#[inline]
- fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
+ fn try_load_from_disk(
+ self,
+ _qcx: QueryCtxt<'tcx>,
+ _key: &Self::Key
+ ) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self::Value> {
should_ever_cache_on_disk!([$($modifiers)*] {
- if Self::cache_on_disk(_qcx.tcx, _key) {
+ if ::rustc_middle::query::cached::$name(_qcx.tcx, _key) {
Some(|qcx: QueryCtxt<'tcx>, dep_node| {
let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
qcx,
@@ -525,15 +548,74 @@ macro_rules! define_queries {
})
}
- const ANON: bool = is_anon!([$($modifiers)*]);
- const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
- const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]);
- const FEEDABLE: bool = feedable!([$($modifiers)*]);
+ #[inline]
+ fn loadable_from_disk(
+ self,
+ _qcx: QueryCtxt<'tcx>,
+ _key: &Self::Key,
+ _index: SerializedDepNodeIndex,
+ ) -> bool {
+ should_ever_cache_on_disk!([$($modifiers)*] {
+ self.cache_on_disk(_qcx.tcx, _key) &&
+ $crate::plumbing::loadable_from_disk(_qcx, _index)
+ } {
+ false
+ })
+ }
+
+ #[inline]
+ fn value_from_cycle_error(
+ self,
+ tcx: TyCtxt<'tcx>,
+ cycle: &[QueryInfo<DepKind>],
+ ) -> Self::Value {
+ let result: query_values::$name<'tcx> = Value::from_cycle_error(tcx, cycle);
+ erase(result)
+ }
+
+ #[inline(always)]
+ fn anon(self) -> bool {
+ is_anon!([$($modifiers)*])
+ }
+
+ #[inline(always)]
+ fn eval_always(self) -> bool {
+ is_eval_always!([$($modifiers)*])
+ }
+
+ #[inline(always)]
+ fn depth_limit(self) -> bool {
+ depth_limit!([$($modifiers)*])
+ }
+
+ #[inline(always)]
+ fn feedable(self) -> bool {
+ feedable!([$($modifiers)*])
+ }
+
+ #[inline(always)]
+ fn dep_kind(self) -> rustc_middle::dep_graph::DepKind {
+ dep_graph::DepKind::$name
+ }
+
+ #[inline(always)]
+ fn handle_cycle_error(self) -> rustc_query_system::HandleCycleError {
+ handle_cycle_error!([$($modifiers)*])
+ }
+
+ #[inline(always)]
+ fn hash_result(self) -> rustc_query_system::query::HashResult<Self::Value> {
+ hash_result!([$($modifiers)*][query_values::$name<'tcx>])
+ }
+ })*
- const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name;
- const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]);
+ $(impl<'tcx> QueryConfigRestored<'tcx> for queries::$name<'tcx> {
+ type RestoredValue = query_values::$name<'tcx>;
- const HASH_RESULT: rustc_query_system::query::HashResult<QueryCtxt<'tcx>, Self> = hash_result!([$($modifiers)*]);
+ #[inline(always)]
+ fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
+ restore::<query_values::$name<'tcx>>(value)
+ }
})*
#[allow(nonstandard_style)]
@@ -649,8 +731,13 @@ macro_rules! define_queries {
string_cache,
)
},
- encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
- $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
+ encode_query_results: expand_if_cached!([$($modifiers)*], |qcx, encoder, query_result_index|
+ $crate::on_disk_cache::encode_query_results::<super::queries::$name<'tcx>>(
+ super::queries::$name::default(),
+ qcx,
+ encoder,
+ query_result_index,
+ )
),
}})*
}
@@ -730,16 +817,22 @@ macro_rules! define_queries_struct {
$($(#[$attr])*
#[inline(always)]
- #[tracing::instrument(level = "trace", skip(self, tcx), ret)]
+ #[tracing::instrument(level = "trace", skip(self, tcx))]
fn $name(
&'tcx self,
tcx: TyCtxt<'tcx>,
span: Span,
- key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
+ key: query_keys::$name<'tcx>,
mode: QueryMode,
- ) -> Option<query_values::$name<'tcx>> {
+ ) -> Option<Erase<query_values::$name<'tcx>>> {
let qcx = QueryCtxt { tcx, queries: self };
- get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)
+ get_query(
+ queries::$name::default(),
+ qcx,
+ span,
+ key,
+ mode
+ )
})*
}
};