Skip to content

Commit

Permalink
Auto merge of #92681 - Aaron1011:task-deps-ref, r=cjgillot
Browse files Browse the repository at this point in the history
Introduce new `TaskDepsRef` enum to track allow/ignore/forbid status
  • Loading branch information
bors committed Jan 14, 2022
2 parents 86f7f78 + f64cd87 commit 02c9e73
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 61 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::ty::{self, TyCtxt};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock;
use rustc_query_system::ich::StableHashingContext;
use rustc_session::Session;

Expand All @@ -17,6 +16,7 @@ crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item};

pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>;
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
Expand Down Expand Up @@ -45,7 +45,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
write!(f, ")")
}

fn with_deps<OP, R>(task_deps: Option<&Lock<TaskDeps>>, op: OP) -> R
fn with_deps<OP, R>(task_deps: TaskDepsRef<'_>, op: OP) -> R
where
OP: FnOnce() -> R,
{
Expand All @@ -58,7 +58,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {

fn read_deps<OP>(op: OP)
where
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps>>),
OP: for<'a> FnOnce(TaskDepsRef<'a>),
{
ty::tls::with_context_opt(|icx| {
let icx = if let Some(icx) = icx { icx } else { return };
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
pub mod tls {
use super::{ptr_eq, GlobalCtxt, TyCtxt};

use crate::dep_graph::{DepKind, TaskDeps};
use crate::dep_graph::{DepKind, TaskDepsRef};
use crate::ty::query;
use rustc_data_structures::sync::{self, Lock};
use rustc_data_structures::thin_vec::ThinVec;
Expand Down Expand Up @@ -1697,13 +1697,19 @@ pub mod tls {

/// The current dep graph task. This is used to add dependencies to queries
/// when executing them.
pub task_deps: Option<&'a Lock<TaskDeps>>,
pub task_deps: TaskDepsRef<'a>,
}

impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
let tcx = TyCtxt { gcx };
ImplicitCtxt { tcx, query: None, diagnostics: None, layout_depth: 0, task_deps: None }
ImplicitCtxt {
tcx,
query: None,
diagnostics: None,
layout_depth: 0,
task_deps: TaskDepsRef::Ignore,
}
}
}

Expand Down
121 changes: 70 additions & 51 deletions compiler/rustc_query_system/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
use rustc_index::vec::IndexVec;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use smallvec::{smallvec, SmallVec};
use std::assert_matches::assert_matches;
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
Expand Down Expand Up @@ -165,7 +166,11 @@ impl<K: DepKind> DepGraph<K> {
pub fn assert_ignored(&self) {
if let Some(..) = self.data {
K::read_deps(|task_deps| {
assert!(task_deps.is_none(), "expected no task dependency tracking");
assert_matches!(
task_deps,
TaskDepsRef::Ignore,
"expected no task dependency tracking"
);
})
}
}
Expand All @@ -174,7 +179,7 @@ impl<K: DepKind> DepGraph<K> {
where
OP: FnOnce() -> R,
{
K::with_deps(None, op)
K::with_deps(TaskDepsRef::Ignore, op)
}

/// Used to wrap the deserialization of a query result from disk,
Expand Down Expand Up @@ -227,10 +232,7 @@ impl<K: DepKind> DepGraph<K> {
where
OP: FnOnce() -> R,
{
let mut deps = TaskDeps::default();
deps.read_allowed = false;
let deps = Lock::new(deps);
K::with_deps(Some(&deps), op)
K::with_deps(TaskDepsRef::Forbid, op)
}

/// Starts a new dep-graph task. Dep-graph tasks are specified
Expand Down Expand Up @@ -313,10 +315,15 @@ impl<K: DepKind> DepGraph<K> {
reads: SmallVec::new(),
read_set: Default::default(),
phantom_data: PhantomData,
read_allowed: true,
}))
};
let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));

let task_deps_ref = match &task_deps {
Some(deps) => TaskDepsRef::Allow(deps),
None => TaskDepsRef::Ignore,
};

let result = K::with_deps(task_deps_ref, || task(cx, arg));
let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);

