Skip to content

Move the query system to a dedicated crate #70162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8c1c90b
Make QueryConfig argument a type.
cjgillot Mar 8, 2020
f74fd03
Make QueryAccessor argument a type.
cjgillot Mar 8, 2020
57c3177
Make QueryDescription parameter a type.
cjgillot Mar 8, 2020
c4a451e
Make QueryCache generic on the context.
cjgillot Mar 11, 2020
ee9781c
Make QueryContext a subtrait of DepContext.
cjgillot Mar 18, 2020
2a52436
Generalise QueryJobId.
cjgillot Mar 18, 2020
a51ad88
Decouple from DepKind.
cjgillot Mar 18, 2020
232364a
Generalise QueryLatch.
cjgillot Mar 18, 2020
63087b6
Parametrise by try_collect_active_jobs.
cjgillot Mar 19, 2020
42f0db5
Move HashStable bound to the trait definition.
cjgillot Mar 19, 2020
decfd70
Generalise try_get_cached.
cjgillot Mar 19, 2020
4ac4ccd
Generalise JobOwner::try_start.
cjgillot Mar 19, 2020
27e8a95
Generalise Query starting.
cjgillot Mar 19, 2020
6184a71
Make get_query into an extension trait.
cjgillot Mar 19, 2020
5b8dac3
Move query system to librustc_query_system.
cjgillot Mar 19, 2020
8e873c3
Make librustc_query_system compile.
cjgillot Mar 19, 2020
dca0344
Make librustc compile.
cjgillot Mar 19, 2020
301ad11
Rustfmt.
cjgillot Mar 26, 2020
d305b2c
Unify key types in get_lookup.
cjgillot Mar 24, 2020
228ca8e
Access QueryStateShard directly.
cjgillot Mar 24, 2020
b6033fc
Retire DepGraphSafe and HashStableContext.
cjgillot Mar 24, 2020
0e8b59a
Prune dependencies.
cjgillot Mar 24, 2020
fa06cfd
Move generics on QueryCache.
cjgillot Mar 24, 2020
5dfed41
Simplify generics on try_start.
cjgillot Mar 24, 2020
fce0d37
Add comment.
cjgillot Mar 24, 2020
d224e21
Rename read_query_job -> current_query_job and simplify it.
cjgillot Mar 25, 2020
260cfab
Don't allow access to the Session.
cjgillot Mar 25, 2020
4faf701
Remove the QueryGetter trait.
cjgillot Mar 27, 2020
db5be1f
Move QueryContext to the parent module.
cjgillot Mar 27, 2020
222d010
Cleanups.
cjgillot Mar 27, 2020
2d7bbda
Implement HashStable directly.
cjgillot Mar 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Parametrise by try_collect_active_jobs.
  • Loading branch information
cjgillot committed Mar 26, 2020
commit 63087b6b15bff0346fda199e1a077ab3cdc30ba3
11 changes: 8 additions & 3 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

use crate::dep_graph::SerializedDepNodeIndex;
use crate::ty::query::caches::QueryCache;
use crate::ty::query::job::QueryJobId;
use crate::ty::query::job::{QueryJobId, QueryJobInfo};
use crate::ty::query::plumbing::CycleError;
use crate::ty::query::QueryState;
use rustc_data_structures::profiling::ProfileCategory;
use rustc_hir::def_id::DefId;

use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_query_system::dep_graph::{DepContext, DepNode};
use rustc_session::Session;
use std::borrow::Cow;
Expand All @@ -24,7 +25,7 @@ pub trait QueryConfig<CTX> {
}

