Store query jobs and query results in separate maps to reduce memory usage
This commit is contained in:
parent
987631d3ba
commit
9a59789663
3 changed files with 23 additions and 25 deletions
|
|
@ -17,13 +17,10 @@ use ty::context::TyCtxt;
|
|||
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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ use syntax::codemap::{CodeMap, StableFilemapId};
|
|||
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 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ use syntax_pos::Span;
|
|||
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 @@ impl<T> QueryValue<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 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
|
|||
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 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
|
|||
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 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
|
|||
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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue