Skip to content

Commit 4bfab89

Browse files
incr.comp.: Store the query result index which records where query results can be found in the cached.
1 parent 2087d5e commit 4bfab89

File tree

2 files changed

+134
-20
lines changed

2 files changed

+134
-20
lines changed

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 133 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashMap;
2020
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
2121
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
2222
SpecializedDecoder, SpecializedEncoder,
23-
UseSpecializedDecodable};
23+
UseSpecializedDecodable, UseSpecializedEncodable};
2424
use session::{CrateDisambiguator, Session};
2525
use std::borrow::Cow;
2626
use std::cell::RefCell;
@@ -30,20 +30,25 @@ use syntax::ast::NodeId;
3030
use syntax::codemap::{CodeMap, StableFilemapId};
3131
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
3232
use ty;
33-
use ty::codec::{self as ty_codec, TyDecoder};
33+
use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
3434
use ty::context::TyCtxt;
3535
use ty::subst::Substs;
3636

3737
// Some magic values used for verifying that encoding and decoding. These are
3838
// basically random numbers.
3939
const PREV_DIAGNOSTICS_TAG: u64 = 0x1234_5678_A1A1_A1A1;
4040
const 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.
4647
pub 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

7079
type EncodedPrevDiagnostics = Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)>;
80+
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, usize)>;
7181

7282
impl<'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+
}

src/librustc_incremental/persist/load.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess
207207
}
208208

209209
if let Some((bytes, start_pos)) = load_data(sess, &query_cache_path(sess)) {
210-
OnDiskCache::new(sess, &bytes[..], start_pos)
210+
OnDiskCache::new(sess, bytes, start_pos)
211211
} else {
212212
OnDiskCache::new_empty(sess.codemap())
213213
}

0 commit comments

Comments
 (0)