pub trait QueryContext: DepContext {
type Query;
type Query: Clone;

/// Access the session.
fn session(&self) -> &Session;
Expand All @@ -34,6 +35,10 @@ pub trait QueryContext: DepContext {

/// Get the query information from the TLS context.
fn read_query_job<R>(&self, op: impl FnOnce(Option<QueryJobId<Self::DepKind>>) -> R) -> R;

fn try_collect_active_jobs(
&self,
) -> Option<FxHashMap<QueryJobId<Self::DepKind>, QueryJobInfo<Self>>>;
}

pub(crate) trait QueryAccessors<CTX: QueryContext>: QueryConfig<CTX> {
Expand All @@ -56,7 +61,7 @@ pub(crate) trait QueryAccessors<CTX: QueryContext>: QueryConfig<CTX> {
result: &Self::Value,
) -> Option<Fingerprint>;

fn handle_cycle_error(tcx: CTX, error: CycleError<CTX>) -> Self::Value;
fn handle_cycle_error(tcx: CTX, error: CycleError<CTX::Query>) -> Self::Value;
}

pub(crate) trait QueryDescription<CTX: QueryContext>: QueryAccessors<CTX> {
Expand Down
120 changes: 59 additions & 61 deletions src/librustc/ty/query/job.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::dep_graph::DepKind;
use crate::ty::context::TyCtxt;
use crate::ty::query::config::QueryContext;
use crate::ty::query::plumbing::CycleError;
use crate::ty::query::Query;
#[cfg(parallel_compiler)]
use crate::ty::tls;

use rustc_data_structures::fx::FxHashMap;
use rustc_query_system::dep_graph::DepContext;
use rustc_span::Span;

use std::convert::TryFrom;
Expand All @@ -28,13 +27,13 @@ use {

/// Represents a span and a query key.
#[derive(Clone, Debug)]
pub struct QueryInfo<CTX: QueryContext> {
pub struct QueryInfo<Q> {
/// The span corresponding to the reason for which this query was required.
pub span: Span,
pub query: CTX::Query,
pub query: Q,
}

type QueryMap<'tcx> = FxHashMap<QueryJobId<DepKind>, QueryJobInfo<TyCtxt<'tcx>>>;
type QueryMap<CTX> = FxHashMap<QueryJobId<<CTX as DepContext>::DepKind>, QueryJobInfo<CTX>>;

/// A value uniquely identifiying an active query job within a shard in the query cache.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
Expand All @@ -53,35 +52,36 @@ pub struct QueryJobId<K> {
pub kind: K,
}

impl<K> QueryJobId<K> {
impl<K: rustc_query_system::dep_graph::DepKind> QueryJobId<K> {
pub fn new(job: QueryShardJobId, shard: usize, kind: K) -> Self {
QueryJobId { job, shard: u16::try_from(shard).unwrap(), kind }
}
}

impl QueryJobId<DepKind> {
fn query<'tcx>(self, map: &QueryMap<'tcx>) -> Query<'tcx> {
fn query<CTX: QueryContext<DepKind = K>>(self, map: &QueryMap<CTX>) -> CTX::Query {
map.get(&self).unwrap().info.query.clone()
}

#[cfg(parallel_compiler)]
fn span(self, map: &QueryMap<'_>) -> Span {
fn span<CTX: QueryContext<DepKind = K>>(self, map: &QueryMap<CTX>) -> Span {
map.get(&self).unwrap().job.span
}

#[cfg(parallel_compiler)]
fn parent(self, map: &QueryMap<'_>) -> Option<QueryJobId<DepKind>> {
fn parent<CTX: QueryContext<DepKind = K>>(self, map: &QueryMap<CTX>) -> Option<QueryJobId<K>> {
map.get(&self).unwrap().job.parent
}

#[cfg(parallel_compiler)]
fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<TyCtxt<'tcx>>> {
fn latch<'a, CTX: QueryContext<DepKind = K>>(
self,
map: &'a QueryMap<CTX>,
) -> Option<&'a QueryLatch<CTX>> {
map.get(&self).unwrap().job.latch.as_ref()
}
}

pub struct QueryJobInfo<CTX: QueryContext> {
pub info: QueryInfo<CTX>,
pub info: QueryInfo<CTX::Query>,
pub job: QueryJob<CTX>,
}

Expand Down Expand Up @@ -147,16 +147,12 @@ pub(super) struct QueryLatch<CTX: QueryContext> {
}

#[cfg(not(parallel_compiler))]
impl<'tcx> QueryLatch<TyCtxt<'tcx>> {
pub(super) fn find_cycle_in_stack(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
) -> CycleError<TyCtxt<'tcx>> {
let query_map = tcx.queries.try_collect_active_jobs().unwrap();
impl<CTX: QueryContext> QueryLatch<CTX> {
pub(super) fn find_cycle_in_stack(&self, tcx: CTX, span: Span) -> CycleError<CTX::Query> {
let query_map = tcx.try_collect_active_jobs().unwrap();

// Get the current executing query (waiter) and find the waitee amongst its parents
let mut current_job = tls::with_related_context(tcx, |icx| icx.query);
let mut current_job = tcx.read_query_job(|query| query);
let mut cycle = Vec::new();

while let Some(job) = current_job {
Expand Down Expand Up @@ -192,7 +188,7 @@ struct QueryWaiter<CTX: QueryContext> {
query: Option<QueryJobId<CTX::DepKind>>,
condvar: Condvar,
span: Span,
cycle: Lock<Option<CycleError<CTX>>>,
cycle: Lock<Option<CycleError<CTX::Query>>>,
}

#[cfg(parallel_compiler)]
Expand Down Expand Up @@ -225,13 +221,9 @@ impl<CTX: QueryContext> QueryLatch<CTX> {
}

#[cfg(parallel_compiler)]
impl<K, CTX> QueryLatch<CTX>
where
K: rustc_query_system::dep_graph::DepKind,
CTX: QueryContext<DepKind = K>,
{
impl<CTX: QueryContext> QueryLatch<CTX> {
/// Awaits for the query job to complete.
pub(super) fn wait_on(&self, tcx: CTX, span: Span) -> Result<(), CycleError<CTX>> {
pub(super) fn wait_on(&self, tcx: CTX, span: Span) -> Result<(), CycleError<CTX::Query>> {
tcx.read_query_job(move |query| {
let waiter = Lrc::new(QueryWaiter {
query,
Expand Down Expand Up @@ -299,7 +291,7 @@ impl<CTX: QueryContext> QueryLatch<CTX> {

/// A resumable waiter of a query. The usize is the index into waiters in the query's latch
#[cfg(parallel_compiler)]
type Waiter = (QueryJobId<DepKind>, usize);
type Waiter<K> = (QueryJobId<K>, usize);

/// Visits all the non-resumable and resumable waiters of a query.
/// Only waiters in a query are visited.
Expand All @@ -311,13 +303,13 @@ type Waiter = (QueryJobId<DepKind>, usize);
/// required information to resume the waiter.
/// If all `visit` calls returns None, this function also returns None.
#[cfg(parallel_compiler)]
fn visit_waiters<'tcx, F>(
query_map: &QueryMap<'tcx>,
query: QueryJobId<DepKind>,
fn visit_waiters<CTX: QueryContext, F>(
query_map: &QueryMap<CTX>,
query: QueryJobId<CTX::DepKind>,
mut visit: F,
) -> Option<Option<Waiter>>
) -> Option<Option<Waiter<CTX::DepKind>>>
where
F: FnMut(Span, QueryJobId<DepKind>) -> Option<Option<Waiter>>,
F: FnMut(Span, QueryJobId<CTX::DepKind>) -> Option<Option<Waiter<CTX::DepKind>>>,
{
// Visit the parent query which is a non-resumable waiter since it's on the same stack
if let Some(parent) = query.parent(query_map) {
Expand Down Expand Up @@ -346,13 +338,13 @@ where
/// If a cycle is detected, this initial value is replaced with the span causing
/// the cycle.
#[cfg(parallel_compiler)]
fn cycle_check<'tcx>(
query_map: &QueryMap<'tcx>,
query: QueryJobId<DepKind>,
fn cycle_check<CTX: QueryContext>(
query_map: &QueryMap<CTX>,
query: QueryJobId<CTX::DepKind>,
span: Span,
stack: &mut Vec<(Span, QueryJobId<DepKind>)>,
visited: &mut FxHashSet<QueryJobId<DepKind>>,
) -> Option<Option<Waiter>> {
stack: &mut Vec<(Span, QueryJobId<CTX::DepKind>)>,
visited: &mut FxHashSet<QueryJobId<CTX::DepKind>>,
) -> Option<Option<Waiter<CTX::DepKind>>> {
if !visited.insert(query) {
return if let Some(p) = stack.iter().position(|q| q.1 == query) {
// We detected a query cycle, fix up the initial span and return Some
Expand Down Expand Up @@ -387,10 +379,10 @@ fn cycle_check<'tcx>(
/// from `query` without going through any of the queries in `visited`.
/// This is achieved with a depth first search.
#[cfg(parallel_compiler)]
fn connected_to_root<'tcx>(
query_map: &QueryMap<'tcx>,
query: QueryJobId<DepKind>,
visited: &mut FxHashSet<QueryJobId<DepKind>>,
fn connected_to_root<CTX: QueryContext>(
query_map: &QueryMap<CTX>,
query: QueryJobId<CTX::DepKind>,
visited: &mut FxHashSet<QueryJobId<CTX::DepKind>>,
) -> bool {
// We already visited this or we're deliberately ignoring it
if !visited.insert(query) {
Expand All @@ -410,12 +402,12 @@ fn connected_to_root<'tcx>(

// Deterministically pick an query from a list
#[cfg(parallel_compiler)]
fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryJobId<DepKind>)>(
query_map: &QueryMap<'tcx>,
tcx: TyCtxt<'tcx>,
queries: &'a [T],
f: F,
) -> &'a T {
fn pick_query<'a, CTX, T, F>(query_map: &QueryMap<CTX>, tcx: CTX, queries: &'a [T], f: F) -> &'a T
where
CTX: QueryContext,
CTX::Query: HashStable<CTX::StableHashingContext>,
F: Fn(&T) -> (Span, QueryJobId<CTX::DepKind>),
{
// Deterministically pick an entry point
// FIXME: Sort this instead
let mut hcx = tcx.create_stable_hashing_context();
Expand All @@ -440,12 +432,15 @@ fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryJobId<DepKind>)>(
/// If a cycle was not found, the starting query is removed from `jobs` and
/// the function returns false.
#[cfg(parallel_compiler)]
fn remove_cycle<'tcx>(
query_map: &QueryMap<'tcx>,
jobs: &mut Vec<QueryJobId<DepKind>>,
wakelist: &mut Vec<Lrc<QueryWaiter<TyCtxt<'tcx>>>>,
tcx: TyCtxt<'tcx>,
) -> bool {
fn remove_cycle<CTX: QueryContext>(
query_map: &QueryMap<CTX>,
jobs: &mut Vec<QueryJobId<CTX::DepKind>>,
wakelist: &mut Vec<Lrc<QueryWaiter<CTX>>>,
tcx: CTX,
) -> bool
where
CTX::Query: HashStable<CTX::StableHashingContext>,
{
let mut visited = FxHashSet::default();
let mut stack = Vec::new();
// Look for a cycle starting with the last query in `jobs`
Expand Down Expand Up @@ -497,7 +492,7 @@ fn remove_cycle<'tcx>(
}
}
})
.collect::<Vec<(Span, QueryJobId<DepKind>, Option<(Span, QueryJobId<DepKind>)>)>>();
.collect::<Vec<(Span, QueryJobId<CTX::DepKind>, Option<(Span, QueryJobId<CTX::DepKind>)>)>>();

// Deterministically pick an entry point
let (_, entry_point, usage) = pick_query(query_map, tcx, &entry_points, |e| (e.0, e.1));
Expand Down Expand Up @@ -569,15 +564,18 @@ pub unsafe fn handle_deadlock() {
/// There may be multiple cycles involved in a deadlock, so this searches
/// all active queries for cycles before finally resuming all the waiters at once.
#[cfg(parallel_compiler)]
fn deadlock(tcx: TyCtxt<'_>, registry: &rayon_core::Registry) {
fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry)
where
CTX::Query: HashStable<CTX::StableHashingContext>,
{
let on_panic = OnDrop(|| {
eprintln!("deadlock handler panicked, aborting process");
process::abort();
});

let mut wakelist = Vec::new();
let query_map = tcx.queries.try_collect_active_jobs().unwrap();
let mut jobs: Vec<QueryJobId<DepKind>> = query_map.keys().cloned().collect();
let query_map = tcx.try_collect_active_jobs().unwrap();
let mut jobs: Vec<QueryJobId<CTX::DepKind>> = query_map.keys().cloned().collect();

let mut found_cycle = false;

Expand Down
16 changes: 11 additions & 5 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,10 @@ where
}

#[derive(Clone)]
pub(crate) struct CycleError<CTX: QueryContext> {
pub(crate) struct CycleError<Q> {
/// The query and related span that uses the cycle.
pub(super) usage: Option<(Span, CTX::Query)>,
pub(super) cycle: Vec<QueryInfo<CTX>>,
pub(super) usage: Option<(Span, Q)>,
pub(super) cycle: Vec<QueryInfo<Q>>,
}

/// The result of `try_start`.
Expand Down Expand Up @@ -371,6 +371,12 @@ impl QueryContext for TyCtxt<'tcx> {
fn read_query_job<R>(&self, op: impl FnOnce(Option<QueryJobId<Self::DepKind>>) -> R) -> R {
tls::with_related_context(*self, move |icx| op(icx.query))
}

fn try_collect_active_jobs(
&self,
) -> Option<FxHashMap<QueryJobId<Self::DepKind>, QueryJobInfo<Self>>> {
self.queries.try_collect_active_jobs()
}
}

impl<'tcx> TyCtxt<'tcx> {
Expand Down Expand Up @@ -409,7 +415,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[cold]
pub(super) fn report_cycle(
self,
CycleError { usage, cycle: stack }: CycleError<TyCtxt<'tcx>>,
CycleError { usage, cycle: stack }: CycleError<Query<'tcx>>,
) -> DiagnosticBuilder<'tcx> {
assert!(!stack.is_empty());

Expand Down Expand Up @@ -1033,7 +1039,7 @@ macro_rules! define_queries_inner {

fn handle_cycle_error(
tcx: TyCtxt<'tcx>,
error: CycleError<TyCtxt<'tcx>>
error: CycleError<Query<'tcx>>
) -> Self::Value {
handle_cycle_error!([$($modifiers)*][tcx, error])
}
Expand Down