11//! Lazily compute the reverse control-flow graph for the MIR.
22
33use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
4- use rustc_data_structures:: sync:: { Lock , Lrc } ;
4+ use rustc_data_structures:: sync:: OnceCell ;
55use rustc_index:: vec:: IndexVec ;
66use rustc_serialize as serialize;
77use smallvec:: SmallVec ;
@@ -13,37 +13,33 @@ pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
1313
1414#[ derive( Clone , Debug ) ]
1515pub ( super ) struct PredecessorCache {
16- cache : Lock < Option < Lrc < Predecessors > > > ,
16+ cache : OnceCell < Predecessors > ,
1717}
1818
1919impl PredecessorCache {
2020 #[ inline]
2121 pub ( super ) fn new ( ) -> Self {
22- PredecessorCache { cache : Lock :: new ( None ) }
22+ PredecessorCache { cache : OnceCell :: new ( ) }
2323 }
2424
2525 /// Invalidates the predecessor cache.
2626 ///
2727 /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
2828 /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
2929 /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
30- /// cache. This means we don't actually need to take a lock when `invalidate` is called.
30+ /// cache. This means we never need to do synchronization when `invalidate` is called.
3131 #[ inline]
3232 pub ( super ) fn invalidate ( & mut self ) {
33- * self . cache . get_mut ( ) = None ;
33+ self . cache = OnceCell :: new ( ) ;
3434 }
3535
36- /// Returns a ref-counted smart pointer containing the predecessor graph for this MIR.
37- ///
38- /// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for
39- /// `cache` is only held inside this function. As long as no other locks are taken while
40- /// computing the predecessor graph, deadlock is impossible.
36+ /// Returns the the predecessor graph for this MIR.
4137 #[ inline]
4238 pub ( super ) fn compute (
4339 & self ,
4440 basic_blocks : & IndexVec < BasicBlock , BasicBlockData < ' _ > > ,
45- ) -> Lrc < Predecessors > {
46- Lrc :: clone ( self . cache . lock ( ) . get_or_insert_with ( || {
41+ ) -> & Predecessors {
42+ self . cache . get_or_init ( || {
4743 let mut preds = IndexVec :: from_elem ( SmallVec :: new ( ) , basic_blocks) ;
4844 for ( bb, data) in basic_blocks. iter_enumerated ( ) {
4945 if let Some ( term) = & data. terminator {
@@ -53,8 +49,8 @@ impl PredecessorCache {
5349 }
5450 }
5551
56- Lrc :: new ( preds)
57- } ) )
52+ preds
53+ } )
5854 }
5955}
6056
0 commit comments