Skip to content

Commit e8ef41e

Browse files
committed
Allow the QueryCache to specify storage.
1 parent fb5615a commit e8ef41e

File tree

5 files changed

+62
-39
lines changed

5 files changed

+62
-39
lines changed

src/librustc_middle/ty/query/plumbing.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ macro_rules! define_queries_inner {
328328
$(impl<$tcx> QueryConfig<TyCtxt<$tcx>> for queries::$name<$tcx> {
329329
type Key = $($K)*;
330330
type Value = $V;
331+
type Stored = <
332+
query_storage!([$($modifiers)*][$($K)*, $V])
333+
as QueryStorage
334+
>::Stored;
331335
const NAME: &'static str = stringify!($name);
332336
const CATEGORY: ProfileCategory = $category;
333337
}
@@ -426,8 +430,10 @@ macro_rules! define_queries_inner {
426430

427431
$($(#[$attr])*
428432
#[inline(always)]
429-
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
430-
self.at(DUMMY_SP).$name(key)
433+
pub fn $name(self, key: query_helper_param_ty!($($K)*))
434+
-> <queries::$name<$tcx> as QueryConfig<TyCtxt<$tcx>>>::Stored
435+
{
436+
self.at(DUMMY_SP).$name(key.into_query_param())
431437
})*
432438

433439
/// All self-profiling events generated by the query engine use
@@ -463,7 +469,9 @@ macro_rules! define_queries_inner {
463469
impl TyCtxtAt<$tcx> {
464470
$($(#[$attr])*
465471
#[inline(always)]
466-
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
472+
pub fn $name(self, key: query_helper_param_ty!($($K)*))
473+
-> <queries::$name<$tcx> as QueryConfig<TyCtxt<$tcx>>>::Stored
474+
{
467475
get_query::<queries::$name<'_>, _>(self.tcx, self.span, key.into_query_param())
468476
})*
469477
}

src/librustc_query_system/query/caches.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ use std::default::Default;
88
use std::hash::Hash;
99
use std::marker::PhantomData;
1010

11-
pub trait CacheSelector<K: Hash, V> {
12-
type Cache: QueryCache<Key = K, Value = V>;
11+
pub trait CacheSelector<K, V> {
12+
type Cache;
1313
}
1414

15-
pub trait QueryCache: Default {
16-
type Key: Hash;
15+
pub trait QueryStorage: Default {
1716
type Value;
17+
type Stored: Clone;
18+
19+
/// Store a value without putting it in the cache.
20+
/// This is meant to be used with cycle errors.
21+
fn store_nocache(&self, value: Self::Value) -> Self::Stored;
22+
}
23+
24+
pub trait QueryCache: QueryStorage {
25+
type Key: Hash;
1826
type Sharded: Default;
1927

2028
/// Checks if the query is already computed and in the cache.
@@ -30,7 +38,7 @@ pub trait QueryCache: Default {
3038
on_miss: OnMiss,
3139
) -> R
3240
where
33-
OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R,
41+
OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
3442
OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;
3543

3644
fn complete<CTX: QueryContext>(
@@ -40,7 +48,7 @@ pub trait QueryCache: Default {
4048
key: Self::Key,
4149
value: Self::Value,
4250
index: DepNodeIndex,
43-
);
51+
) -> Self::Stored;
4452

4553
fn iter<R, L>(
4654
&self,
@@ -66,9 +74,18 @@ impl<K, V> Default for DefaultCache<K, V> {
6674
}
6775
}
6876

77+
impl<K: Eq + Hash, V: Clone> QueryStorage for DefaultCache<K, V> {
78+
type Value = V;
79+
type Stored = V;
80+
81+
fn store_nocache(&self, value: Self::Value) -> Self::Stored {
82+
// We have no dedicated storage
83+
value
84+
}
85+
}
86+
6987
impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
7088
type Key = K;
71-
type Value = V;
7289
type Sharded = FxHashMap<K, (V, DepNodeIndex)>;
7390

7491
#[inline(always)]
@@ -99,8 +116,9 @@ impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
99116
key: K,
100117
value: V,
101118
index: DepNodeIndex,
102-
) {
103-
lock_sharded_storage.insert(key, (value, index));
119+
) -> Self::Stored {
120+
lock_sharded_storage.insert(key, (value.clone(), index));
121+
value
104122
}
105123

106124
fn iter<R, L>(

src/librustc_query_system/query/config.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ pub trait QueryConfig<CTX> {
2020
const CATEGORY: ProfileCategory;
2121

2222
type Key: Eq + Hash + Clone + Debug;
23-
type Value: Clone;
23+
type Value;
24+
type Stored: Clone;
2425
}
2526

2627
pub trait QueryAccessors<CTX: QueryContext>: QueryConfig<CTX> {
2728
const ANON: bool;
2829
const EVAL_ALWAYS: bool;
2930
const DEP_KIND: CTX::DepKind;
3031

31-
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
32+
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
3233

3334
// Don't use this method to access query results, instead use the methods on TyCtxt
3435
fn query_state<'a>(tcx: CTX) -> &'a QueryState<CTX, Self::Cache>;

src/librustc_query_system/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub use self::job::deadlock;
77
pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
88

99
mod caches;
10-
pub use self::caches::{CacheSelector, DefaultCacheSelector, QueryCache};
10+
pub use self::caches::{CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage};
1111

1212
mod config;
1313
pub use self::config::{QueryAccessors, QueryConfig, QueryDescription};

src/librustc_query_system/query/plumbing.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ struct JobOwner<'tcx, CTX: QueryContext, C>
148148
where
149149
C: QueryCache,
150150
C::Key: Eq + Hash + Clone + Debug,
151-
C::Value: Clone,
152151
{
153152
state: &'tcx QueryState<CTX, C>,
154153
key: C::Key,
@@ -159,7 +158,6 @@ impl<'tcx, CTX: QueryContext, C> JobOwner<'tcx, CTX, C>
159158
where
160159
C: QueryCache,
161160
C::Key: Eq + Hash + Clone + Debug,
162-
C::Value: Clone,
163161
{
164162
/// Either gets a `JobOwner` corresponding the query, allowing us to
165163
/// start executing the query, or returns with the result of the query.
@@ -177,7 +175,7 @@ where
177175
mut lookup: QueryLookup<'a, CTX, C::Key, C::Sharded>,
178176
) -> TryGetJob<'b, CTX, C>
179177
where
180-
Q: QueryDescription<CTX, Key = C::Key, Value = C::Value, Cache = C>,
178+
Q: QueryDescription<CTX, Key = C::Key, Stored = C::Stored, Value = C::Value, Cache = C>,
181179
CTX: QueryContext,
182180
{
183181
let lock = &mut *lookup.lock;
@@ -229,7 +227,8 @@ where
229227
// so we just return the error.
230228
#[cfg(not(parallel_compiler))]
231229
return TryGetJob::Cycle(cold_path(|| {
232-
Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span))
230+
let value = Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span));
231+
Q::query_state(tcx).cache.store_nocache(value)
233232
}));
234233

235234
// With parallel queries we might just have to wait on some other
@@ -239,7 +238,9 @@ where
239238
let result = latch.wait_on(tcx, span);
240239

241240
if let Err(cycle) = result {
242-
return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle));
241+
let value = Q::handle_cycle_error(tcx, cycle);
242+
let value = Q::query_state(tcx).cache.store_nocache(value);
243+
return TryGetJob::Cycle(value);
243244
}
244245

245246
let cached = try_get_cached(
@@ -261,26 +262,26 @@ where
261262
/// Completes the query by updating the query cache with the `result`,
262263
/// signals the waiter and forgets the JobOwner, so it won't poison the query
263264
#[inline(always)]
264-
fn complete(self, tcx: CTX, result: &C::Value, dep_node_index: DepNodeIndex) {
265+
fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
265266
// We can move out of `self` here because we `mem::forget` it below
266267
let key = unsafe { ptr::read(&self.key) };
267268
let state = self.state;
268269

269270
// Forget ourself so our destructor won't poison the query
270271
mem::forget(self);
271272

272-
let job = {
273-
let result = result.clone();
273+
let (job, result) = {
274274
let mut lock = state.shards.get_shard_by_value(&key).lock();
275275
let job = match lock.active.remove(&key).unwrap() {
276276
QueryResult::Started(job) => job,
277277
QueryResult::Poisoned => panic!(),
278278
};
279-
state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index);
280-
job
279+
let result = state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index);
280+
(job, result)
281281
};
282282

283283
job.signal_complete();
284+
result
284285
}
285286
}
286287

@@ -297,7 +298,6 @@ where
297298
impl<'tcx, CTX: QueryContext, C: QueryCache> Drop for JobOwner<'tcx, CTX, C>
298299
where
299300
C::Key: Eq + Hash + Clone + Debug,
300-
C::Value: Clone,
301301
{
302302
#[inline(never)]
303303
#[cold]
@@ -331,7 +331,6 @@ pub struct CycleError<Q> {
331331
enum TryGetJob<'tcx, CTX: QueryContext, C: QueryCache>
332332
where
333333
C::Key: Eq + Hash + Clone + Debug,
334-
C::Value: Clone,
335334
{
336335
/// The query is not yet started. Contains a guard to the cache eventually used to start it.
337336
NotYetStarted(JobOwner<'tcx, CTX, C>),
@@ -340,10 +339,10 @@ where
340339
/// Returns the result of the query and its dep-node index
341340
/// if it succeeded or a cycle error if it failed.
342341
#[cfg(parallel_compiler)]
343-
JobCompleted((C::Value, DepNodeIndex)),
342+
JobCompleted((C::Stored, DepNodeIndex)),
344343

345344
/// Trying to execute the query resulted in a cycle.
346-
Cycle(C::Value),
345+
Cycle(C::Stored),
347346
}
348347

349348
/// Checks if the query is already computed and in the cache.
@@ -362,7 +361,7 @@ fn try_get_cached<CTX, C, R, OnHit, OnMiss>(
362361
where
363362
C: QueryCache,
364363
CTX: QueryContext,
365-
OnHit: FnOnce(&C::Value, DepNodeIndex) -> R,
364+
OnHit: FnOnce(&C::Stored, DepNodeIndex) -> R,
366365
OnMiss: FnOnce(C::Key, QueryLookup<'_, CTX, C::Key, C::Sharded>) -> R,
367366
{
368367
state.cache.lookup(
@@ -388,7 +387,7 @@ fn try_execute_query<Q, CTX>(
388387
span: Span,
389388
key: Q::Key,
390389
lookup: QueryLookup<'_, CTX, Q::Key, <Q::Cache as QueryCache>::Sharded>,
391-
) -> Q::Value
390+
) -> Q::Stored
392391
where
393392
Q: QueryDescription<CTX>,
394393
CTX: QueryContext,
@@ -427,9 +426,7 @@ where
427426
tcx.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
428427
}
429428

430-
job.complete(tcx, &result, dep_node_index);
431-
432-
return result;
429+
return job.complete(tcx, result, dep_node_index);
433430
}
434431

435432
let dep_node = Q::to_dep_node(tcx, &key);
@@ -454,8 +451,7 @@ where
454451
})
455452
});
456453
if let Some((result, dep_node_index)) = loaded {
457-
job.complete(tcx, &result, dep_node_index);
458-
return result;
454+
return job.complete(tcx, result, dep_node_index);
459455
}
460456
}
461457

@@ -558,7 +554,7 @@ fn force_query_with_job<Q, CTX>(
558554
key: Q::Key,
559555
job: JobOwner<'_, CTX, Q::Cache>,
560556
dep_node: DepNode<CTX::DepKind>,
561-
) -> (Q::Value, DepNodeIndex)
557+
) -> (Q::Stored, DepNodeIndex)
562558
where
563559
Q: QueryDescription<CTX>,
564560
CTX: QueryContext,
@@ -603,13 +599,13 @@ where
603599
}
604600
}
605601

606-
job.complete(tcx, &result, dep_node_index);
602+
let result = job.complete(tcx, result, dep_node_index);
607603

608604
(result, dep_node_index)
609605
}
610606

611607
#[inline(never)]
612-
pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key) -> Q::Value
608+
pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key) -> Q::Stored
613609
where
614610
Q: QueryDescription<CTX>,
615611
CTX: QueryContext,

0 commit comments

Comments
 (0)