diff options
| author | bors <bors@rust-lang.org> | 2017-11-24 21:50:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-11-24 21:50:09 +0000 |
| commit | a550f2d3b3d4eb57e7fcad284d60c4bea4aed687 (patch) | |
| tree | a036ae31b754a6c99717680be680bfe5f2bdb5d3 | |
| parent | 5f44c653cff61d0f55f53e07a188f755c7acddd1 (diff) | |
| parent | 0ea4b476509022def6a546aaa5630f273a6cc1d5 (diff) | |
| download | rust-a550f2d3b3d4eb57e7fcad284d60c4bea4aed687.tar.gz rust-a550f2d3b3d4eb57e7fcad284d60c4bea4aed687.zip | |
Auto merge of #46111 - michaelwoerister:promote-green, r=nikomatsakis
incr.comp.: Make sure we don't lose unused green results from the query cache. In its current implementation, the query result cache works by bulk-writing the results of all cacheable queries into a monolithic binary file on disk. Prior to this PR, we would potentially lose query results during this process because only results that had already been loaded into memory were serialized. In contrast, results that were not needed during the given compilation session were not serialized again. This PR will do one pass over all green `DepNodes` that represent a cacheable query and execute the corresponding query in order to make sure that the query result gets loaded into memory before cache serialization. In the future we might want to look into a serialization format the can be updated in-place so that we don't have to load unchanged results just for immediately storing them again. r? @nikomatsakis
| -rw-r--r-- | src/librustc/dep_graph/graph.rs | 33 | ||||
| -rw-r--r-- | src/librustc/ty/maps/on_disk_cache.rs | 4 | ||||
| -rw-r--r-- | src/librustc/ty/maps/plumbing.rs | 55 |
3 files changed, 92 insertions, 0 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 015cdd11bbd..32f40367fab 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -659,6 +659,39 @@ impl DepGraph { }).unwrap_or(false) } + // This method loads all on-disk cacheable query results into memory, so + // they can be written out to the new cache file again. Most query results + // will already be in memory but in the case where we marked something as + // green but then did not need the value, that value will never have been + // loaded from disk. + // + // 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<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let green_nodes: Vec<DepNode> = { + let data = self.data.as_ref().unwrap(); + data.colors.borrow().iter().filter_map(|(dep_node, color)| match color { + DepNodeColor::Green(_) => { + if dep_node.cache_on_disk(tcx) { + Some(*dep_node) + } else { + None + } + } + 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 + } + }).collect() + }; + + for dep_node in green_nodes { + dep_node.load_from_on_disk_cache(tcx); + } + } + pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { debug!("mark_loaded_from_cache({:?}, {})", self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index], diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 53ca9b3851d..6f55df76df4 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -197,6 +197,10 @@ impl<'sess> OnDiskCache<'sess> { encoder.encode_tagged(PREV_DIAGNOSTICS_TAG, &diagnostics)?; + // Load everything into memory so we can write it out to the on-disk + // cache. The vast majority of cacheable query results should already + // be in memory, so this should be a cheap operation. + tcx.dep_graph.exec_cache_promotions(tcx); // Encode query results let mut query_result_index = EncodedQueryResultIndex::new(); diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 739537c7c3a..c469991d848 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -898,3 +898,58 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, true } + + +// FIXME(#45015): Another piece of boilerplate code that could be generated in +// a combined define_dep_nodes!()/define_maps!() 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 ty::maps::queries; + use ty::maps::QueryDescription; + + match self.kind { + $(DepKind::$dep_kind => { + let def_id = self.extract_def_id(tcx).unwrap(); + queries::$query_name::cache_on_disk(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!( + TypeckTables => typeck_tables_of, + MirOptimized => optimized_mir, + UnsafetyCheckResult => unsafety_check_result, + BorrowCheck => borrowck, + MirBorrowCheck => mir_borrowck, + MirConstQualif => mir_const_qualif, +); |
