From e8ef41e83f34e7de8d0f7abf5034f2e19e98edba Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 27 Mar 2020 18:41:13 +0100 Subject: [PATCH] Allow the QueryCache to specify storage. --- src/librustc_middle/ty/query/plumbing.rs | 14 +++++-- src/librustc_query_system/query/caches.rs | 36 ++++++++++++----- src/librustc_query_system/query/config.rs | 5 ++- src/librustc_query_system/query/mod.rs | 2 +- src/librustc_query_system/query/plumbing.rs | 44 ++++++++++----------- 5 files changed, 62 insertions(+), 39 deletions(-) diff --git a/src/librustc_middle/ty/query/plumbing.rs b/src/librustc_middle/ty/query/plumbing.rs index 068322b08b7..a9367dc40b7 100644 --- a/src/librustc_middle/ty/query/plumbing.rs +++ b/src/librustc_middle/ty/query/plumbing.rs @@ -328,6 +328,10 @@ pub struct $name<$tcx> { $(impl<$tcx> QueryConfig> for queries::$name<$tcx> { type Key = $($K)*; type Value = $V; + type Stored = < + query_storage!([$($modifiers)*][$($K)*, $V]) + as QueryStorage + >::Stored; const NAME: &'static str = stringify!($name); const CATEGORY: ProfileCategory = $category; } @@ -426,8 +430,10 @@ pub fn at(self, span: Span) -> TyCtxtAt<$tcx> { $($(#[$attr])* #[inline(always)] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { - self.at(DUMMY_SP).$name(key) + pub fn $name(self, key: query_helper_param_ty!($($K)*)) + -> as QueryConfig>>::Stored + { + self.at(DUMMY_SP).$name(key.into_query_param()) })* /// All self-profiling events generated by the query engine use @@ -463,7 +469,9 @@ pub fn alloc_self_profile_query_strings(self) { impl TyCtxtAt<$tcx> { $($(#[$attr])* #[inline(always)] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { + pub fn $name(self, key: query_helper_param_ty!($($K)*)) + -> as QueryConfig>>::Stored + { get_query::, _>(self.tcx, self.span, key.into_query_param()) })* } diff --git a/src/librustc_query_system/query/caches.rs b/src/librustc_query_system/query/caches.rs index 0c0335ba04f..7b9d75037c2 100644 --- a/src/librustc_query_system/query/caches.rs +++ b/src/librustc_query_system/query/caches.rs @@ -8,13 +8,21 @@ use std::hash::Hash; use std::marker::PhantomData; -pub trait CacheSelector { - type Cache: QueryCache; +pub trait CacheSelector { + type Cache; } -pub trait QueryCache: Default { - type Key: Hash; +pub trait QueryStorage: Default { type Value; + type Stored: Clone; + + /// Store a value without putting it in the cache. + /// This is meant to be used with cycle errors. + fn store_nocache(&self, value: Self::Value) -> Self::Stored; +} + +pub trait QueryCache: QueryStorage { + type Key: Hash; type Sharded: Default; /// Checks if the query is already computed and in the cache. @@ -30,7 +38,7 @@ fn lookup( on_miss: OnMiss, ) -> R where - OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R, + OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R, OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R; fn complete( @@ -40,7 +48,7 @@ fn complete( key: Self::Key, value: Self::Value, index: DepNodeIndex, - ); + ) -> Self::Stored; fn iter( &self, @@ -66,9 +74,18 @@ fn default() -> Self { } } +impl QueryStorage for DefaultCache { + type Value = V; + type Stored = V; + + fn store_nocache(&self, value: Self::Value) -> Self::Stored { + // We have no dedicated storage + value + } +} + impl QueryCache for DefaultCache { type Key = K; - type Value = V; type Sharded = FxHashMap; #[inline(always)] @@ -99,8 +116,9 @@ fn complete( key: K, value: V, index: DepNodeIndex, - ) { - lock_sharded_storage.insert(key, (value, index)); + ) -> Self::Stored { + lock_sharded_storage.insert(key, (value.clone(), index)); + value } fn iter( diff --git a/src/librustc_query_system/query/config.rs b/src/librustc_query_system/query/config.rs index 06e3302b263..710ec3bfb0b 100644 --- a/src/librustc_query_system/query/config.rs +++ b/src/librustc_query_system/query/config.rs @@ -20,7 +20,8 @@ pub trait QueryConfig { const CATEGORY: ProfileCategory; type Key: Eq + Hash + Clone + Debug; - type Value: Clone; + type Value; + type Stored: Clone; } pub trait QueryAccessors: QueryConfig { @@ -28,7 +29,7 @@ pub trait QueryAccessors: QueryConfig { const EVAL_ALWAYS: bool; const DEP_KIND: CTX::DepKind; - type Cache: QueryCache; + type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt fn query_state<'a>(tcx: CTX) -> &'a QueryState; diff --git a/src/librustc_query_system/query/mod.rs b/src/librustc_query_system/query/mod.rs index b1677c5c93d..83513b7e11d 100644 --- a/src/librustc_query_system/query/mod.rs +++ b/src/librustc_query_system/query/mod.rs @@ -7,7 +7,7 @@ pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; mod caches; -pub use self::caches::{CacheSelector, DefaultCacheSelector, QueryCache}; +pub use self::caches::{CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage}; mod config; pub use self::config::{QueryAccessors, QueryConfig, QueryDescription}; diff --git a/src/librustc_query_system/query/plumbing.rs b/src/librustc_query_system/query/plumbing.rs index 9da13f23664..0aeec269e61 100644 --- a/src/librustc_query_system/query/plumbing.rs +++ b/src/librustc_query_system/query/plumbing.rs @@ -148,7 +148,6 @@ struct JobOwner<'tcx, CTX: QueryContext, C> where C: QueryCache, C::Key: Eq + Hash + Clone + Debug, - C::Value: Clone, { state: &'tcx QueryState, key: C::Key, @@ -159,7 +158,6 @@ impl<'tcx, CTX: QueryContext, C> JobOwner<'tcx, CTX, C> where C: QueryCache, C::Key: Eq + Hash + Clone + Debug, - C::Value: Clone, { /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. @@ -177,7 +175,7 @@ fn try_start<'a, 'b, Q>( mut lookup: QueryLookup<'a, CTX, C::Key, C::Sharded>, ) -> TryGetJob<'b, CTX, C> where - Q: QueryDescription, + Q: QueryDescription, CTX: QueryContext, { let lock = &mut *lookup.lock; @@ -229,7 +227,8 @@ fn try_start<'a, 'b, Q>( // so we just return the error. #[cfg(not(parallel_compiler))] return TryGetJob::Cycle(cold_path(|| { - Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span)) + let value = Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span)); + Q::query_state(tcx).cache.store_nocache(value) })); // With parallel queries we might just have to wait on some other @@ -239,7 +238,9 @@ fn try_start<'a, 'b, Q>( let result = latch.wait_on(tcx, span); if let Err(cycle) = result { - return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); + let value = Q::handle_cycle_error(tcx, cycle); + let value = Q::query_state(tcx).cache.store_nocache(value); + return TryGetJob::Cycle(value); } let cached = try_get_cached( @@ -261,7 +262,7 @@ fn try_start<'a, 'b, Q>( /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query #[inline(always)] - fn complete(self, tcx: CTX, result: &C::Value, dep_node_index: DepNodeIndex) { + fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; let state = self.state; @@ -269,18 +270,18 @@ fn complete(self, tcx: CTX, result: &C::Value, dep_node_index: DepNodeIndex) { // Forget ourself so our destructor won't poison the query mem::forget(self); - let job = { - let result = result.clone(); + let (job, result) = { let mut lock = state.shards.get_shard_by_value(&key).lock(); let job = match lock.active.remove(&key).unwrap() { QueryResult::Started(job) => job, QueryResult::Poisoned => panic!(), }; - state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index); - job + let result = state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index); + (job, result) }; job.signal_complete(); + result } } @@ -297,7 +298,6 @@ fn with_diagnostics(f: F) -> (R, ThinVec) impl<'tcx, CTX: QueryContext, C: QueryCache> Drop for JobOwner<'tcx, CTX, C> where C::Key: Eq + Hash + Clone + Debug, - C::Value: Clone, { #[inline(never)] #[cold] @@ -331,7 +331,6 @@ pub struct CycleError { enum TryGetJob<'tcx, CTX: QueryContext, C: QueryCache> where C::Key: Eq + Hash + Clone + Debug, - C::Value: Clone, { /// The query is not yet started. Contains a guard to the cache eventually used to start it. NotYetStarted(JobOwner<'tcx, CTX, C>), @@ -340,10 +339,10 @@ enum TryGetJob<'tcx, CTX: QueryContext, C: QueryCache> /// Returns the result of the query and its dep-node index /// if it succeeded or a cycle error if it failed. #[cfg(parallel_compiler)] - JobCompleted((C::Value, DepNodeIndex)), + JobCompleted((C::Stored, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. - Cycle(C::Value), + Cycle(C::Stored), } /// Checks if the query is already computed and in the cache. @@ -362,7 +361,7 @@ fn try_get_cached( where C: QueryCache, CTX: QueryContext, - OnHit: FnOnce(&C::Value, DepNodeIndex) -> R, + OnHit: FnOnce(&C::Stored, DepNodeIndex) -> R, OnMiss: FnOnce(C::Key, QueryLookup<'_, CTX, C::Key, C::Sharded>) -> R, { state.cache.lookup( @@ -388,7 +387,7 @@ fn try_execute_query( span: Span, key: Q::Key, lookup: QueryLookup<'_, CTX, Q::Key, ::Sharded>, -) -> Q::Value +) -> Q::Stored where Q: QueryDescription, CTX: QueryContext, @@ -427,9 +426,7 @@ fn try_execute_query( tcx.store_diagnostics_for_anon_node(dep_node_index, diagnostics); } - job.complete(tcx, &result, dep_node_index); - - return result; + return job.complete(tcx, result, dep_node_index); } let dep_node = Q::to_dep_node(tcx, &key); @@ -454,8 +451,7 @@ fn try_execute_query( }) }); if let Some((result, dep_node_index)) = loaded { - job.complete(tcx, &result, dep_node_index); - return result; + return job.complete(tcx, result, dep_node_index); } } @@ -558,7 +554,7 @@ fn force_query_with_job( key: Q::Key, job: JobOwner<'_, CTX, Q::Cache>, dep_node: DepNode, -) -> (Q::Value, DepNodeIndex) +) -> (Q::Stored, DepNodeIndex) where Q: QueryDescription, CTX: QueryContext, @@ -603,13 +599,13 @@ fn force_query_with_job( } } - job.complete(tcx, &result, dep_node_index); + let result = job.complete(tcx, result, dep_node_index); (result, dep_node_index) } #[inline(never)] -pub fn get_query(tcx: CTX, span: Span, key: Q::Key) -> Q::Value +pub fn get_query(tcx: CTX, span: Span, key: Q::Key) -> Q::Stored where Q: QueryDescription, CTX: QueryContext,