1 use crate::dep_graph
::DepNodeIndex
;
3 use rustc_data_structures
::fx
::FxHashMap
;
4 use rustc_data_structures
::sharded
;
5 #[cfg(parallel_compiler)]
6 use rustc_data_structures
::sharded
::Sharded
;
7 use rustc_data_structures
::sync
::Lock
;
8 use rustc_index
::vec
::{Idx, IndexVec}
;
11 use std
::marker
::PhantomData
;
13 pub trait CacheSelector
<'tcx
, V
> {
19 pub trait QueryStorage
{
23 pub trait QueryCache
: QueryStorage
+ Sized
{
24 type Key
: Hash
+ Eq
+ Copy
+ Debug
;
26 /// Checks if the query is already computed and in the cache.
27 /// It returns the shard index and a lock guard to the shard,
28 /// which will be used if the query is not in the cache and we need
30 fn lookup(&self, key
: &Self::Key
) -> Option
<(Self::Value
, DepNodeIndex
)>;
32 fn complete(&self, key
: Self::Key
, value
: Self::Value
, index
: DepNodeIndex
);
34 fn iter(&self, f
: &mut dyn FnMut(&Self::Key
, &Self::Value
, DepNodeIndex
));
37 pub struct DefaultCacheSelector
<K
>(PhantomData
<K
>);
39 impl<'tcx
, K
: Eq
+ Hash
, V
: 'tcx
> CacheSelector
<'tcx
, V
> for DefaultCacheSelector
<K
> {
40 type Cache
= DefaultCache
<K
, V
>
45 pub struct DefaultCache
<K
, V
> {
46 #[cfg(parallel_compiler)]
47 cache
: Sharded
<FxHashMap
<K
, (V
, DepNodeIndex
)>>,
48 #[cfg(not(parallel_compiler))]
49 cache
: Lock
<FxHashMap
<K
, (V
, DepNodeIndex
)>>,
52 impl<K
, V
> Default
for DefaultCache
<K
, V
> {
53 fn default() -> Self {
54 DefaultCache { cache: Default::default() }
58 impl<K
: Eq
+ Hash
, V
: Copy
+ Debug
> QueryStorage
for DefaultCache
<K
, V
> {
62 impl<K
, V
> QueryCache
for DefaultCache
<K
, V
>
64 K
: Eq
+ Hash
+ Copy
+ Debug
,
70 fn lookup(&self, key
: &K
) -> Option
<(V
, DepNodeIndex
)> {
71 let key_hash
= sharded
::make_hash(key
);
72 #[cfg(parallel_compiler)]
73 let lock
= self.cache
.get_shard_by_hash(key_hash
).lock();
74 #[cfg(not(parallel_compiler))]
75 let lock
= self.cache
.lock();
76 let result
= lock
.raw_entry().from_key_hashed_nocheck(key_hash
, key
);
78 if let Some((_
, value
)) = result { Some(*value) }
else { None }
82 fn complete(&self, key
: K
, value
: V
, index
: DepNodeIndex
) {
83 #[cfg(parallel_compiler)]
84 let mut lock
= self.cache
.get_shard_by_value(&key
).lock();
85 #[cfg(not(parallel_compiler))]
86 let mut lock
= self.cache
.lock();
87 // We may be overwriting another value. This is all right, since the dep-graph
88 // will check that the fingerprint matches.
89 lock
.insert(key
, (value
, index
));
92 fn iter(&self, f
: &mut dyn FnMut(&Self::Key
, &Self::Value
, DepNodeIndex
)) {
93 #[cfg(parallel_compiler)]
95 let shards
= self.cache
.lock_shards();
96 for shard
in shards
.iter() {
97 for (k
, v
) in shard
.iter() {
102 #[cfg(not(parallel_compiler))]
104 let map
= self.cache
.lock();
105 for (k
, v
) in map
.iter() {
112 pub struct SingleCacheSelector
;
114 impl<'tcx
, V
: 'tcx
> CacheSelector
<'tcx
, V
> for SingleCacheSelector
{
115 type Cache
= SingleCache
<V
>
120 pub struct SingleCache
<V
> {
121 cache
: Lock
<Option
<(V
, DepNodeIndex
)>>,
124 impl<V
> Default
for SingleCache
<V
> {
125 fn default() -> Self {
126 SingleCache { cache: Lock::new(None) }
130 impl<V
: Copy
+ Debug
> QueryStorage
for SingleCache
<V
> {
134 impl<V
> QueryCache
for SingleCache
<V
>
141 fn lookup(&self, _key
: &()) -> Option
<(V
, DepNodeIndex
)> {
146 fn complete(&self, _key
: (), value
: V
, index
: DepNodeIndex
) {
147 *self.cache
.lock() = Some((value
, index
));
150 fn iter(&self, f
: &mut dyn FnMut(&Self::Key
, &Self::Value
, DepNodeIndex
)) {
151 self.cache
.lock().as_ref().map(|value
| f(&(), &value
.0, value
.1));
155 pub struct VecCacheSelector
<K
>(PhantomData
<K
>);
157 impl<'tcx
, K
: Idx
, V
: 'tcx
> CacheSelector
<'tcx
, V
> for VecCacheSelector
<K
> {
158 type Cache
= VecCache
<K
, V
>
163 pub struct VecCache
<K
: Idx
, V
> {
164 #[cfg(parallel_compiler)]
165 cache
: Sharded
<IndexVec
<K
, Option
<(V
, DepNodeIndex
)>>>,
166 #[cfg(not(parallel_compiler))]
167 cache
: Lock
<IndexVec
<K
, Option
<(V
, DepNodeIndex
)>>>,
170 impl<K
: Idx
, V
> Default
for VecCache
<K
, V
> {
171 fn default() -> Self {
172 VecCache { cache: Default::default() }
176 impl<K
: Eq
+ Idx
, V
: Copy
+ Debug
> QueryStorage
for VecCache
<K
, V
> {
180 impl<K
, V
> QueryCache
for VecCache
<K
, V
>
182 K
: Eq
+ Idx
+ Copy
+ Debug
,
188 fn lookup(&self, key
: &K
) -> Option
<(V
, DepNodeIndex
)> {
189 #[cfg(parallel_compiler)]
190 let lock
= self.cache
.get_shard_by_hash(key
.index() as u64).lock();
191 #[cfg(not(parallel_compiler))]
192 let lock
= self.cache
.lock();
193 if let Some(Some(value
)) = lock
.get(*key
) { Some(*value) }
else { None }
197 fn complete(&self, key
: K
, value
: V
, index
: DepNodeIndex
) {
198 #[cfg(parallel_compiler)]
199 let mut lock
= self.cache
.get_shard_by_hash(key
.index() as u64).lock();
200 #[cfg(not(parallel_compiler))]
201 let mut lock
= self.cache
.lock();
202 lock
.insert(key
, (value
, index
));
205 fn iter(&self, f
: &mut dyn FnMut(&Self::Key
, &Self::Value
, DepNodeIndex
)) {
206 #[cfg(parallel_compiler)]
208 let shards
= self.cache
.lock_shards();
209 for shard
in shards
.iter() {
210 for (k
, v
) in shard
.iter_enumerated() {
217 #[cfg(not(parallel_compiler))]
219 let map
= self.cache
.lock();
220 for (k
, v
) in map
.iter_enumerated() {