Skip to content

Commit

Permalink
Reuse the query caching infrastructure for const eval
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Mar 13, 2018
1 parent af099bb commit 0d88db1
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 61 deletions.
6 changes: 3 additions & 3 deletions src/librustc/ty/maps/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,15 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
}

#[inline]
fn cache_on_disk(key: Self::Key) -> bool {
key.value.instance.def_id().is_local()
fn cache_on_disk(_key: Self::Key) -> bool {
true
}

#[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)
tcx.on_disk_query_result_cache.try_load_query_result(tcx, id).map(Ok)
}
}

Expand Down
63 changes: 7 additions & 56 deletions src/librustc/ty/maps/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ 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.
Expand All @@ -88,10 +84,8 @@ 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>;
Expand Down Expand Up @@ -145,7 +139,6 @@ 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()),
}
}
Expand All @@ -161,7 +154,6 @@ 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()),
}
}
Expand Down Expand Up @@ -229,46 +221,25 @@ impl<'sess> OnDiskCache<'sess> {
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
encode_query_results::<check_match, _>(tcx, enc, qri)?;
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;
// const eval is special, it only encodes successfully evaluated constants
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);
use ty::maps::config::QueryDescription;
if const_eval::cache_on_disk(key.clone()) {
if let Ok(ref value) = entry.value {
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)
};
qri.push((dep_node, AbsoluteBytePos::new(enc.position())));

// Encode the type check tables with the SerializedDepNodeIndex
// as tag.
encoder.encode_tagged(dep_node, &constant)?;
enc.encode_tagged(dep_node, value)?;
}
}
}
constants_index
};
}

// Encode diagnostics
let diagnostics_index = {
Expand Down Expand Up @@ -303,7 +274,6 @@ 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
Expand All @@ -326,25 +296,6 @@ 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>,
Expand Down
8 changes: 6 additions & 2 deletions src/librustc_mir/interpret/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
span = mir.span;
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
let alloc = tcx.interpret_interner.get_cached(cid.instance.def_id());
let is_static = tcx.is_static(cid.instance.def_id()).is_some();
let alloc = match alloc {
Some(alloc) => {
assert!(cid.promoted.is_none());
Expand All @@ -123,7 +124,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
layout.align,
None,
)?;
if tcx.is_static(cid.instance.def_id()).is_some() {
if is_static {
tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id);
}
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
Expand Down Expand Up @@ -151,8 +152,11 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
}
};
let ptr = MemoryPointer::new(alloc, 0).into();
// always try to read the value and report errors
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
Some(val) => val,
// if it's a constant (so it needs no address, directly compute its value)
Some(val) if !is_static => val,
// point at the allocation
_ => Value::ByRef(ptr, layout.align),
};
Ok((value, ptr, layout.ty))
Expand Down

0 comments on commit 0d88db1

Please sign in to comment.