about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-09 07:09:24 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-13 15:57:59 +0100
commitaf099bb2401bc9fe7aa753a20086d51c49816bcd (patch)
tree55179c08f796e904ebf863b499e777dbb87c15f3
parente65547d4fad0425d1db4f33a4d8134bf2cad939e (diff)
downloadrust-af099bb2401bc9fe7aa753a20086d51c49816bcd.tar.gz
rust-af099bb2401bc9fe7aa753a20086d51c49816bcd.zip
Cache const eval queries
-rw-r--r--src/librustc/ty/maps/config.rs12
-rw-r--r--src/librustc/ty/maps/mod.rs2
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs68
3 files changed, 81 insertions, 1 deletions
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index 21affcbc9ed..7e2ece1b334 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -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> {
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 0ded759fec7..27eb7de2d06 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -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>
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index 49c4b8bc49d..bb0b1975b9e 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -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);
                 }