1
Fork 0

Cache const eval queries

This commit is contained in:
Oliver Schneider 2018-03-09 07:09:24 +01:00
parent e65547d4fa
commit af099bb240
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
3 changed files with 81 additions and 1 deletions

View file

@ -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<Self::Value> {
tcx.on_disk_query_result_cache.load_constant(tcx, id).map(Ok)
}
}
impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {

View file

@ -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>

View file

@ -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<SerializedDepNodeIndex, AbsoluteBytePos>,
// A map from dep-node to the position of any associated constants in
// `serialized_data`.
prev_constants_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
}
// 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<Diagnostic>;
@ -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::<trans_fn_attrs, _>(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<interpret::AllocId>);
let constant: Option<Encoded<'tcx>> = 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<interpret::AllocId> for CacheDecoder<'a, '
tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
if let Some(glob) = Option::<DefId>::decode(self)? {
trace!("connecting alloc {:?} with {:?}", alloc_id, glob);
tcx.interpret_interner.cache(glob, alloc_id);
}