11use  rustc_index:: vec:: IndexVec ; 
2- use  rustc_data_structures:: sync:: { RwLock ,  MappedReadGuard ,  ReadGuard } ; 
32use  rustc_data_structures:: stable_hasher:: { HashStable ,  StableHasher } ; 
43use  rustc_serialize:: { Encodable ,  Encoder ,  Decodable ,  Decoder } ; 
54use  crate :: ich:: StableHashingContext ; 
6- use  crate :: mir:: { Body ,  BasicBlock } ; 
5+ use  crate :: mir:: { BasicBlock ,  BasicBlockData ,  Body ,  LocalDecls ,  Location ,  Successors } ; 
6+ use  rustc_data_structures:: graph:: { self ,  GraphPredecessors ,  GraphSuccessors } ; 
7+ use  rustc_data_structures:: graph:: dominators:: { dominators,  Dominators } ; 
8+ use  std:: iter; 
9+ use  std:: ops:: { Deref ,  DerefMut ,  Index ,  IndexMut } ; 
10+ use  std:: vec:: IntoIter ; 
711
812#[ derive( Clone ,  Debug ) ]  
913pub  struct  Cache  { 
10-     predecessors :  RwLock < Option < IndexVec < BasicBlock ,  Vec < BasicBlock > > > > 
14+     predecessors :  Option < IndexVec < BasicBlock ,  Vec < BasicBlock > > > , 
1115} 
1216
13- 
1417impl  rustc_serialize:: Encodable  for  Cache  { 
1518    fn  encode < S :  Encoder > ( & self ,  s :  & mut  S )  -> Result < ( ) ,  S :: Error >  { 
1619        Encodable :: encode ( & ( ) ,  s) 
@@ -31,39 +34,264 @@ impl<'a> HashStable<StableHashingContext<'a>> for Cache {
3134
3235impl  Cache  { 
3336    pub  fn  new ( )  -> Self  { 
34-         Cache  { 
35-             predecessors :  RwLock :: new ( None ) 
37+         Self  { 
38+             predecessors :  None , 
3639        } 
3740    } 
3841
39-     pub  fn  invalidate ( & self )  { 
42+     pub  fn  invalidate_predecessors ( & mut   self )  { 
4043        // FIXME: consider being more fine-grained 
41-         * self . predecessors . borrow_mut ( )  = None ; 
44+         self . predecessors  = None ; 
4245    } 
4346
44-     pub  fn  predecessors ( 
45-         & self , 
46-         body :  & Body < ' _ > 
47-     )  -> MappedReadGuard < ' _ ,  IndexVec < BasicBlock ,  Vec < BasicBlock > > >  { 
48-         if  self . predecessors . borrow ( ) . is_none ( )  { 
49-             * self . predecessors . borrow_mut ( )  = Some ( calculate_predecessors ( body) ) ; 
47+     pub  fn  ensure_predecessors ( & mut  self ,  body :  & Body < ' _ > )  { 
48+         if  self . predecessors . is_none ( )  { 
49+             let  mut  result = IndexVec :: from_elem ( vec ! [ ] ,  body. basic_blocks ( ) ) ; 
50+             for  ( bb,  data)  in  body. basic_blocks ( ) . iter_enumerated ( )  { 
51+                 if  let  Some ( ref  term)  = data. terminator  { 
52+                     for  & tgt in  term. successors ( )  { 
53+                         result[ tgt] . push ( bb) ; 
54+                     } 
55+                 } 
56+             } 
57+ 
58+             self . predecessors  = Some ( result) 
5059        } 
60+     } 
61+ 
62+     /// This will recompute the predecessors cache if it is not available 
63+      fn  predecessors ( & mut  self ,  body :  & Body < ' _ > )  -> & IndexVec < BasicBlock ,  Vec < BasicBlock > >  { 
64+         self . ensure_predecessors ( body) ; 
65+         self . predecessors . as_ref ( ) . unwrap ( ) 
66+     } 
67+ 
68+     fn  unwrap_predecessors_for ( & self ,  bb :  BasicBlock )  -> & [ BasicBlock ]  { 
69+         & self . predecessors . as_ref ( ) . unwrap ( ) [ bb] 
70+     } 
5171
52-         ReadGuard :: map ( self . predecessors . borrow ( ) ,  |p| p. as_ref ( ) . unwrap ( ) ) 
72+     fn  unwrap_predecessor_locations < ' a > ( 
73+         & ' a  self , 
74+         loc :  Location , 
75+         body :  & ' a  Body < ' a > 
76+     )  -> impl  Iterator < Item  = Location >  + ' a  { 
77+         let  if_zero_locations = if  loc. statement_index  == 0  { 
78+             let  predecessor_blocks = self . unwrap_predecessors_for ( loc. block ) ; 
79+             let  num_predecessor_blocks = predecessor_blocks. len ( ) ; 
80+             Some ( 
81+                 ( 0 ..num_predecessor_blocks) 
82+                     . map ( move  |i| predecessor_blocks[ i] ) 
83+                     . map ( move  |bb| body. terminator_loc ( bb) ) , 
84+             ) 
85+         }  else  { 
86+             None 
87+         } ; 
88+ 
89+         let  if_not_zero_locations = if  loc. statement_index  == 0  { 
90+             None 
91+         }  else  { 
92+             Some ( Location  {  block :  loc. block ,  statement_index :  loc. statement_index  - 1  } ) 
93+         } ; 
94+ 
95+         if_zero_locations. into_iter ( ) . flatten ( ) . chain ( if_not_zero_locations) 
96+     } 
97+ 
98+     pub  fn  basic_blocks_mut < ' a ,  ' tcx > ( 
99+         & mut  self , 
100+         body :  & ' a  mut  Body < ' tcx > 
101+     )  -> & ' a  mut  IndexVec < BasicBlock ,  BasicBlockData < ' tcx > >  { 
102+         debug ! ( "bbm: Clearing predecessors cache for body at: {:?}" ,  body. span. data( ) ) ; 
103+         self . invalidate_predecessors ( ) ; 
104+         & mut  body. basic_blocks 
105+     } 
106+ 
107+     pub  fn  basic_blocks_and_local_decls_mut < ' a ,  ' tcx > ( 
108+         & mut  self , 
109+         body :  & ' a  mut  Body < ' tcx > 
110+     )  -> ( & ' a  mut  IndexVec < BasicBlock ,  BasicBlockData < ' tcx > > ,  & ' a  mut  LocalDecls < ' tcx > )  { 
111+         debug ! ( "bbaldm: Clearing predecessors cache for body at: {:?}" ,  body. span. data( ) ) ; 
112+         self . invalidate_predecessors ( ) ; 
113+         ( & mut  body. basic_blocks ,  & mut  body. local_decls ) 
53114    } 
54115} 
55116
56- fn  calculate_predecessors ( body :  & Body < ' _ > )  -> IndexVec < BasicBlock ,  Vec < BasicBlock > >  { 
57-     let  mut  result = IndexVec :: from_elem ( vec ! [ ] ,  body. basic_blocks ( ) ) ; 
58-     for  ( bb,  data)  in  body. basic_blocks ( ) . iter_enumerated ( )  { 
59-         if  let  Some ( ref  term)  = data. terminator  { 
60-             for  & tgt in  term. successors ( )  { 
61-                 result[ tgt] . push ( bb) ; 
62-             } 
117+ #[ derive( Clone ,  Debug ,  HashStable ,  RustcEncodable ,  RustcDecodable ,  TypeFoldable ) ]  
118+ pub  struct  BodyCache < ' tcx >  { 
119+     cache :  Cache , 
120+     body :  Body < ' tcx > , 
121+ } 
122+ 
123+ impl  BodyCache < ' tcx >  { 
124+     pub  fn  new ( body :  Body < ' tcx > )  -> Self  { 
125+         Self  { 
126+             cache :  Cache :: new ( ) , 
127+             body, 
128+         } 
129+     } 
130+ } 
131+ 
132+ #[ macro_export]  
133+ macro_rules!  read_only { 
134+     ( $body: expr)  => { 
135+         { 
136+             $body. ensure_predecessors( ) ; 
137+             $body. unwrap_read_only( ) 
138+         } 
139+     } ; 
140+ } 
141+ 
142+ impl  BodyCache < ' tcx >  { 
143+     pub  fn  ensure_predecessors ( & mut  self )  { 
144+         self . cache . ensure_predecessors ( & self . body ) ; 
145+     } 
146+ 
147+     pub  fn  predecessors ( & mut  self )  -> & IndexVec < BasicBlock ,  Vec < BasicBlock > >  { 
148+         self . cache . predecessors ( & self . body ) 
149+     } 
150+ 
151+     pub  fn  unwrap_read_only ( & self )  -> ReadOnlyBodyCache < ' _ ,  ' tcx >  { 
152+         ReadOnlyBodyCache :: new ( & self . cache ,  & self . body ) 
153+     } 
154+ 
155+     pub  fn  basic_blocks_mut ( & mut  self )  -> & mut  IndexVec < BasicBlock ,  BasicBlockData < ' tcx > >  { 
156+         self . cache . basic_blocks_mut ( & mut  self . body ) 
157+     } 
158+ 
159+     pub  fn  basic_blocks_and_local_decls_mut ( 
160+         & mut  self 
161+     )  -> ( & mut  IndexVec < BasicBlock ,  BasicBlockData < ' tcx > > ,  & mut  LocalDecls < ' tcx > )  { 
162+         self . cache . basic_blocks_and_local_decls_mut ( & mut  self . body ) 
163+     } 
164+ } 
165+ 
166+ impl < ' tcx >  Index < BasicBlock >  for  BodyCache < ' tcx >  { 
167+     type  Output  = BasicBlockData < ' tcx > ; 
168+ 
169+     fn  index ( & self ,  index :  BasicBlock )  -> & BasicBlockData < ' tcx >  { 
170+         & self . body [ index] 
171+     } 
172+ } 
173+ 
174+ impl < ' tcx >  IndexMut < BasicBlock >  for  BodyCache < ' tcx >  { 
175+     fn  index_mut ( & mut  self ,  index :  BasicBlock )  -> & mut  Self :: Output  { 
176+         & mut  self . basic_blocks_mut ( ) [ index] 
177+     } 
178+ } 
179+ 
180+ impl < ' tcx >  Deref  for  BodyCache < ' tcx >  { 
181+     type  Target  = Body < ' tcx > ; 
182+ 
183+     fn  deref ( & self )  -> & Self :: Target  { 
184+         & self . body 
185+     } 
186+ } 
187+ 
188+ impl < ' tcx >  DerefMut  for  BodyCache < ' tcx >  { 
189+     fn  deref_mut ( & mut  self )  -> & mut  Self :: Target  { 
190+         & mut  self . body 
191+     } 
192+ } 
193+ 
194+ #[ derive( Copy ,  Clone ,  Debug ) ]  
195+ pub  struct  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
196+     cache :  & ' a  Cache , 
197+     body :  & ' a  Body < ' tcx > , 
198+ } 
199+ 
200+ impl  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
201+     fn  new ( cache :  & ' a  Cache ,  body :  & ' a  Body < ' tcx > )  -> Self  { 
202+         assert ! ( 
203+             cache. predecessors. is_some( ) , 
204+             "Cannot construct ReadOnlyBodyCache without computed predecessors" ) ; 
205+         Self  { 
206+             cache, 
207+             body, 
63208        } 
64209    } 
65210
66-     result
211+     pub  fn  predecessors ( & self )  -> & IndexVec < BasicBlock ,  Vec < BasicBlock > >  { 
212+         self . cache . predecessors . as_ref ( ) . unwrap ( ) 
213+     } 
214+ 
215+     pub  fn  predecessors_for ( & self ,  bb :  BasicBlock )  -> & [ BasicBlock ]  { 
216+         self . cache . unwrap_predecessors_for ( bb) 
217+     } 
218+ 
219+     pub  fn  predecessor_locations ( & self ,  loc :  Location )  -> impl  Iterator < Item  = Location >  + ' _  { 
220+         self . cache . unwrap_predecessor_locations ( loc,  self . body ) 
221+     } 
222+ 
223+     pub  fn  body ( & self )  -> & ' a  Body < ' tcx >  { 
224+         self . body 
225+     } 
226+ 
227+     pub  fn  basic_blocks ( & self )  -> & IndexVec < BasicBlock ,  BasicBlockData < ' tcx > >  { 
228+         & self . body . basic_blocks 
229+     } 
230+ 
231+     pub  fn  dominators ( & self )  -> Dominators < BasicBlock >  { 
232+         dominators ( self ) 
233+     } 
234+ } 
235+ 
236+ impl  graph:: DirectedGraph  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
237+     type  Node  = BasicBlock ; 
238+ } 
239+ 
240+ impl  graph:: GraphPredecessors < ' graph >  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
241+     type  Item  = BasicBlock ; 
242+     type  Iter  = IntoIter < BasicBlock > ; 
243+ } 
244+ 
245+ impl  graph:: WithPredecessors  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
246+     fn  predecessors ( 
247+         & self , 
248+         node :  Self :: Node , 
249+     )  -> <Self  as  GraphPredecessors < ' _ > >:: Iter  { 
250+         self . cache . unwrap_predecessors_for ( node) . to_vec ( ) . into_iter ( ) 
251+     } 
252+ } 
253+ 
254+ impl  graph:: WithNumNodes  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
255+     fn  num_nodes ( & self )  -> usize  { 
256+         self . body . num_nodes ( ) 
257+     } 
258+ } 
259+ 
260+ impl  graph:: WithStartNode  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
261+     fn  start_node ( & self )  -> Self :: Node  { 
262+         self . body . start_node ( ) 
263+     } 
264+ } 
265+ 
266+ impl  graph:: WithSuccessors  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
267+     fn  successors ( 
268+         & self , 
269+         node :  Self :: Node , 
270+     )  -> <Self  as  GraphSuccessors < ' _ > >:: Iter  { 
271+         self . body . successors ( node) 
272+     } 
273+ } 
274+ 
275+ impl < ' a ,  ' b ,  ' tcx >  graph:: GraphSuccessors < ' b >  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
276+     type  Item  = BasicBlock ; 
277+     type  Iter  = iter:: Cloned < Successors < ' b > > ; 
278+ } 
279+ 
280+ 
281+ impl  Deref  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
282+     type  Target  = Body < ' tcx > ; 
283+ 
284+     fn  deref ( & self )  -> & Self :: Target  { 
285+         self . body 
286+     } 
287+ } 
288+ 
289+ impl  Index < BasicBlock >  for  ReadOnlyBodyCache < ' a ,  ' tcx >  { 
290+     type  Output  = BasicBlockData < ' tcx > ; 
291+ 
292+     fn  index ( & self ,  index :  BasicBlock )  -> & BasicBlockData < ' tcx >  { 
293+         & self . body [ index] 
294+     } 
67295} 
68296
69297CloneTypeFoldableAndLiftImpls !  { 
0 commit comments