Skip to content
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

Check that a query has not completed and is not executing before starting it #108845

Merged
merged 1 commit into from
Mar 12, 2023
Merged
Changes from all commits
Commits
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
27 changes: 21 additions & 6 deletions compiler/rustc_query_system/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_data_structures::profiling::TimingGuard;
#[cfg(parallel_compiler)]
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::sync::{Lock, LockGuard};
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
use rustc_session::Session;
use rustc_span::{Span, DUMMY_SP};
Expand Down Expand Up @@ -178,16 +178,13 @@ where
fn try_start<'b, Qcx>(
qcx: &'b Qcx,
state: &'b QueryState<K, Qcx::DepKind>,
mut state_lock: LockGuard<'b, FxHashMap<K, QueryResult<Qcx::DepKind>>>,
span: Span,
key: K,
) -> TryGetJob<'b, K, D>
where
Qcx: QueryContext + HasDepContext<DepKind = D>,
{
#[cfg(parallel_compiler)]
let mut state_lock = state.active.get_shard_by_value(&key).lock();
#[cfg(not(parallel_compiler))]
let mut state_lock = state.active.lock();
let lock = &mut *state_lock;
let current_job_id = qcx.current_query_job();

Expand Down Expand Up @@ -362,7 +359,25 @@ where
Qcx: QueryContext,
{
let state = query.query_state(qcx);
match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key) {
#[cfg(parallel_compiler)]
let state_lock = state.active.get_shard_by_value(&key).lock();
#[cfg(not(parallel_compiler))]
let state_lock = state.active.lock();

// For the parallel compiler we need to check both the query cache and query state structures
// while holding the state lock to ensure that 1) the query has not yet completed and 2) the
// query is not still executing. Without checking the query cache here, we can end up
// re-executing the query since `try_start` only checks that the query is not currently
// executing, but another thread may have already completed the query and stores it result
// in the query cache.
if cfg!(parallel_compiler) && qcx.dep_context().sess().threads() > 1 {
if let Some((value, index)) = query.query_cache(qcx).lookup(&key) {
qcx.dep_context().profiler().query_cache_hit(index.into());
return (value, Some(index));
}
}

match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, state_lock, span, key) {
TryGetJob::NotYetStarted(job) => {
let (result, dep_node_index) = execute_job(query, qcx, key.clone(), dep_node, job.id);
let cache = query.query_cache(qcx);
Expand Down