@@ -217,6 +217,7 @@ use trans::monomorphize;
217217use util:: nodemap:: { FnvHashSet , FnvHashMap , DefIdMap } ;
218218
219219use std:: hash:: { Hash , Hasher } ;
220+ use std:: rc:: Rc ;
220221
221222#[ derive( PartialEq , Eq , Hash , Clone , Copy , Debug ) ]
222223pub enum TransItemCollectionMode {
@@ -281,9 +282,14 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
281282 debug ! ( "Building translation item graph, beginning at roots" ) ;
282283 let mut visited = FnvHashSet ( ) ;
283284 let mut recursion_depths = DefIdMap ( ) ;
285+ let mut mir_cache = DefIdMap ( ) ;
284286
285287 for root in roots {
286- collect_items_rec ( ccx, root, & mut visited, & mut recursion_depths) ;
288+ collect_items_rec ( ccx,
289+ root,
290+ & mut visited,
291+ & mut recursion_depths,
292+ & mut mir_cache) ;
287293 }
288294
289295 visited
@@ -313,11 +319,27 @@ fn collect_roots<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
313319 roots
314320}
315321
322+ #[ derive( Clone ) ]
323+ enum CachedMir < ' mir , ' tcx : ' mir > {
324+ Ref ( & ' mir mir:: Mir < ' tcx > ) ,
325+ Owned ( Rc < mir:: Mir < ' tcx > > )
326+ }
327+
328+ impl < ' mir , ' tcx : ' mir > CachedMir < ' mir , ' tcx > {
329+ fn get_ref < ' a > ( & ' a self ) -> & ' a mir:: Mir < ' tcx > {
330+ match * self {
331+ CachedMir :: Ref ( r) => r,
332+ CachedMir :: Owned ( ref rc) => & * * rc,
333+ }
334+ }
335+ }
336+
316337// Collect all monomorphized translation items reachable from `starting_point`
317338fn collect_items_rec < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
318339 starting_point : TransItem < ' tcx > ,
319340 visited : & mut FnvHashSet < TransItem < ' tcx > > ,
320- recursion_depths : & mut DefIdMap < usize > ) {
341+ recursion_depths : & mut DefIdMap < usize > ,
342+ mir_cache : & mut DefIdMap < CachedMir < ' a , ' tcx > > ) {
321343 if !visited. insert ( starting_point. clone ( ) ) {
322344 // We've been here already, no need to search again.
323345 return ;
@@ -343,42 +365,21 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
343365
344366 // Scan the MIR in order to find function calls, closures, and
345367 // drop-glue
346- let mir_not_found_error_message = || {
347- format ! ( "Could not find MIR for function: {}" ,
348- ccx. tcx( ) . item_path_str( def_id) )
349- } ;
350-
351- let external_mir = if !def_id. is_local ( ) {
352- ccx. sess ( ) . cstore . maybe_get_item_mir ( ccx. tcx ( ) , def_id)
353- } else {
354- None
355- } ;
356-
357- let mir_opt = match external_mir {
358- Some ( ref mir) => Some ( mir) ,
359- None => {
360- let node_id = ccx. tcx ( ) . map . as_local_node_id ( def_id) . unwrap ( ) ;
361- ccx. mir_map ( ) . get ( & node_id)
362- }
363- } ;
364-
365- let mir = errors:: expect ( ccx. sess ( ) . diagnostic ( ) ,
366- mir_opt,
367- mir_not_found_error_message) ;
368+ let mir = load_mir ( ccx, def_id, mir_cache) ;
368369
369370 let mut visitor = MirNeighborCollector {
370371 ccx : ccx,
371- mir : mir,
372+ mir : mir. get_ref ( ) ,
372373 output : & mut neighbors,
373374 param_substs : param_substs
374375 } ;
375376
376- visitor. visit_mir ( mir) ;
377+ visitor. visit_mir ( mir. get_ref ( ) ) ;
377378 }
378379 }
379380
380381 for neighbour in neighbors {
381- collect_items_rec ( ccx, neighbour, visited, recursion_depths) ;
382+ collect_items_rec ( ccx, neighbour, visited, recursion_depths, mir_cache ) ;
382383 }
383384
384385 if let Some ( ( def_id, depth) ) = recursion_depth_reset {
@@ -388,6 +389,37 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
388389 debug ! ( "END collect_items_rec({})" , starting_point. to_string( ccx) ) ;
389390}
390391
392+ fn load_mir < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
393+ def_id : DefId ,
394+ mir_cache : & mut DefIdMap < CachedMir < ' a , ' tcx > > )
395+ -> CachedMir < ' a , ' tcx > {
396+ let mir_not_found_error_message = || {
397+ format ! ( "Could not find MIR for function: {}" ,
398+ ccx. tcx( ) . item_path_str( def_id) )
399+ } ;
400+
401+ if def_id. is_local ( ) {
402+ let node_id = ccx. tcx ( ) . map . as_local_node_id ( def_id) . unwrap ( ) ;
403+ let mir_opt = ccx. mir_map ( ) . get ( & node_id) ;
404+ let mir = errors:: expect ( ccx. sess ( ) . diagnostic ( ) ,
405+ mir_opt,
406+ mir_not_found_error_message) ;
407+ CachedMir :: Ref ( mir)
408+ } else {
409+ if let Some ( mir) = mir_cache. get ( & def_id) {
410+ return mir. clone ( ) ;
411+ }
412+
413+ let mir_opt = ccx. sess ( ) . cstore . maybe_get_item_mir ( ccx. tcx ( ) , def_id) ;
414+ let mir = errors:: expect ( ccx. sess ( ) . diagnostic ( ) ,
415+ mir_opt,
416+ mir_not_found_error_message) ;
417+ let cached = CachedMir :: Owned ( Rc :: new ( mir) ) ;
418+ mir_cache. insert ( def_id, cached. clone ( ) ) ;
419+ cached
420+ }
421+ }
422+
391423fn check_recursion_limit < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
392424 def_id : DefId ,
393425 recursion_depths : & mut DefIdMap < usize > )
@@ -1488,14 +1520,15 @@ pub enum TransItemState {
14881520 NotPredictedButGenerated ,
14891521}
14901522
1523+ pub fn collecting_debug_information ( ccx : & CrateContext ) -> bool {
1524+ return cfg ! ( debug_assertions) &&
1525+ ccx. sess ( ) . opts . debugging_opts . print_trans_items . is_some ( ) ;
1526+ }
1527+
14911528pub fn print_collection_results < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ) {
14921529 use std:: hash:: { Hash , SipHasher , Hasher } ;
14931530
1494- if !cfg ! ( debug_assertions) {
1495- return ;
1496- }
1497-
1498- if ccx. sess ( ) . opts . debugging_opts . print_trans_items . is_none ( ) {
1531+ if !collecting_debug_information ( ccx) {
14991532 return ;
15001533 }
15011534
0 commit comments