use crate::dep_graph::DepNodeIndex;
-use crate::query::plumbing::{QueryCacheStore, QueryLookup};
use rustc_arena::TypedArena;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sharded::Sharded;
+use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::sync::WorkerLocal;
use std::default::Default;
use std::fmt::Debug;
pub trait QueryCache: QueryStorage + Sized {
type Key: Hash + Eq + Clone + Debug;
- type Sharded: Default;
/// Checks if the query is already computed and in the cache.
/// It returns the shard index and a lock guard to the shard,
/// which will be used if the query is not in the cache and we need
/// to compute it.
- fn lookup<'s, R, OnHit>(
+ fn lookup<R, OnHit>(
&self,
- state: &'s QueryCacheStore<Self>,
key: &Self::Key,
// `on_hit` can be called while holding a lock to the query state shard.
on_hit: OnHit,
- ) -> Result<R, QueryLookup>
+ ) -> Result<R, ()>
where
OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R;
- fn complete(
- &self,
- lock_sharded_storage: &mut Self::Sharded,
- key: Self::Key,
- value: Self::Value,
- index: DepNodeIndex,
- ) -> Self::Stored;
+ fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
- fn iter(
- &self,
- shards: &Sharded<Self::Sharded>,
- f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
- );
+ fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
}
pub struct DefaultCacheSelector;
type Cache = DefaultCache<K, V>;
}
-pub struct DefaultCache<K, V>(PhantomData<(K, V)>);
+pub struct DefaultCache<K, V> {
+ shards: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
+}
impl<K, V> Default for DefaultCache<K, V> {
fn default() -> Self {
- DefaultCache(PhantomData)
+ DefaultCache { shards: Default::default() }
}
}
V: Clone + Debug,
{
type Key = K;
- type Sharded = FxHashMap<K, (V, DepNodeIndex)>;
#[inline(always)]
- fn lookup<'s, R, OnHit>(
- &self,
- state: &'s QueryCacheStore<Self>,
- key: &K,
- on_hit: OnHit,
- ) -> Result<R, QueryLookup>
+ fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
where
OnHit: FnOnce(&V, DepNodeIndex) -> R,
{
- let (lookup, lock) = state.get_lookup(key);
- let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key);
+ let key_hash = sharded::make_hash(key);
+ let shard = sharded::get_shard_index_by_hash(key_hash);
+ let lock = self.shards.get_shard_by_index(shard).lock();
+ let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
if let Some((_, value)) = result {
let hit_result = on_hit(&value.0, value.1);
Ok(hit_result)
} else {
- Err(lookup)
+ Err(())
}
}
#[inline]
- fn complete(
- &self,
- lock_sharded_storage: &mut Self::Sharded,
- key: K,
- value: V,
- index: DepNodeIndex,
- ) -> Self::Stored {
- lock_sharded_storage.insert(key, (value.clone(), index));
+ fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+ self.shards.get_shard_by_value(&key).lock().insert(key, (value.clone(), index));
value
}
- fn iter(
- &self,
- shards: &Sharded<Self::Sharded>,
- f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
- ) {
- let shards = shards.lock_shards();
+ fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+ let shards = self.shards.lock_shards();
for shard in shards.iter() {
for (k, v) in shard.iter() {
f(k, &v.0, v.1);
pub struct ArenaCache<'tcx, K, V> {
arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
- phantom: PhantomData<(K, &'tcx V)>,
+ shards: Sharded<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
}
impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
fn default() -> Self {
- ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), phantom: PhantomData }
+ ArenaCache {
+ arena: WorkerLocal::new(|_| TypedArena::default()),
+ shards: Default::default(),
+ }
}
}
V: Debug,
{
type Key = K;
- type Sharded = FxHashMap<K, &'tcx (V, DepNodeIndex)>;
#[inline(always)]
- fn lookup<'s, R, OnHit>(
- &self,
- state: &'s QueryCacheStore<Self>,
- key: &K,
- on_hit: OnHit,
- ) -> Result<R, QueryLookup>
+ fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
where
OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
{
- let (lookup, lock) = state.get_lookup(key);
- let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key);
+ let key_hash = sharded::make_hash(key);
+ let shard = sharded::get_shard_index_by_hash(key_hash);
+ let lock = self.shards.get_shard_by_index(shard).lock();
+ let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
if let Some((_, value)) = result {
let hit_result = on_hit(&&value.0, value.1);
Ok(hit_result)
} else {
- Err(lookup)
+ Err(())
}
}
#[inline]
- fn complete(
- &self,
- lock_sharded_storage: &mut Self::Sharded,
- key: K,
- value: V,
- index: DepNodeIndex,
- ) -> Self::Stored {
+ fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
let value = self.arena.alloc((value, index));
let value = unsafe { &*(value as *const _) };
- lock_sharded_storage.insert(key, value);
+ self.shards.get_shard_by_value(&key).lock().insert(key, value);
&value.0
}
- fn iter(
- &self,
- shards: &Sharded<Self::Sharded>,
- f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
- ) {
- let shards = shards.lock_shards();
+ fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+ let shards = self.shards.lock_shards();
for shard in shards.iter() {
for (k, v) in shard.iter() {
f(k, &v.0, v.1);