From af099bb2401bc9fe7aa753a20086d51c49816bcd Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Mar 2018 07:09:24 +0100 Subject: [PATCH] Cache const eval queries --- src/librustc/ty/maps/config.rs | 12 +++++ src/librustc/ty/maps/mod.rs | 2 +- src/librustc/ty/maps/on_disk_cache.rs | 68 +++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 21affcbc9ed..7e2ece1b334 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -156,6 +156,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> { fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String { format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())) } + + #[inline] + fn cache_on_disk(key: Self::Key) -> bool { + key.value.instance.def_id().is_local() + } + + #[inline] + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option { + tcx.on_disk_query_result_cache.load_constant(tcx, id).map(Ok) + } } impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 0ded759fec7..27eb7de2d06 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -82,7 +82,7 @@ pub use self::on_disk_cache::OnDiskCache; // the driver creates (using several `rustc_*` crates). // // The result of query must implement Clone. They must also implement ty::maps::values::Value -// which produces an appropiate error value if the query resulted in a query cycle. +// which produces an appropriate error value if the query resulted in a query cycle. // Queries marked with `fatal_cycle` do not need that implementation // as they will raise an fatal error on query cycles instead. define_maps! { <'tcx> diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 49c4b8bc49d..bb0b1975b9e 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -75,6 +75,10 @@ pub struct OnDiskCache<'sess> { // A map from dep-node to the position of any associated diagnostics in // `serialized_data`. prev_diagnostics_index: FxHashMap, + + // A map from dep-node to the position of any associated constants in + // `serialized_data`. + prev_constants_index: FxHashMap, } // This type is used only for (de-)serialization. @@ -84,8 +88,10 @@ struct Footer { prev_cnums: Vec<(u32, String, CrateDisambiguator)>, query_result_index: EncodedQueryResultIndex, diagnostics_index: EncodedQueryResultIndex, + constants_index: EncodedConstantsIndex, } +type EncodedConstantsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnostics = Vec; @@ -139,6 +145,7 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: RefCell::new(FxHashMap()), query_result_index: footer.query_result_index.into_iter().collect(), prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(), + prev_constants_index: footer.constants_index.into_iter().collect(), synthetic_expansion_infos: RefCell::new(FxHashMap()), } } @@ -154,6 +161,7 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: RefCell::new(FxHashMap()), query_result_index: FxHashMap(), prev_diagnostics_index: FxHashMap(), + prev_constants_index: FxHashMap(), synthetic_expansion_infos: RefCell::new(FxHashMap()), } } @@ -223,6 +231,45 @@ impl<'sess> OnDiskCache<'sess> { encode_query_results::(tcx, enc, qri)?; } + // encode successful constant evaluations + let constants_index = { + let mut constants_index = EncodedConstantsIndex::new(); + use ty::maps::queries::const_eval; + use ty::maps::plumbing::GetCacheInternal; + use ty::maps::config::QueryDescription; + for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() { + if let Ok(ref constant) = entry.value { + if const_eval::cache_on_disk(key.clone()) { + trace!("caching constant {:?} with value {:#?}", key, constant); + let dep_node = SerializedDepNodeIndex::new(entry.index.index()); + + // Record position of the cache entry + constants_index.push(( + dep_node, + AbsoluteBytePos::new(encoder.position()), + )); + let did = key.value.instance.def_id(); + let constant = if key.value.promoted.is_none() + && tcx.is_static(did).is_some() { + // memorize the allocation for the static, too, so + // we can refer to the static, not just read its value + // since we have had a successful query, the cached value must + // exist, so we can unwrap it + let cached = tcx.interpret_interner.get_cached(did).unwrap(); + (constant, Some(cached)) + } else { + (constant, None) + }; + + // Encode the type check tables with the SerializedDepNodeIndex + // as tag. + encoder.encode_tagged(dep_node, &constant)?; + } + } + } + constants_index + }; + // Encode diagnostics let diagnostics_index = { let mut diagnostics_index = EncodedDiagnosticsIndex::new(); @@ -256,6 +303,7 @@ impl<'sess> OnDiskCache<'sess> { prev_cnums, query_result_index, diagnostics_index, + constants_index, })?; // Encode the position of the footer as the last 8 bytes of the @@ -278,6 +326,25 @@ impl<'sess> OnDiskCache<'sess> { }) } + /// Load a constant emitted during the previous compilation session. + pub fn load_constant<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + dep_node_index: SerializedDepNodeIndex) + -> Option<&'tcx ty::Const<'tcx>> { + type Encoded<'tcx> = (ty::Const<'tcx>, Option); + let constant: Option> = self.load_indexed( + tcx, + dep_node_index, + &self.prev_constants_index, + "constants"); + + constant.map(|(c, _alloc_id)| { + // the AllocId decoding already registers the AllocId to its DefId + // so we don't need to take additional actions here + tcx.mk_const(c) + }) + } + /// Load a diagnostic emitted during the previous compilation session. pub fn load_diagnostics<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -563,6 +630,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder for CacheDecoder<'a, ' tcx.interpret_interner.intern_at_reserved(alloc_id, allocation); if let Some(glob) = Option::::decode(self)? { + trace!("connecting alloc {:?} with {:?}", alloc_id, glob); tcx.interpret_interner.cache(glob, alloc_id); }