about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/dep_graph/graph.rs33
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs4
-rw-r--r--src/librustc/ty/maps/plumbing.rs55
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,
+);