use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use crate::ich::StableHashingContext; use crate::mir::{Mir, BasicBlock}; use crate::rustc_serialize as serialize; #[derive(Clone, Debug)] pub struct Cache { predecessors: RwLock>>> } impl serialize::Encodable for Cache { fn encode(&self, s: &mut S) -> Result<(), S::Error> { serialize::Encodable::encode(&(), s) } } impl serialize::Decodable for Cache { fn decode(d: &mut D) -> Result { serialize::Decodable::decode(d).map(|_v: ()| Self::new()) } } impl<'a> HashStable> for Cache { fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { // do nothing } } impl Cache { pub fn new() -> Self { Cache { predecessors: RwLock::new(None) } } pub fn invalidate(&self) { // FIXME: consider being more fine-grained *self.predecessors.borrow_mut() = None; } pub fn predecessors( &self, mir: &Mir<'_> ) -> MappedReadGuard<'_, IndexVec>> { if self.predecessors.borrow().is_none() { *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir)); } ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap()) } } fn calculate_predecessors(mir: &Mir<'_>) -> IndexVec> { let mut result = IndexVec::from_elem(vec![], mir.basic_blocks()); for (bb, data) in mir.basic_blocks().iter_enumerated() { if let Some(ref term) = data.terminator { for &tgt in term.successors() { result[tgt].push(bb); } } } result } CloneTypeFoldableAndLiftImpls! { Cache, }