]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/cache.rs
Rollup merge of #61273 - RalfJung:maybe-uninit, r=Centril
[rust.git] / src / librustc / mir / cache.rs
1 use rustc_data_structures::indexed_vec::IndexVec;
2 use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard};
3 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
4                                            StableHasherResult};
5 use crate::ich::StableHashingContext;
6 use crate::mir::{Body, BasicBlock};
7
8 use crate::rustc_serialize as serialize;
9
10 #[derive(Clone, Debug)]
11 pub struct Cache {
12     predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
13 }
14
15
16 impl serialize::Encodable for Cache {
17     fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
18         serialize::Encodable::encode(&(), s)
19     }
20 }
21
22 impl serialize::Decodable for Cache {
23     fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
24         serialize::Decodable::decode(d).map(|_v: ()| Self::new())
25     }
26 }
27
28 impl<'a> HashStable<StableHashingContext<'a>> for Cache {
29     fn hash_stable<W: StableHasherResult>(&self,
30                                           _: &mut StableHashingContext<'a>,
31                                           _: &mut StableHasher<W>) {
32         // do nothing
33     }
34 }
35
36 impl Cache {
37     pub fn new() -> Self {
38         Cache {
39             predecessors: RwLock::new(None)
40         }
41     }
42
43     pub fn invalidate(&self) {
44         // FIXME: consider being more fine-grained
45         *self.predecessors.borrow_mut() = None;
46     }
47
48     pub fn predecessors(
49         &self,
50         mir: &Body<'_>
51     ) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
52         if self.predecessors.borrow().is_none() {
53             *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
54         }
55
56         ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
57     }
58 }
59
60 fn calculate_predecessors(mir: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
61     let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
62     for (bb, data) in mir.basic_blocks().iter_enumerated() {
63         if let Some(ref term) = data.terminator {
64             for &tgt in term.successors() {
65                 result[tgt].push(bb);
66             }
67         }
68     }
69
70     result
71 }
72
73 CloneTypeFoldableAndLiftImpls! {
74     Cache,
75 }