@@ -18,12 +18,13 @@ use rustc_ast::attr;
18
18
use rustc_data_structures:: fingerprint:: Fingerprint ;
19
19
use rustc_data_structures:: fx:: FxHashMap ;
20
20
use rustc_data_structures:: stable_hasher:: StableHasher ;
21
- use rustc_data_structures:: sync:: Lrc ;
21
+ use rustc_data_structures:: sync:: { join , Lrc } ;
22
22
use rustc_hir as hir;
23
23
use rustc_hir:: def:: CtorKind ;
24
+ use rustc_hir:: def_id:: DefIdSet ;
24
25
use rustc_hir:: def_id:: { CrateNum , DefId , DefIndex , LocalDefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
25
26
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
26
- use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
27
+ use rustc_hir:: itemlikevisit:: { ItemLikeVisitor , ParItemLikeVisitor } ;
27
28
use rustc_hir:: { AnonConst , GenericParamKind } ;
28
29
use rustc_index:: vec:: Idx ;
29
30
use rustc_serialize:: { opaque, Encodable , Encoder , SpecializedEncoder } ;
@@ -467,12 +468,6 @@ impl<'tcx> EncodeContext<'tcx> {
467
468
let impls = self . encode_impls ( ) ;
468
469
let impl_bytes = self . position ( ) - i;
469
470
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
-
476
471
let tcx = self . tcx ;
477
472
478
473
// Encode the items.
@@ -513,6 +508,13 @@ impl<'tcx> EncodeContext<'tcx> {
513
508
let proc_macro_data = self . encode_proc_macros ( ) ;
514
509
let proc_macro_data_bytes = self . position ( ) - i;
515
510
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
+
516
518
let attrs = tcx. hir ( ) . krate_attrs ( ) ;
517
519
let has_default_lib_allocator = attr:: contains_name ( & attrs, sym:: default_lib_allocator) ;
518
520
@@ -888,6 +890,8 @@ impl EncodeContext<'tcx> {
888
890
self . encode_generics ( def_id) ;
889
891
self . encode_explicit_predicates ( def_id) ;
890
892
self . encode_inferred_outlives ( def_id) ;
893
+
894
+ // This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
891
895
self . encode_optimized_mir ( def_id) ;
892
896
self . encode_promoted_mir ( def_id) ;
893
897
}
@@ -959,6 +963,9 @@ impl EncodeContext<'tcx> {
959
963
self . encode_generics ( def_id) ;
960
964
self . encode_explicit_predicates ( def_id) ;
961
965
self . encode_inferred_outlives ( def_id) ;
966
+
967
+ // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
968
+
962
969
let mir = match ast_item. kind {
963
970
hir:: ImplItemKind :: Const ( ..) => true ,
964
971
hir:: ImplItemKind :: Fn ( ref sig, _) => {
@@ -1250,6 +1257,8 @@ impl EncodeContext<'tcx> {
1250
1257
_ => { }
1251
1258
}
1252
1259
1260
+ // The following part should be kept in sync with `PrefetchVisitor.visit_item`.
1261
+
1253
1262
let mir = match item. kind {
1254
1263
hir:: ItemKind :: Static ( ..) | hir:: ItemKind :: Const ( ..) => true ,
1255
1264
hir:: ItemKind :: Fn ( ref sig, ..) => {
@@ -1697,6 +1706,70 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
1697
1706
}
1698
1707
}
1699
1708
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
+
1700
1773
// NOTE(eddyb) The following comment was preserved for posterity, even
1701
1774
// though it's no longer relevant as EBML (which uses nested & tagged
1702
1775
// "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> {
1721
1794
// generated regardless of trailing bytes that end up in it.
1722
1795
1723
1796
pub ( 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 {
1724
1829
let mut encoder = opaque:: Encoder :: new ( vec ! [ ] ) ;
1725
1830
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
1726
1831
1727
1832
// Will be filled with the root position after encoding everything.
1728
1833
encoder. emit_raw_bytes ( & [ 0 , 0 , 0 , 0 ] ) ;
1729
1834
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 ( ) ;
1753
1855
1754
1856
// Encode the root position.
1755
1857
let header = METADATA_HEADER . len ( ) ;
0 commit comments