let dcx = cx.dep_context();
Expand Down Expand Up @@ -369,7 +376,7 @@ impl<K: DepKind> DepGraph<K> {

if let Some(ref data) = self.data {
let task_deps = Lock::new(TaskDeps::default());
let result = K::with_deps(Some(&task_deps), op);
let result = K::with_deps(TaskDepsRef::Allow(&task_deps), op);
let task_deps = task_deps.into_inner();
let task_deps = task_deps.reads;

Expand Down Expand Up @@ -422,47 +429,47 @@ impl<K: DepKind> DepGraph<K> {
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
if let Some(ref data) = self.data {
K::read_deps(|task_deps| {
if let Some(task_deps) = task_deps {
let mut task_deps = task_deps.lock();
let task_deps = &mut *task_deps;

if !task_deps.read_allowed {
panic!("Illegal read of: {:?}", dep_node_index);
let mut task_deps = match task_deps {
TaskDepsRef::Allow(deps) => deps.lock(),
TaskDepsRef::Ignore => return,
TaskDepsRef::Forbid => {
panic!("Illegal read of: {:?}", dep_node_index)
}
};
let task_deps = &mut *task_deps;

if cfg!(debug_assertions) {
data.current.total_read_count.fetch_add(1, Relaxed);
}
if cfg!(debug_assertions) {
data.current.total_read_count.fetch_add(1, Relaxed);
}

// As long as we only have a low number of reads we can avoid doing a hash
// insert and potentially allocating/reallocating the hashmap
let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
task_deps.reads.iter().all(|other| *other != dep_node_index)
} else {
task_deps.read_set.insert(dep_node_index)
};
if new_read {
task_deps.reads.push(dep_node_index);
if task_deps.reads.len() == TASK_DEPS_READS_CAP {
// Fill `read_set` with what we have so far so we can use the hashset
// next time
task_deps.read_set.extend(task_deps.reads.iter().copied());
}
// As long as we only have a low number of reads we can avoid doing a hash
// insert and potentially allocating/reallocating the hashmap
let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
task_deps.reads.iter().all(|other| *other != dep_node_index)
} else {
task_deps.read_set.insert(dep_node_index)
};
if new_read {
task_deps.reads.push(dep_node_index);
if task_deps.reads.len() == TASK_DEPS_READS_CAP {
// Fill `read_set` with what we have so far so we can use the hashset
// next time
task_deps.read_set.extend(task_deps.reads.iter().copied());
}

#[cfg(debug_assertions)]
{
if let Some(target) = task_deps.node {
if let Some(ref forbidden_edge) = data.current.forbidden_edge {
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
if forbidden_edge.test(&src, &target) {
panic!("forbidden edge {:?} -> {:?} created", src, target)
}
#[cfg(debug_assertions)]
{
if let Some(target) = task_deps.node {
if let Some(ref forbidden_edge) = data.current.forbidden_edge {
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
if forbidden_edge.test(&src, &target) {
panic!("forbidden edge {:?} -> {:?} created", src, target)
}
}
}
} else if cfg!(debug_assertions) {
data.current.total_duplicate_read_count.fetch_add(1, Relaxed);
}
} else if cfg!(debug_assertions) {
data.current.total_duplicate_read_count.fetch_add(1, Relaxed);
}
})
}
Expand Down Expand Up @@ -1185,29 +1192,41 @@ impl<K: DepKind> CurrentDepGraph<K> {
const TASK_DEPS_READS_CAP: usize = 8;
type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>;

pub struct TaskDeps<K> {
#[derive(Debug, Clone, Copy)]
pub enum TaskDepsRef<'a, K: DepKind> {
/// New dependencies can be added to the
/// `TaskDeps`. This is used when executing a 'normal' query
/// (no `eval_always` modifier)
Allow(&'a Lock<TaskDeps<K>>),
/// New dependencies are ignored. This is used when
/// executing an `eval_always` query, since there's no
/// need to track dependencies for a query that's always
/// re-executed. This is also used for `dep_graph.with_ignore`
Ignore,
/// Any attempt to add new dependencies will cause a panic.
/// This is used when decoding a query result from disk,
/// to ensure that the decoding process doesn't itself
/// require the execution of any queries.
Forbid,
}

#[derive(Debug)]
pub struct TaskDeps<K: DepKind> {
#[cfg(debug_assertions)]
node: Option<DepNode<K>>,
reads: EdgesVec,
read_set: FxHashSet<DepNodeIndex>,
phantom_data: PhantomData<DepNode<K>>,
/// Whether or not we allow `DepGraph::read_index` to run.
/// This is normally true, except inside `with_query_deserialization`,
/// where it set to `false` to enforce that no new `DepNode` edges are
/// created. See the documentation of `with_query_deserialization` for
/// more details.
read_allowed: bool,
}

impl<K> Default for TaskDeps<K> {
impl<K: DepKind> Default for TaskDeps<K> {
fn default() -> Self {
Self {
#[cfg(debug_assertions)]
node: None,
reads: EdgesVec::new(),
read_set: FxHashSet::default(),
phantom_data: PhantomData,
read_allowed: true,
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_query_system/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ mod query;
mod serialized;

pub use dep_node::{DepNode, DepNodeParams, WorkProductId};
pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
pub use graph::{
hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct,
};
pub use query::DepGraphQuery;
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};

use crate::ich::StableHashingContext;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock;
use rustc_serialize::{opaque::FileEncoder, Encodable};
use rustc_session::Session;

Expand Down Expand Up @@ -90,12 +91,12 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable<FileEncoder>
fn debug_node(node: &DepNode<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result;

/// Execute the operation with provided dependencies.
fn with_deps<OP, R>(deps: Option<&Lock<TaskDeps<Self>>>, op: OP) -> R
fn with_deps<OP, R>(deps: TaskDepsRef<'_, Self>, op: OP) -> R
where
OP: FnOnce() -> R;

/// Access dependencies from current implicit context.
fn read_deps<OP>(op: OP)
where
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps<Self>>>);
OP: for<'a> FnOnce(TaskDepsRef<'a, Self>);
}

0 comments on commit 02c9e73

Please sign in to comment.