1
1
//! Lazily compute the reverse control-flow graph for the MIR.
2
2
3
3
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
4
- use rustc_data_structures:: sync:: { Lock , Lrc } ;
4
+ use rustc_data_structures:: sync:: OnceCell ;
5
5
use rustc_index:: vec:: IndexVec ;
6
6
use rustc_serialize as serialize;
7
7
use smallvec:: SmallVec ;
@@ -13,37 +13,33 @@ pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
13
13
14
14
#[ derive( Clone , Debug ) ]
15
15
pub ( super ) struct PredecessorCache {
16
- cache : Lock < Option < Lrc < Predecessors > > > ,
16
+ cache : OnceCell < Predecessors > ,
17
17
}
18
18
19
19
impl PredecessorCache {
20
20
#[ inline]
21
21
pub ( super ) fn new ( ) -> Self {
22
- PredecessorCache { cache : Lock :: new ( None ) }
22
+ PredecessorCache { cache : OnceCell :: new ( ) }
23
23
}
24
24
25
25
/// Invalidates the predecessor cache.
26
26
///
27
27
/// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
28
28
/// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
29
29
/// 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.
31
31
#[ inline]
32
32
pub ( super ) fn invalidate ( & mut self ) {
33
- * self . cache . get_mut ( ) = None ;
33
+ self . cache = OnceCell :: new ( ) ;
34
34
}
35
35
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.
41
37
#[ inline]
42
38
pub ( super ) fn compute (
43
39
& self ,
44
40
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 ( || {
47
43
let mut preds = IndexVec :: from_elem ( SmallVec :: new ( ) , basic_blocks) ;
48
44
for ( bb, data) in basic_blocks. iter_enumerated ( ) {
49
45
if let Some ( term) = & data. terminator {
@@ -53,8 +49,8 @@ impl PredecessorCache {
53
49
}
54
50
}
55
51
56
- Lrc :: new ( preds)
57
- } ) )
52
+ preds
53
+ } )
58
54
}
59
55
}
60
56
0 commit comments