@@ -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