]> git.lizzy.rs Git - rust.git/commitdiff
Store query jobs and query results in separate maps to reduce memory usage
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Fri, 20 Apr 2018 07:47:26 +0000 (09:47 +0200)
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Fri, 27 Apr 2018 10:09:59 +0000 (12:09 +0200)
src/librustc/ty/maps/job.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs

index 374406158c1d51a5695dfd0ae615e4dd686d1e8c..3b6af018d6b789d839c4bb2a2f84781bc867cc9a 100644 (file)
 use errors::Diagnostic;
 
 /// Indicates the state of a query for a given key in a query map
-pub(super) enum QueryResult<'tcx, T> {
+pub(super) enum QueryResult<'tcx> {
     /// An already executing query. The query job can be used to await for its completion
     Started(Lrc<QueryJob<'tcx>>),
 
-    /// The query is complete and produced `T`
-    Complete(T),
-
     /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic
     Poisoned,
 }
index 6dfa72a3cf3f33ff622b1cabc466f0136bcc8c6c..cea2a03fd532c58c3ea572c5c90c6ffe2567de14 100644 (file)
@@ -30,7 +30,6 @@
 use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap};
 use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
 use ty;
-use ty::maps::job::QueryResult;
 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use ty::context::TyCtxt;
 use util::common::time;
@@ -240,13 +239,11 @@ pub fn serialize<'a, 'tcx, E>(&self,
 
                 // const eval is special, it only encodes successfully evaluated constants
                 use ty::maps::QueryConfig;
-                for (key, entry) in const_eval::query_map(tcx).borrow().map.iter() {
+                let map = const_eval::query_map(tcx).borrow();
+                assert!(map.active.is_empty());
+                for (key, entry) in map.results.iter() {
                     use ty::maps::config::QueryDescription;
                     if const_eval::cache_on_disk(key.clone()) {
-                        let entry = match *entry {
-                            QueryResult::Complete(ref v) => v,
-                            _ => panic!("incomplete query"),
-                        };
                         if let Ok(ref value) = entry.value {
                             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
@@ -1133,12 +1130,10 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     time(tcx.sess, desc, || {
 
-    for (key, entry) in Q::query_map(tcx).borrow().map.iter() {
+    let map = Q::query_map(tcx).borrow();
+    assert!(map.active.is_empty());
+    for (key, entry) in map.results.iter() {
         if Q::cache_on_disk(key.clone()) {
-            let entry = match *entry {
-                QueryResult::Complete(ref v) => v,
-                _ => panic!("incomplete query"),
-            };
             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
             // Record position of the cache entry
index c3f3424600ca9e4be3302e3c8728e0e866df9f85..83305db57dad7960f93acb0e78ad430b08760c42 100644 (file)
@@ -36,7 +36,8 @@
 use syntax::codemap::DUMMY_SP;
 
 pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> {
-    pub(super) map: FxHashMap<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
+    pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
+    pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
 }
 
 pub(super) struct QueryValue<T> {
@@ -58,7 +59,8 @@ pub(super) fn new(value: T,
 impl<'tcx, M: QueryConfig<'tcx>> QueryMap<'tcx, M> {
     pub(super) fn new() -> QueryMap<'tcx, M> {
         QueryMap {
-            map: FxHashMap(),
+            results: FxHashMap(),
+            active: FxHashMap(),
         }
     }
 }
@@ -111,15 +113,15 @@ pub(super) fn try_get(
         let map = Q::query_map(tcx);
         loop {
             let mut lock = map.borrow_mut();
-            let job = match lock.map.entry((*key).clone()) {
+            if let Some(value) = lock.results.get(key) {
+                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                let result = Ok((value.value.clone(), value.index));
+                return TryGetJob::JobCompleted(result);
+            }
+            let job = match lock.active.entry((*key).clone()) {
                 Entry::Occupied(entry) => {
                     match *entry.get() {
                         QueryResult::Started(ref job) => job.clone(),
-                        QueryResult::Complete(ref value) => {
-                            profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                            let result = Ok((value.value.clone(), value.index));
-                            return TryGetJob::JobCompleted(result);
-                        },
                         QueryResult::Poisoned => FatalError.raise(),
                     }
                 }
@@ -161,7 +163,11 @@ pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
         mem::forget(self);
 
         let value = QueryValue::new(result.clone(), dep_node_index);
-        map.borrow_mut().map.insert(key, QueryResult::Complete(value));
+        {
+            let mut lock = map.borrow_mut();
+            lock.active.remove(&key);
+            lock.results.insert(key, value);
+        }
 
         job.signal_complete();
     }
@@ -205,7 +211,7 @@ pub(super) fn start<'lcx, F, R>(
 impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
     fn drop(&mut self) {
         // Poison the query so jobs waiting on it panic
-        self.map.borrow_mut().map.insert(self.key.clone(), QueryResult::Poisoned);
+        self.map.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned);
         // Also signal the completion of the job, so waiters
         // will continue execution
         self.job.signal_complete();