From 9a5978966305fdb921982db365bf77ac22d090cf Mon Sep 17 00:00:00 2001 From: =?utf8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 20 Apr 2018 09:47:26 +0200 Subject: [PATCH] Store query jobs and query results in separate maps to reduce memory usage --- src/librustc/ty/maps/job.rs | 5 +---- src/librustc/ty/maps/on_disk_cache.rs | 17 ++++++----------- src/librustc/ty/maps/plumbing.rs | 26 ++++++++++++++++---------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/librustc/ty/maps/job.rs b/src/librustc/ty/maps/job.rs index 374406158c1..3b6af018d6b 100644 --- a/src/librustc/ty/maps/job.rs +++ b/src/librustc/ty/maps/job.rs @@ -17,13 +17,10 @@ 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>), - /// 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, } diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 6dfa72a3cf3..cea2a03fd53 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -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 diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index c3f3424600c..83305db57da 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -36,7 +36,8 @@ use syntax::codemap::DUMMY_SP; pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> { - pub(super) map: FxHashMap>>, + pub(super) results: FxHashMap>, + pub(super) active: FxHashMap>, } pub(super) struct QueryValue { @@ -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(); -- 2.44.0