@@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashMap;
2020use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
2121use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder , opaque,
2222 SpecializedDecoder , SpecializedEncoder ,
23- UseSpecializedDecodable } ;
23+ UseSpecializedDecodable , UseSpecializedEncodable } ;
2424use session:: { CrateDisambiguator , Session } ;
2525use std:: borrow:: Cow ;
2626use std:: cell:: RefCell ;
@@ -30,20 +30,25 @@ use syntax::ast::NodeId;
3030use syntax:: codemap:: { CodeMap , StableFilemapId } ;
3131use syntax_pos:: { BytePos , Span , NO_EXPANSION , DUMMY_SP } ;
3232use ty;
33- use ty:: codec:: { self as ty_codec, TyDecoder } ;
33+ use ty:: codec:: { self as ty_codec, TyDecoder , TyEncoder } ;
3434use ty:: context:: TyCtxt ;
3535use ty:: subst:: Substs ;
3636
3737// Some magic values used for verifying that encoding and decoding. These are
3838// basically random numbers.
3939const PREV_DIAGNOSTICS_TAG : u64 = 0x1234_5678_A1A1_A1A1 ;
4040const DEF_PATH_TABLE_TAG : u64 = 0x1234_5678_B2B2_B2B2 ;
41+ const QUERY_RESULT_INDEX_TAG : u64 = 0x1234_5678_C3C3_C3C3 ;
4142
4243/// `OnDiskCache` provides an interface to incr. comp. data cached from the
4344/// previous compilation session. This data will eventually include the results
4445/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
4546/// any diagnostics that have been emitted during a query.
4647pub struct OnDiskCache < ' sess > {
48+
49+ // The complete cache data in serialized form.
50+ serialized_data : Vec < u8 > ,
51+
4752 // The diagnostics emitted during the previous compilation session.
4853 prev_diagnostics : FxHashMap < SerializedDepNodeIndex , Vec < Diagnostic > > ,
4954
@@ -56,8 +61,12 @@ pub struct OnDiskCache<'sess> {
5661 cnum_map : RefCell < Option < IndexVec < CrateNum , Option < CrateNum > > > > ,
5762 prev_def_path_tables : Vec < DefPathTable > ,
5863
59- _prev_filemap_starts : BTreeMap < BytePos , StableFilemapId > ,
64+ prev_filemap_starts : BTreeMap < BytePos , StableFilemapId > ,
6065 codemap : & ' sess CodeMap ,
66+
67+ // A map from dep-node to the position of the cached query result in
68+ // `serialized_data`.
69+ query_result_index : FxHashMap < SerializedDepNodeIndex , usize > ,
6170}
6271
6372// This type is used only for (de-)serialization.
@@ -68,26 +77,25 @@ struct Header {
6877}
6978
7079type EncodedPrevDiagnostics = Vec < ( SerializedDepNodeIndex , Vec < Diagnostic > ) > ;
80+ type EncodedQueryResultIndex = Vec < ( SerializedDepNodeIndex , usize ) > ;
7181
7282impl < ' sess > OnDiskCache < ' sess > {
7383 /// Create a new OnDiskCache instance from the serialized data in `data`.
74- /// Note that the current implementation (which only deals with diagnostics
75- /// so far) will eagerly deserialize the complete cache. Once we are
76- /// dealing with larger amounts of data (i.e. cached query results),
77- /// deserialization will need to happen lazily.
78- pub fn new ( sess : & ' sess Session , data : & [ u8 ] , start_pos : usize ) -> OnDiskCache < ' sess > {
84+ pub fn new ( sess : & ' sess Session , data : Vec < u8 > , start_pos : usize ) -> OnDiskCache < ' sess > {
7985 debug_assert ! ( sess. opts. incremental. is_some( ) ) ;
8086
81- let mut decoder = opaque:: Decoder :: new ( & data[ ..] , start_pos) ;
82-
83-
8487 // Decode the header
85- let header = Header :: decode ( & mut decoder) . unwrap ( ) ;
88+ let ( header, post_header_pos) = {
89+ let mut decoder = opaque:: Decoder :: new ( & data[ ..] , start_pos) ;
90+ let header = Header :: decode ( & mut decoder)
91+ . expect ( "Error while trying to decode incr. comp. cache header." ) ;
92+ ( header, decoder. position ( ) )
93+ } ;
8694
87- let ( prev_diagnostics, prev_def_path_tables) = {
95+ let ( prev_diagnostics, prev_def_path_tables, query_result_index ) = {
8896 let mut decoder = CacheDecoder {
8997 tcx : None ,
90- opaque : decoder ,
98+ opaque : opaque :: Decoder :: new ( & data [ .. ] , post_header_pos ) ,
9199 codemap : sess. codemap ( ) ,
92100 prev_filemap_starts : & header. prev_filemap_starts ,
93101 cnum_map : & IndexVec :: new ( ) ,
@@ -100,38 +108,56 @@ impl<'sess> OnDiskCache<'sess> {
100108 decode_tagged ( & mut decoder, PREV_DIAGNOSTICS_TAG )
101109 . expect ( "Error while trying to decode previous session \
102110 diagnostics from incr. comp. cache.") ;
103-
104111 diagnostics. into_iter ( ) . collect ( )
105112 } ;
106113
107114 // Decode DefPathTables
108115 let prev_def_path_tables: Vec < DefPathTable > =
109116 decode_tagged ( & mut decoder, DEF_PATH_TABLE_TAG )
110- . expect ( "Error while trying to decode cached DefPathTables" ) ;
117+ . expect ( "Error while trying to decode cached DefPathTables." ) ;
118+
119+ // Decode the *position* of the query result index
120+ let query_result_index_pos = {
121+ let pos_pos = data. len ( ) - IntEncodedWithFixedSize :: ENCODED_SIZE ;
122+ decoder. with_position ( pos_pos, |decoder| {
123+ IntEncodedWithFixedSize :: decode ( decoder)
124+ } ) . expect ( "Error while trying to decode query result index position." )
125+ . 0 as usize
126+ } ;
111127
112- ( prev_diagnostics, prev_def_path_tables)
128+ // Decode the query result index itself
129+ let query_result_index: EncodedQueryResultIndex =
130+ decoder. with_position ( query_result_index_pos, |decoder| {
131+ decode_tagged ( decoder, QUERY_RESULT_INDEX_TAG )
132+ } ) . expect ( "Error while trying to decode query result index." ) ;
133+
134+ ( prev_diagnostics, prev_def_path_tables, query_result_index)
113135 } ;
114136
115137 OnDiskCache {
138+ serialized_data : data,
116139 prev_diagnostics,
117- _prev_filemap_starts : header. prev_filemap_starts ,
140+ prev_filemap_starts : header. prev_filemap_starts ,
118141 prev_cnums : header. prev_cnums ,
119142 cnum_map : RefCell :: new ( None ) ,
120143 prev_def_path_tables,
121144 codemap : sess. codemap ( ) ,
122145 current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
146+ query_result_index : query_result_index. into_iter ( ) . collect ( ) ,
123147 }
124148 }
125149
126150 pub fn new_empty ( codemap : & ' sess CodeMap ) -> OnDiskCache < ' sess > {
127151 OnDiskCache {
152+ serialized_data : Vec :: new ( ) ,
128153 prev_diagnostics : FxHashMap ( ) ,
129- _prev_filemap_starts : BTreeMap :: new ( ) ,
154+ prev_filemap_starts : BTreeMap :: new ( ) ,
130155 prev_cnums : vec ! [ ] ,
131156 cnum_map : RefCell :: new ( None ) ,
132157 prev_def_path_tables : Vec :: new ( ) ,
133158 codemap,
134159 current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
160+ query_result_index : FxHashMap ( ) ,
135161 }
136162 }
137163
@@ -201,6 +227,20 @@ impl<'sess> OnDiskCache<'sess> {
201227
202228 encoder. encode_tagged ( DEF_PATH_TABLE_TAG , & def_path_tables) ?;
203229
230+
231+ // Encode query results
232+ let query_result_index = EncodedQueryResultIndex :: new ( ) ;
233+ // ... we don't encode anything yet, actually
234+
235+
236+ // Encode query result index
237+ let query_result_index_pos = encoder. position ( ) as u64 ;
238+ encoder. encode_tagged ( QUERY_RESULT_INDEX_TAG , & query_result_index) ?;
239+
240+ // Encode the position of the query result index as the last 8 bytes of
241+ // file so we know where to look for it.
242+ IntEncodedWithFixedSize ( query_result_index_pos) . encode ( & mut encoder) ?;
243+
204244 return Ok ( ( ) ) ;
205245
206246 fn sorted_cnums_including_local_crate ( cstore : & CrateStore ) -> Vec < CrateNum > {
@@ -231,6 +271,38 @@ impl<'sess> OnDiskCache<'sess> {
231271 debug_assert ! ( prev. is_none( ) ) ;
232272 }
233273
274+ pub fn load_query_result < ' a , ' tcx , T > ( & self ,
275+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
276+ dep_node_index : SerializedDepNodeIndex )
277+ -> T
278+ where T : Decodable
279+ {
280+ let pos = self . query_result_index [ & dep_node_index] ;
281+
282+ let mut cnum_map = self . cnum_map . borrow_mut ( ) ;
283+ if cnum_map. is_none ( ) {
284+ * cnum_map = Some ( Self :: compute_cnum_map ( tcx, & self . prev_cnums [ ..] ) ) ;
285+ }
286+
287+ let mut decoder = CacheDecoder {
288+ tcx : Some ( tcx) ,
289+ opaque : opaque:: Decoder :: new ( & self . serialized_data [ ..] , pos) ,
290+ codemap : self . codemap ,
291+ prev_filemap_starts : & self . prev_filemap_starts ,
292+ cnum_map : cnum_map. as_ref ( ) . unwrap ( ) ,
293+ prev_def_path_tables : & self . prev_def_path_tables ,
294+ } ;
295+
296+ match decode_tagged ( & mut decoder, dep_node_index) {
297+ Ok ( value) => {
298+ value
299+ }
300+ Err ( e) => {
301+ bug ! ( "Could not decode cached query result: {}" , e)
302+ }
303+ }
304+ }
305+
234306 /// Store a diagnostic emitted during computation of an anonymous query.
235307 /// Since many anonymous queries can share the same `DepNode`, we aggregate
236308 /// them -- as opposed to regular queries where we assume that there is a
@@ -700,3 +772,45 @@ impl<'enc, 'tcx, E> Encoder for CacheEncoder<'enc, 'tcx, E>
700772 }
701773}
702774
775+ // An integer that will always encode to 8 bytes.
776+ struct IntEncodedWithFixedSize ( u64 ) ;
777+
778+ impl IntEncodedWithFixedSize {
779+ pub const ENCODED_SIZE : usize = 8 ;
780+ }
781+
782+ impl UseSpecializedEncodable for IntEncodedWithFixedSize { }
783+ impl UseSpecializedDecodable for IntEncodedWithFixedSize { }
784+
785+ impl < ' enc , ' tcx , E > SpecializedEncoder < IntEncodedWithFixedSize >
786+ for CacheEncoder < ' enc , ' tcx , E >
787+ where E : ' enc + ty_codec:: TyEncoder
788+ {
789+ fn specialized_encode ( & mut self , x : & IntEncodedWithFixedSize ) -> Result < ( ) , Self :: Error > {
790+ let start_pos = self . position ( ) ;
791+ for i in 0 .. IntEncodedWithFixedSize :: ENCODED_SIZE {
792+ ( ( x. 0 >> i * 8 ) as u8 ) . encode ( self ) ?;
793+ }
794+ let end_pos = self . position ( ) ;
795+ assert_eq ! ( ( end_pos - start_pos) , IntEncodedWithFixedSize :: ENCODED_SIZE ) ;
796+ Ok ( ( ) )
797+ }
798+ }
799+
800+ impl < ' a , ' tcx , ' x > SpecializedDecoder < IntEncodedWithFixedSize >
801+ for CacheDecoder < ' a , ' tcx , ' x > {
802+ fn specialized_decode ( & mut self ) -> Result < IntEncodedWithFixedSize , Self :: Error > {
803+ let mut value: u64 = 0 ;
804+ let start_pos = self . position ( ) ;
805+
806+ for i in 0 .. IntEncodedWithFixedSize :: ENCODED_SIZE {
807+ let byte: u8 = Decodable :: decode ( self ) ?;
808+ value |= ( byte as u64 ) << ( i * 8 ) ;
809+ }
810+
811+ let end_pos = self . position ( ) ;
812+ assert_eq ! ( ( end_pos - start_pos) , IntEncodedWithFixedSize :: ENCODED_SIZE ) ;
813+
814+ Ok ( IntEncodedWithFixedSize ( value) )
815+ }
816+ }
0 commit comments