Skip to content
Permalink
Browse files

Clean up query cache code

  • Loading branch information...
Zoxc committed Apr 5, 2019
1 parent 3467e21 commit 930ad86e3d4524b10547c35b23b95d593c751214
@@ -842,31 +842,20 @@ impl DepGraph {
// This method will only load queries that will end up in the disk cache.
// Other queries will not be executed.
pub fn exec_cache_promotions<'tcx>(&self, tcx: TyCtxt<'tcx>) {
let green_nodes: Vec<DepNode> = {
let data = self.data.as_ref().unwrap();
data.colors.values.indices().filter_map(|prev_index| {
match data.colors.get(prev_index) {
Some(DepNodeColor::Green(_)) => {
let dep_node = data.previous.index_to_node(prev_index);
if dep_node.cache_on_disk(tcx) {
Some(dep_node)
} else {
None
}
}
None |
Some(DepNodeColor::Red) => {
// We can skip red nodes because a node can only be marked
// as red if the query result was recomputed and thus is
// already in memory.
None
}
let data = self.data.as_ref().unwrap();
for prev_index in data.colors.values.indices() {
match data.colors.get(prev_index) {
Some(DepNodeColor::Green(_)) => {
let dep_node = data.previous.index_to_node(prev_index);
dep_node.try_load_from_on_disk_cache(tcx);
}
}).collect()
};

for dep_node in green_nodes {
dep_node.load_from_on_disk_cache(tcx);
None |
Some(DepNodeColor::Red) => {
// We can skip red nodes because a node can only be marked
// as red if the query result was recomputed and thus is
// already in memory.
}
}
}
}

@@ -18,7 +18,7 @@ use errors::DiagnosticBuilder;
use syntax_pos::{Pos, Span};
use syntax::symbol::Symbol;

#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
pub enum ErrorHandled {
/// Already reported a lint or an error for this evaluation.
Reported,
@@ -2,7 +2,7 @@ use crate::ty::query::QueryDescription;
use crate::ty::query::queries;
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use crate::ty::subst::SubstsRef;
use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::{RecoverKey,DepKind, DepNode, SerializedDepNodeIndex};
use crate::hir::def_id::{CrateNum, DefId, DefIndex};
use crate::mir;
use crate::mir::interpret::GlobalId;
@@ -33,13 +33,13 @@ rustc_queries! {
Other {
/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
cache { key.is_local() }
cache_on_disk_if { key.is_local() }
}

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
/// associated generics.
query generics_of(key: DefId) -> &'tcx ty::Generics {
cache { key.is_local() }
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
@@ -62,7 +62,9 @@ rustc_queries! {
/// predicate gets in the way of some checks, which are intended
/// to operate over only the actual where-clauses written by the
/// user.)
query predicates_of(_: DefId) -> &'tcx ty::GenericPredicates<'tcx> {}
query predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
cache_on_disk_if { key.is_local() }
}

query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
desc { "looking up the native libraries of a linked crate" }
@@ -93,7 +95,7 @@ rustc_queries! {
/// of the MIR qualify_consts pass. The actual meaning of
/// the value isn't known except to the pass itself.
query mir_const_qualif(key: DefId) -> (u8, &'tcx BitSet<mir::Local>) {
cache { key.is_local() }
cache_on_disk_if { key.is_local() }
}

/// Fetch the MIR for a given `DefId` right after it's built - this includes
@@ -115,7 +117,7 @@ rustc_queries! {
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
cache { key.is_local() }
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
@@ -285,7 +287,9 @@ rustc_queries! {

TypeChecking {
/// The result of unsafety-checking this `DefId`.
query unsafety_check_result(_: DefId) -> mir::UnsafetyCheckResult {}
query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult {
cache_on_disk_if { key.is_local() }
}

/// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
query unsafe_derive_on_repr_packed(_: DefId) -> () {}
@@ -348,7 +352,7 @@ rustc_queries! {
}

query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
cache { key.is_local() }
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
.queries.on_disk_cache
@@ -360,7 +364,9 @@ rustc_queries! {
}

Other {
query used_trait_imports(_: DefId) -> &'tcx DefIdSet {}
query used_trait_imports(key: DefId) -> &'tcx DefIdSet {
cache_on_disk_if { key.is_local() }
}
}

TypeChecking {
@@ -372,11 +378,15 @@ rustc_queries! {
}

BorrowChecking {
query borrowck(_: DefId) -> &'tcx BorrowCheckResult {}
query borrowck(key: DefId) -> &'tcx BorrowCheckResult {
cache_on_disk_if { key.is_local() }
}

/// Borrow-checks the function body. If this is a closure, returns
/// additional requirements that the closure's creator must verify.
query mir_borrowck(_: DefId) -> mir::BorrowCheckResult<'tcx> {}
query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> {
cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) }
}
}

TypeChecking {
@@ -412,9 +422,10 @@ rustc_queries! {
"const-evaluating `{}`",
tcx.def_path_str(key.value.instance.def.def_id())
}
cache { true }
load_cached(tcx, id) {
tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
cache_on_disk_if(_, opt_result) {
// Only store results without errors
// FIXME: We never store these
opt_result.map_or(true, |r| r.is_ok())
}
}

@@ -427,9 +438,9 @@ rustc_queries! {
"const-evaluating + checking `{}`",
tcx.def_path_str(key.value.instance.def.def_id())
}
cache { true }
load_cached(tcx, id) {
tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
cache_on_disk_if(_, opt_result) {
// Only store results without errors
opt_result.map_or(true, |r| r.is_ok())
}
}

@@ -453,7 +464,9 @@ rustc_queries! {
}

TypeChecking {
query check_match(_: DefId) -> () {}
query check_match(key: DefId) -> () {
cache_on_disk_if { key.is_local() }
}

/// Performs part of the privacy check and computes "access levels".
query privacy_access_levels(_: CrateNum) -> &'tcx AccessLevels {
@@ -483,7 +496,6 @@ rustc_queries! {
query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
no_force
desc { "computing the symbol for `{}`", key }
cache { true }
}

query def_kind(_: DefId) -> Option<DefKind> {}
@@ -501,7 +513,9 @@ rustc_queries! {
}

Codegen {
query codegen_fn_attrs(_: DefId) -> CodegenFnAttrs {}
query codegen_fn_attrs(_: DefId) -> CodegenFnAttrs {
cache_on_disk_if { true }
}
}

Other {
@@ -519,7 +533,7 @@ rustc_queries! {
"const checking if rvalue is promotable to static `{}`",
tcx.def_path_str(key)
}
cache { true }
cache_on_disk_if { true }
}
query rvalue_promotable_map(key: DefId) -> &'tcx ItemLocalSet {
desc { |tcx|
@@ -548,7 +562,6 @@ rustc_queries! {
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
) -> Vtable<'tcx, ()> {
no_force
cache { true }
desc { |tcx|
"checking if `{}` fulfills its obligations",
tcx.def_path_str(key.1.def_id())
@@ -560,7 +573,9 @@ rustc_queries! {
query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls {
desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
}
query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {}
query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {
cache_on_disk_if { true }
}
query is_object_safe(key: DefId) -> bool {
desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
}
@@ -55,7 +55,7 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
fn describe(tcx: TyCtxt<'_>, key: Self::Key) -> Cow<'static, str>;

#[inline]
fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key) -> bool {
fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
false
}

@@ -80,33 +80,3 @@ impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
"running analysis passes on this crate".into()
}
}

macro_rules! impl_disk_cacheable_query(
($query_name:ident, |$tcx:tt, $key:tt| $cond:expr) => {
impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
#[inline]
fn cache_on_disk($tcx: TyCtxt<'tcx>, $key: Self::Key) -> bool {
$cond
}

#[inline]
fn try_load_from_disk(tcx: TyCtxt<'tcx>,
id: SerializedDepNodeIndex)
-> Option<Self::Value> {
tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
}
}
}
);

impl_disk_cacheable_query!(mir_borrowck, |tcx, def_id| {
def_id.is_local() && tcx.is_closure(def_id)
});

impl_disk_cacheable_query!(unsafety_check_result, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(borrowck, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(used_trait_imports, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(codegen_fn_attrs, |_, _| true);
impl_disk_cacheable_query!(specialization_graph_of, |_, _| true);
@@ -221,26 +221,8 @@ impl<'sess> OnDiskCache<'sess> {
encode_query_results::<check_match<'_>, _>(tcx, enc, qri)?;
encode_query_results::<codegen_fn_attrs<'_>, _>(tcx, enc, qri)?;
encode_query_results::<specialization_graph_of<'_>, _>(tcx, enc, qri)?;

// const eval is special, it only encodes successfully evaluated constants
use crate::ty::query::QueryAccessors;
let cache = const_eval::query_cache(tcx).borrow();
assert!(cache.active.is_empty());
for (key, entry) in cache.results.iter() {
use crate::ty::query::config::QueryDescription;
if const_eval::cache_on_disk(tcx, key.clone()) {
if let Ok(ref value) = entry.value {
let dep_node = SerializedDepNodeIndex::new(entry.index.index());

// Record position of the cache entry
qri.push((dep_node, AbsoluteBytePos::new(enc.position())));

// Encode the type check tables with the SerializedDepNodeIndex
// as tag.
enc.encode_tagged(dep_node, value)?;
}
}
}
encode_query_results::<const_eval<'_>, _>(tcx, enc, qri)?;
// FIXME: Include const_eval_raw?

Ok(())
})?;
@@ -1090,7 +1072,7 @@ where
let map = Q::query_cache(tcx).borrow();
assert!(map.active.is_empty());
for (key, entry) in map.results.iter() {
if Q::cache_on_disk(tcx, key.clone()) {
if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) {
let dep_node = SerializedDepNodeIndex::new(entry.index.index());

// Record position of the cache entry
@@ -444,7 +444,7 @@ impl<'tcx> TyCtxt<'tcx> {
debug_assert!(self.dep_graph.is_green(dep_node));

// First we try to load the result from the on-disk cache
let result = if Q::cache_on_disk(self.global_tcx(), key.clone()) &&
let result = if Q::cache_on_disk(self.global_tcx(), key.clone(), None) &&
self.sess.opts.debugging_opts.incremental_queries {
self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME));
let result = Q::try_load_from_disk(self.global_tcx(), prev_dep_node_index);
@@ -1243,66 +1243,3 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool

true
}


// FIXME(#45015): Another piece of boilerplate code that could be generated in
// a combined define_dep_nodes!()/define_queries!() macro.
macro_rules! impl_load_from_cache {
($($dep_kind:ident => $query_name:ident,)*) => {
impl DepNode {
// Check whether the query invocation corresponding to the given
// DepNode is eligible for on-disk-caching.
pub fn cache_on_disk(&self, tcx: TyCtxt<'_>) -> bool {
use crate::ty::query::queries;
use crate::ty::query::QueryDescription;

match self.kind {
$(DepKind::$dep_kind => {
let def_id = self.extract_def_id(tcx).unwrap();
queries::$query_name::cache_on_disk(tcx.global_tcx(), def_id)
})*
_ => false
}
}

// This is method will execute the query corresponding to the given
// DepNode. It is only expected to work for DepNodes where the
// above `cache_on_disk` methods returns true.
// Also, as a sanity check, it expects that the corresponding query
// invocation has been marked as green already.
pub fn load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
match self.kind {
$(DepKind::$dep_kind => {
debug_assert!(tcx.dep_graph
.node_color(self)
.map(|c| c.is_green())
.unwrap_or(false));

let def_id = self.extract_def_id(tcx).unwrap();
let _ = tcx.$query_name(def_id);
})*
_ => {
bug!()
}
}
}
}
}
}

impl_load_from_cache!(
typeck_tables_of => typeck_tables_of,
optimized_mir => optimized_mir,
unsafety_check_result => unsafety_check_result,
borrowck => borrowck,
mir_borrowck => mir_borrowck,
mir_const_qualif => mir_const_qualif,
const_is_rvalue_promotable_to_static => const_is_rvalue_promotable_to_static,
check_match => check_match,
type_of => type_of,
generics_of => generics_of,
predicates_of => predicates_of,
used_trait_imports => used_trait_imports,
codegen_fn_attrs => codegen_fn_attrs,
specialization_graph_of => specialization_graph_of,
);

0 comments on commit 930ad86

Please sign in to comment.
You can’t perform that action at this time.