@@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashMap;
20
20
use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
21
21
use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder , opaque,
22
22
SpecializedDecoder , SpecializedEncoder ,
23
- UseSpecializedDecodable } ;
23
+ UseSpecializedDecodable , UseSpecializedEncodable } ;
24
24
use session:: { CrateDisambiguator , Session } ;
25
25
use std:: borrow:: Cow ;
26
26
use std:: cell:: RefCell ;
@@ -30,20 +30,25 @@ use syntax::ast::NodeId;
30
30
use syntax:: codemap:: { CodeMap , StableFilemapId } ;
31
31
use syntax_pos:: { BytePos , Span , NO_EXPANSION , DUMMY_SP } ;
32
32
use ty;
33
- use ty:: codec:: { self as ty_codec, TyDecoder } ;
33
+ use ty:: codec:: { self as ty_codec, TyDecoder , TyEncoder } ;
34
34
use ty:: context:: TyCtxt ;
35
35
use ty:: subst:: Substs ;
36
36
37
37
// Some magic values used for verifying that encoding and decoding. These are
38
38
// basically random numbers.
39
39
const PREV_DIAGNOSTICS_TAG : u64 = 0x1234_5678_A1A1_A1A1 ;
40
40
const DEF_PATH_TABLE_TAG : u64 = 0x1234_5678_B2B2_B2B2 ;
41
+ const QUERY_RESULT_INDEX_TAG : u64 = 0x1234_5678_C3C3_C3C3 ;
41
42
42
43
/// `OnDiskCache` provides an interface to incr. comp. data cached from the
43
44
/// previous compilation session. This data will eventually include the results
44
45
/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
45
46
/// any diagnostics that have been emitted during a query.
46
47
pub struct OnDiskCache < ' sess > {
48
+
49
+ // The complete cache data in serialized form.
50
+ serialized_data : Vec < u8 > ,
51
+
47
52
// The diagnostics emitted during the previous compilation session.
48
53
prev_diagnostics : FxHashMap < SerializedDepNodeIndex , Vec < Diagnostic > > ,
49
54
@@ -56,8 +61,12 @@ pub struct OnDiskCache<'sess> {
56
61
cnum_map : RefCell < Option < IndexVec < CrateNum , Option < CrateNum > > > > ,
57
62
prev_def_path_tables : Vec < DefPathTable > ,
58
63
59
- _prev_filemap_starts : BTreeMap < BytePos , StableFilemapId > ,
64
+ prev_filemap_starts : BTreeMap < BytePos , StableFilemapId > ,
60
65
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 > ,
61
70
}
62
71
63
72
// This type is used only for (de-)serialization.
@@ -68,26 +77,25 @@ struct Header {
68
77
}
69
78
70
79
type EncodedPrevDiagnostics = Vec < ( SerializedDepNodeIndex , Vec < Diagnostic > ) > ;
80
+ type EncodedQueryResultIndex = Vec < ( SerializedDepNodeIndex , usize ) > ;
71
81
72
82
impl < ' sess > OnDiskCache < ' sess > {
73
83
/// 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 > {
79
85
debug_assert ! ( sess. opts. incremental. is_some( ) ) ;
80
86
81
- let mut decoder = opaque:: Decoder :: new ( & data[ ..] , start_pos) ;
82
-
83
-
84
87
// 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
+ } ;
86
94
87
- let ( prev_diagnostics, prev_def_path_tables) = {
95
+ let ( prev_diagnostics, prev_def_path_tables, query_result_index ) = {
88
96
let mut decoder = CacheDecoder {
89
97
tcx : None ,
90
- opaque : decoder ,
98
+ opaque : opaque :: Decoder :: new ( & data [ .. ] , post_header_pos ) ,
91
99
codemap : sess. codemap ( ) ,
92
100
prev_filemap_starts : & header. prev_filemap_starts ,
93
101
cnum_map : & IndexVec :: new ( ) ,
@@ -100,38 +108,56 @@ impl<'sess> OnDiskCache<'sess> {
100
108
decode_tagged ( & mut decoder, PREV_DIAGNOSTICS_TAG )
101
109
. expect ( "Error while trying to decode previous session \
102
110
diagnostics from incr. comp. cache.") ;
103
-
104
111
diagnostics. into_iter ( ) . collect ( )
105
112
} ;
106
113
107
114
// Decode DefPathTables
108
115
let prev_def_path_tables: Vec < DefPathTable > =
109
116
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
+ } ;
111
127
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)
113
135
} ;
114
136
115
137
OnDiskCache {
138
+ serialized_data : data,
116
139
prev_diagnostics,
117
- _prev_filemap_starts : header. prev_filemap_starts ,
140
+ prev_filemap_starts : header. prev_filemap_starts ,
118
141
prev_cnums : header. prev_cnums ,
119
142
cnum_map : RefCell :: new ( None ) ,
120
143
prev_def_path_tables,
121
144
codemap : sess. codemap ( ) ,
122
145
current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
146
+ query_result_index : query_result_index. into_iter ( ) . collect ( ) ,
123
147
}
124
148
}
125
149
126
150
pub fn new_empty ( codemap : & ' sess CodeMap ) -> OnDiskCache < ' sess > {
127
151
OnDiskCache {
152
+ serialized_data : Vec :: new ( ) ,
128
153
prev_diagnostics : FxHashMap ( ) ,
129
- _prev_filemap_starts : BTreeMap :: new ( ) ,
154
+ prev_filemap_starts : BTreeMap :: new ( ) ,
130
155
prev_cnums : vec ! [ ] ,
131
156
cnum_map : RefCell :: new ( None ) ,
132
157
prev_def_path_tables : Vec :: new ( ) ,
133
158
codemap,
134
159
current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
160
+ query_result_index : FxHashMap ( ) ,
135
161
}
136
162
}
137
163
@@ -201,6 +227,20 @@ impl<'sess> OnDiskCache<'sess> {
201
227
202
228
encoder. encode_tagged ( DEF_PATH_TABLE_TAG , & def_path_tables) ?;
203
229
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
+
204
244
return Ok ( ( ) ) ;
205
245
206
246
fn sorted_cnums_including_local_crate ( cstore : & CrateStore ) -> Vec < CrateNum > {
@@ -231,6 +271,38 @@ impl<'sess> OnDiskCache<'sess> {
231
271
debug_assert ! ( prev. is_none( ) ) ;
232
272
}
233
273
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
+
234
306
/// Store a diagnostic emitted during computation of an anonymous query.
235
307
/// Since many anonymous queries can share the same `DepNode`, we aggregate
236
308
/// 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>
700
772
}
701
773
}
702
774
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