@@ -18,12 +18,13 @@ use rustc_ast::attr;
1818use  rustc_data_structures:: fingerprint:: Fingerprint ; 
1919use  rustc_data_structures:: fx:: FxHashMap ; 
2020use  rustc_data_structures:: stable_hasher:: StableHasher ; 
21- use  rustc_data_structures:: sync:: Lrc ; 
21+ use  rustc_data_structures:: sync:: { join ,   Lrc } ; 
2222use  rustc_hir as  hir; 
2323use  rustc_hir:: def:: CtorKind ; 
24+ use  rustc_hir:: def_id:: DefIdSet ; 
2425use  rustc_hir:: def_id:: { CrateNum ,  DefId ,  DefIndex ,  LocalDefId ,  CRATE_DEF_INDEX ,  LOCAL_CRATE } ; 
2526use  rustc_hir:: intravisit:: { self ,  NestedVisitorMap ,  Visitor } ; 
26- use  rustc_hir:: itemlikevisit:: ItemLikeVisitor ; 
27+ use  rustc_hir:: itemlikevisit:: { ItemLikeVisitor ,   ParItemLikeVisitor } ; 
2728use  rustc_hir:: { AnonConst ,  GenericParamKind } ; 
2829use  rustc_index:: vec:: Idx ; 
2930use  rustc_serialize:: { opaque,  Encodable ,  Encoder ,  SpecializedEncoder } ; 
@@ -467,12 +468,6 @@ impl<'tcx> EncodeContext<'tcx> {
467468        let  impls = self . encode_impls ( ) ; 
468469        let  impl_bytes = self . position ( )  - i; 
469470
470-         // Encode exported symbols info. 
471-         i = self . position ( ) ; 
472-         let  exported_symbols = self . tcx . exported_symbols ( LOCAL_CRATE ) ; 
473-         let  exported_symbols = self . encode_exported_symbols ( & exported_symbols) ; 
474-         let  exported_symbols_bytes = self . position ( )  - i; 
475- 
476471        let  tcx = self . tcx ; 
477472
478473        // Encode the items. 
@@ -513,6 +508,13 @@ impl<'tcx> EncodeContext<'tcx> {
513508        let  proc_macro_data = self . encode_proc_macros ( ) ; 
514509        let  proc_macro_data_bytes = self . position ( )  - i; 
515510
511+         // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode 
512+         // this last to give the prefetching as much time as possible to complete. 
513+         i = self . position ( ) ; 
514+         let  exported_symbols = self . tcx . exported_symbols ( LOCAL_CRATE ) ; 
515+         let  exported_symbols = self . encode_exported_symbols ( & exported_symbols) ; 
516+         let  exported_symbols_bytes = self . position ( )  - i; 
517+ 
516518        let  attrs = tcx. hir ( ) . krate_attrs ( ) ; 
517519        let  has_default_lib_allocator = attr:: contains_name ( & attrs,  sym:: default_lib_allocator) ; 
518520
@@ -888,6 +890,8 @@ impl EncodeContext<'tcx> {
888890        self . encode_generics ( def_id) ; 
889891        self . encode_explicit_predicates ( def_id) ; 
890892        self . encode_inferred_outlives ( def_id) ; 
893+ 
894+         // This should be kept in sync with `PrefetchVisitor.visit_trait_item`. 
891895        self . encode_optimized_mir ( def_id) ; 
892896        self . encode_promoted_mir ( def_id) ; 
893897    } 
@@ -959,6 +963,9 @@ impl EncodeContext<'tcx> {
959963        self . encode_generics ( def_id) ; 
960964        self . encode_explicit_predicates ( def_id) ; 
961965        self . encode_inferred_outlives ( def_id) ; 
966+ 
967+         // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`. 
968+ 
962969        let  mir = match  ast_item. kind  { 
963970            hir:: ImplItemKind :: Const ( ..)  => true , 
964971            hir:: ImplItemKind :: Fn ( ref  sig,  _)  => { 
@@ -1250,6 +1257,8 @@ impl EncodeContext<'tcx> {
12501257            _ => { } 
12511258        } 
12521259
1260+         // The following part should be kept in sync with `PrefetchVisitor.visit_item`. 
1261+ 
12531262        let  mir = match  item. kind  { 
12541263            hir:: ItemKind :: Static ( ..)  | hir:: ItemKind :: Const ( ..)  => true , 
12551264            hir:: ItemKind :: Fn ( ref  sig,  ..)  => { 
@@ -1697,6 +1706,70 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
16971706    } 
16981707} 
16991708
1709+ /// Used to prefetch queries which will be needed later by metadata encoding. 
1710+ /// Only a subset of the queries are actually prefetched to keep this code smaller. 
1711+ struct  PrefetchVisitor < ' tcx >  { 
1712+     tcx :  TyCtxt < ' tcx > , 
1713+     mir_keys :  & ' tcx  DefIdSet , 
1714+ } 
1715+ 
1716+ impl < ' tcx >  PrefetchVisitor < ' tcx >  { 
1717+     fn  prefetch_mir ( & self ,  def_id :  DefId )  { 
1718+         if  self . mir_keys . contains ( & def_id)  { 
1719+             self . tcx . optimized_mir ( def_id) ; 
1720+             self . tcx . promoted_mir ( def_id) ; 
1721+         } 
1722+     } 
1723+ } 
1724+ 
1725+ impl < ' tcx ,  ' v >  ParItemLikeVisitor < ' v >  for  PrefetchVisitor < ' tcx >  { 
1726+     fn  visit_item ( & self ,  item :  & hir:: Item < ' _ > )  { 
1727+         // This should be kept in sync with `encode_info_for_item`. 
1728+         let  tcx = self . tcx ; 
1729+         match  item. kind  { 
1730+             hir:: ItemKind :: Static ( ..)  | hir:: ItemKind :: Const ( ..)  => { 
1731+                 self . prefetch_mir ( tcx. hir ( ) . local_def_id ( item. hir_id ) ) 
1732+             } 
1733+             hir:: ItemKind :: Fn ( ref  sig,  ..)  => { 
1734+                 let  def_id = tcx. hir ( ) . local_def_id ( item. hir_id ) ; 
1735+                 let  generics = tcx. generics_of ( def_id) ; 
1736+                 let  needs_inline = generics. requires_monomorphization ( tcx) 
1737+                     || tcx. codegen_fn_attrs ( def_id) . requests_inline ( ) ; 
1738+                 if  needs_inline || sig. header . constness  == hir:: Constness :: Const  { 
1739+                     self . prefetch_mir ( def_id) 
1740+                 } 
1741+             } 
1742+             _ => ( ) , 
1743+         } 
1744+     } 
1745+ 
1746+     fn  visit_trait_item ( & self ,  trait_item :  & ' v  hir:: TraitItem < ' v > )  { 
1747+         // This should be kept in sync with `encode_info_for_trait_item`. 
1748+         self . prefetch_mir ( self . tcx . hir ( ) . local_def_id ( trait_item. hir_id ) ) ; 
1749+     } 
1750+ 
1751+     fn  visit_impl_item ( & self ,  impl_item :  & ' v  hir:: ImplItem < ' v > )  { 
1752+         // This should be kept in sync with `encode_info_for_impl_item`. 
1753+         let  tcx = self . tcx ; 
1754+         match  impl_item. kind  { 
1755+             hir:: ImplItemKind :: Const ( ..)  => { 
1756+                 self . prefetch_mir ( tcx. hir ( ) . local_def_id ( impl_item. hir_id ) ) 
1757+             } 
1758+             hir:: ImplItemKind :: Fn ( ref  sig,  _)  => { 
1759+                 let  def_id = tcx. hir ( ) . local_def_id ( impl_item. hir_id ) ; 
1760+                 let  generics = tcx. generics_of ( def_id) ; 
1761+                 let  needs_inline = generics. requires_monomorphization ( tcx) 
1762+                     || tcx. codegen_fn_attrs ( def_id) . requests_inline ( ) ; 
1763+                 let  is_const_fn = sig. header . constness  == hir:: Constness :: Const ; 
1764+                 if  needs_inline || is_const_fn { 
1765+                     self . prefetch_mir ( def_id) 
1766+                 } 
1767+             } 
1768+             hir:: ImplItemKind :: OpaqueTy ( ..)  | hir:: ImplItemKind :: TyAlias ( ..)  => ( ) , 
1769+         } 
1770+     } 
1771+ } 
1772+ 
17001773// NOTE(eddyb) The following comment was preserved for posterity, even 
17011774// though it's no longer relevant as EBML (which uses nested & tagged 
17021775// "documents") was replaced with a scheme that can't go out of bounds. 
@@ -1721,35 +1794,64 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
17211794// generated regardless of trailing bytes that end up in it. 
17221795
17231796pub ( super )  fn  encode_metadata ( tcx :  TyCtxt < ' _ > )  -> EncodedMetadata  { 
1797+     // Since encoding metadata is not in a query, and nothing is cached, 
1798+     // there's no need to do dep-graph tracking for any of it. 
1799+     tcx. dep_graph . assert_ignored ( ) ; 
1800+ 
1801+     join ( 
1802+         || encode_metadata_impl ( tcx) , 
1803+         || { 
1804+             if  tcx. sess . threads ( )  == 1  { 
1805+                 return ; 
1806+             } 
1807+             // Prefetch some queries used by metadata encoding. 
1808+             // This is not necessary for correctness, but is only done for performance reasons. 
1809+             // It can be removed if it turns out to cause trouble or be detrimental to performance. 
1810+             join ( 
1811+                 || { 
1812+                     if  !tcx. sess . opts . output_types . should_codegen ( )  { 
1813+                         // We won't emit MIR, so don't prefetch it. 
1814+                         return ; 
1815+                     } 
1816+                     tcx. hir ( ) . krate ( ) . par_visit_all_item_likes ( & PrefetchVisitor  { 
1817+                         tcx, 
1818+                         mir_keys :  tcx. mir_keys ( LOCAL_CRATE ) , 
1819+                     } ) ; 
1820+                 } , 
1821+                 || tcx. exported_symbols ( LOCAL_CRATE ) , 
1822+             ) ; 
1823+         } , 
1824+     ) 
1825+     . 0 
1826+ } 
1827+ 
1828+ fn  encode_metadata_impl ( tcx :  TyCtxt < ' _ > )  -> EncodedMetadata  { 
17241829    let  mut  encoder = opaque:: Encoder :: new ( vec ! [ ] ) ; 
17251830    encoder. emit_raw_bytes ( METADATA_HEADER ) ; 
17261831
17271832    // Will be filled with the root position after encoding everything. 
17281833    encoder. emit_raw_bytes ( & [ 0 ,  0 ,  0 ,  0 ] ) ; 
17291834
1730-     // Since encoding metadata is not in a query, and nothing is cached, 
1731-     // there's no need to do dep-graph tracking for any of it. 
1732-     let  ( root,  mut  result)  = tcx. dep_graph . with_ignore ( move  || { 
1733-         let  mut  ecx = EncodeContext  { 
1734-             opaque :  encoder, 
1735-             tcx, 
1736-             per_def :  Default :: default ( ) , 
1737-             lazy_state :  LazyState :: NoNode , 
1738-             type_shorthands :  Default :: default ( ) , 
1739-             predicate_shorthands :  Default :: default ( ) , 
1740-             source_file_cache :  tcx. sess . source_map ( ) . files ( ) [ 0 ] . clone ( ) , 
1741-             interpret_allocs :  Default :: default ( ) , 
1742-             interpret_allocs_inverse :  Default :: default ( ) , 
1743-         } ; 
1744- 
1745-         // Encode the rustc version string in a predictable location. 
1746-         rustc_version ( ) . encode ( & mut  ecx) . unwrap ( ) ; 
1747- 
1748-         // Encode all the entries and extra information in the crate, 
1749-         // culminating in the `CrateRoot` which points to all of it. 
1750-         let  root = ecx. encode_crate_root ( ) ; 
1751-         ( root,  ecx. opaque . into_inner ( ) ) 
1752-     } ) ; 
1835+     let  mut  ecx = EncodeContext  { 
1836+         opaque :  encoder, 
1837+         tcx, 
1838+         per_def :  Default :: default ( ) , 
1839+         lazy_state :  LazyState :: NoNode , 
1840+         type_shorthands :  Default :: default ( ) , 
1841+         predicate_shorthands :  Default :: default ( ) , 
1842+         source_file_cache :  tcx. sess . source_map ( ) . files ( ) [ 0 ] . clone ( ) , 
1843+         interpret_allocs :  Default :: default ( ) , 
1844+         interpret_allocs_inverse :  Default :: default ( ) , 
1845+     } ; 
1846+ 
1847+     // Encode the rustc version string in a predictable location. 
1848+     rustc_version ( ) . encode ( & mut  ecx) . unwrap ( ) ; 
1849+ 
1850+     // Encode all the entries and extra information in the crate, 
1851+     // culminating in the `CrateRoot` which points to all of it. 
1852+     let  root = ecx. encode_crate_root ( ) ; 
1853+ 
1854+     let  mut  result = ecx. opaque . into_inner ( ) ; 
17531855
17541856    // Encode the root position. 
17551857    let  header = METADATA_HEADER . len ( ) ; 
0 commit comments