Skip to content

Commit af099bb

Browse files
committed
Cache const eval queries
1 parent e65547d commit af099bb

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

src/librustc/ty/maps/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
156156
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
157157
format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id()))
158158
}
159+
160+
#[inline]
161+
fn cache_on_disk(key: Self::Key) -> bool {
162+
key.value.instance.def_id().is_local()
163+
}
164+
165+
#[inline]
166+
fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
167+
id: SerializedDepNodeIndex)
168+
-> Option<Self::Value> {
169+
tcx.on_disk_query_result_cache.load_constant(tcx, id).map(Ok)
170+
}
159171
}
160172

161173
impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {

src/librustc/ty/maps/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub use self::on_disk_cache::OnDiskCache;
8282
// the driver creates (using several `rustc_*` crates).
8383
//
8484
// The result of query must implement Clone. They must also implement ty::maps::values::Value
85-
// which produces an appropiate error value if the query resulted in a query cycle.
85+
// which produces an appropriate error value if the query resulted in a query cycle.
8686
// Queries marked with `fatal_cycle` do not need that implementation
8787
// as they will raise an fatal error on query cycles instead.
8888
define_maps! { <'tcx>

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ pub struct OnDiskCache<'sess> {
7575
// A map from dep-node to the position of any associated diagnostics in
7676
// `serialized_data`.
7777
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
78+
79+
// A map from dep-node to the position of any associated constants in
80+
// `serialized_data`.
81+
prev_constants_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7882
}
7983

8084
// This type is used only for (de-)serialization.
@@ -84,8 +88,10 @@ struct Footer {
8488
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
8589
query_result_index: EncodedQueryResultIndex,
8690
diagnostics_index: EncodedQueryResultIndex,
91+
constants_index: EncodedConstantsIndex,
8792
}
8893

94+
type EncodedConstantsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
8995
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
9096
type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
9197
type EncodedDiagnostics = Vec<Diagnostic>;
@@ -139,6 +145,7 @@ impl<'sess> OnDiskCache<'sess> {
139145
current_diagnostics: RefCell::new(FxHashMap()),
140146
query_result_index: footer.query_result_index.into_iter().collect(),
141147
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
148+
prev_constants_index: footer.constants_index.into_iter().collect(),
142149
synthetic_expansion_infos: RefCell::new(FxHashMap()),
143150
}
144151
}
@@ -154,6 +161,7 @@ impl<'sess> OnDiskCache<'sess> {
154161
current_diagnostics: RefCell::new(FxHashMap()),
155162
query_result_index: FxHashMap(),
156163
prev_diagnostics_index: FxHashMap(),
164+
prev_constants_index: FxHashMap(),
157165
synthetic_expansion_infos: RefCell::new(FxHashMap()),
158166
}
159167
}
@@ -223,6 +231,45 @@ impl<'sess> OnDiskCache<'sess> {
223231
encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
224232
}
225233

234+
// encode successful constant evaluations
235+
let constants_index = {
236+
let mut constants_index = EncodedConstantsIndex::new();
237+
use ty::maps::queries::const_eval;
238+
use ty::maps::plumbing::GetCacheInternal;
239+
use ty::maps::config::QueryDescription;
240+
for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() {
241+
if let Ok(ref constant) = entry.value {
242+
if const_eval::cache_on_disk(key.clone()) {
243+
trace!("caching constant {:?} with value {:#?}", key, constant);
244+
let dep_node = SerializedDepNodeIndex::new(entry.index.index());
245+
246+
// Record position of the cache entry
247+
constants_index.push((
248+
dep_node,
249+
AbsoluteBytePos::new(encoder.position()),
250+
));
251+
let did = key.value.instance.def_id();
252+
let constant = if key.value.promoted.is_none()
253+
&& tcx.is_static(did).is_some() {
254+
// memorize the allocation for the static, too, so
255+
// we can refer to the static, not just read its value
256+
// since we have had a successful query, the cached value must
257+
// exist, so we can unwrap it
258+
let cached = tcx.interpret_interner.get_cached(did).unwrap();
259+
(constant, Some(cached))
260+
} else {
261+
(constant, None)
262+
};
263+
264+
// Encode the type check tables with the SerializedDepNodeIndex
265+
// as tag.
266+
encoder.encode_tagged(dep_node, &constant)?;
267+
}
268+
}
269+
}
270+
constants_index
271+
};
272+
226273
// Encode diagnostics
227274
let diagnostics_index = {
228275
let mut diagnostics_index = EncodedDiagnosticsIndex::new();
@@ -256,6 +303,7 @@ impl<'sess> OnDiskCache<'sess> {
256303
prev_cnums,
257304
query_result_index,
258305
diagnostics_index,
306+
constants_index,
259307
})?;
260308

261309
// Encode the position of the footer as the last 8 bytes of the
@@ -278,6 +326,25 @@ impl<'sess> OnDiskCache<'sess> {
278326
})
279327
}
280328

329+
/// Load a constant emitted during the previous compilation session.
330+
pub fn load_constant<'a, 'tcx>(&self,
331+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
332+
dep_node_index: SerializedDepNodeIndex)
333+
-> Option<&'tcx ty::Const<'tcx>> {
334+
type Encoded<'tcx> = (ty::Const<'tcx>, Option<interpret::AllocId>);
335+
let constant: Option<Encoded<'tcx>> = self.load_indexed(
336+
tcx,
337+
dep_node_index,
338+
&self.prev_constants_index,
339+
"constants");
340+
341+
constant.map(|(c, _alloc_id)| {
342+
// the AllocId decoding already registers the AllocId to its DefId
343+
// so we don't need to take additional actions here
344+
tcx.mk_const(c)
345+
})
346+
}
347+
281348
/// Load a diagnostic emitted during the previous compilation session.
282349
pub fn load_diagnostics<'a, 'tcx>(&self,
283350
tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -563,6 +630,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, '
563630
tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
564631

565632
if let Some(glob) = Option::<DefId>::decode(self)? {
633+
trace!("connecting alloc {:?} with {:?}", alloc_id, glob);
566634
tcx.interpret_interner.cache(glob, alloc_id);
567635
}
568636

0 commit comments

Comments
 (0)