From d6986916aff9732f2ace0b6c12125c1849ac71d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 10 Mar 2019 10:11:15 +0100 Subject: [PATCH 1/4] Combine input and eval_always query types --- src/librustc/dep_graph/dep_node.rs | 74 +++++++++++------------------- src/librustc/dep_graph/graph.rs | 41 ++++------------- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/query/plumbing.rs | 10 ++-- 4 files changed, 44 insertions(+), 83 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 41a4a8031006f..509ccd7da3da5 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -85,11 +85,6 @@ macro_rules! is_anon_attr { ($attr:ident) => (false); } -macro_rules! is_input_attr { - (input) => (true); - ($attr:ident) => (false); -} - macro_rules! is_eval_always_attr { (eval_always) => (true); ($attr:ident) => (false); @@ -99,10 +94,6 @@ macro_rules! contains_anon_attr { ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); } -macro_rules! contains_input_attr { - ($($attr:ident),*) => ({$(is_input_attr!($attr) | )* false}); -} - macro_rules! contains_eval_always_attr { ($($attr:ident),*) => ({$(is_eval_always_attr!($attr) | )* false}); } @@ -151,7 +142,7 @@ macro_rules! define_dep_nodes { } } - // FIXME: Make `is_anon`, `is_input`, `is_eval_always` and `has_params` properties + // FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties // of queries #[inline(always)] pub fn is_anon(&self) -> bool { @@ -162,15 +153,6 @@ macro_rules! define_dep_nodes { } } - #[inline(always)] - pub fn is_input(&self) -> bool { - match *self { - $( - DepKind :: $variant => { contains_input_attr!($($attr),*) } - )* - } - } - #[inline(always)] pub fn is_eval_always(&self) -> bool { match *self { @@ -438,17 +420,17 @@ define_dep_nodes!( <'tcx> // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable // edges yourself for the individual items that you read. - [input] Krate, + [eval_always] Krate, // Represents the body of a function or method. The def-id is that of the // function/method. - [input] HirBody(DefId), + [eval_always] HirBody(DefId), // Represents the HIR node with the given node-id - [input] Hir(DefId), + [eval_always] Hir(DefId), // Represents metadata from an extern crate. - [input] CrateMetadata(CrateNum), + [eval_always] CrateMetadata(CrateNum), // Represents different phases in the compiler. [] RegionScopeTree(DefId), @@ -542,7 +524,7 @@ define_dep_nodes!( <'tcx> // The set of impls for a given trait. [] TraitImpls(DefId), - [input] AllLocalTraitImpls, + [eval_always] AllLocalTraitImpls, [anon] TraitSelect, @@ -555,7 +537,7 @@ define_dep_nodes!( <'tcx> // to make type debuginfo to be source location independent. Declaring // DefSpan an input makes sure that changes to these are always detected // regardless of HIR hashing. - [input] DefSpan(DefId), + [eval_always] DefSpan(DefId), [] LookupStability(DefId), [] LookupDeprecationEntry(DefId), [] ConstIsRvaluePromotableToStatic(DefId), @@ -574,11 +556,11 @@ define_dep_nodes!( <'tcx> [] IsCompilerBuiltins(CrateNum), [] HasGlobalAllocator(CrateNum), [] HasPanicHandler(CrateNum), - [input] ExternCrate(DefId), + [eval_always] ExternCrate(DefId), [eval_always] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, - [input] InScopeTraits(DefIndex), - [input] ModuleExports(DefId), + [eval_always] InScopeTraits(DefIndex), + [eval_always] ModuleExports(DefId), [] IsSanitizerRuntime(CrateNum), [] IsProfilerRuntime(CrateNum), [] GetPanicStrategy(CrateNum), @@ -592,10 +574,10 @@ define_dep_nodes!( <'tcx> [] EntryFn(CrateNum), [] PluginRegistrarFn(CrateNum), [] ProcMacroDeclsStatic(CrateNum), - [input] CrateDisambiguator(CrateNum), - [input] CrateHash(CrateNum), - [input] OriginalCrateName(CrateNum), - [input] ExtraFileName(CrateNum), + [eval_always] CrateDisambiguator(CrateNum), + [eval_always] CrateHash(CrateNum), + [eval_always] OriginalCrateName(CrateNum), + [eval_always] ExtraFileName(CrateNum), [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, [] AllTraitImplementations(CrateNum), @@ -604,7 +586,7 @@ define_dep_nodes!( <'tcx> [] IsDllimportForeignItem(DefId), [] IsStaticallyIncludedForeignItem(DefId), [] NativeLibraryKind(DefId), - [input] LinkArgs, + [eval_always] LinkArgs, [] ResolveLifetimes(CrateNum), [] NamedRegion(DefIndex), @@ -612,8 +594,8 @@ define_dep_nodes!( <'tcx> [] ObjectLifetimeDefaults(DefIndex), [] Visibility(DefId), - [input] DepKind(CrateNum), - [input] CrateName(CrateNum), + [eval_always] DepKind(CrateNum), + [eval_always] CrateName(CrateNum), [] ItemChildren(DefId), [] ExternModStmtCnum(DefId), [eval_always] GetLibFeatures, @@ -622,9 +604,9 @@ define_dep_nodes!( <'tcx> [] DefinedLangItems(CrateNum), [] MissingLangItems(CrateNum), [] VisibleParentMap, - [input] MissingExternCrateItem(CrateNum), - [input] UsedCrateSource(CrateNum), - [input] PostorderCnums, + [eval_always] MissingExternCrateItem(CrateNum), + [eval_always] UsedCrateSource(CrateNum), + [eval_always] PostorderCnums, // These queries are not expected to have inputs -- as a result, they // are not good candidates for "replay" because they are essentially @@ -634,20 +616,20 @@ define_dep_nodes!( <'tcx> // may save a bit of time. [anon] EraseRegionsTy { ty: Ty<'tcx> }, - [input] Freevars(DefId), - [input] MaybeUnusedTraitImport(DefId), - [input] MaybeUnusedExternCrates, - [input] NamesImportedByGlobUse(DefId), + [eval_always] Freevars(DefId), + [eval_always] MaybeUnusedTraitImport(DefId), + [eval_always] MaybeUnusedExternCrates, + [eval_always] NamesImportedByGlobUse(DefId), [eval_always] StabilityIndex, [eval_always] AllTraits, - [input] AllCrateNums, + [eval_always] AllCrateNums, [] ExportedSymbols(CrateNum), [eval_always] CollectAndPartitionMonoItems, [] IsCodegenedItem(DefId), [] CodegenUnit(InternedString), [] BackendOptimizationLevel(CrateNum), [] CompileCodegenUnit(InternedString), - [input] OutputFilenames, + [eval_always] OutputFilenames, [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>), [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>), [] ImpliedOutlivesBounds(CanonicalTyGoal<'tcx>), @@ -666,11 +648,11 @@ define_dep_nodes!( <'tcx> [] SubstituteNormalizeAndTestPredicates { key: (DefId, SubstsRef<'tcx>) }, [] MethodAutoderefSteps(CanonicalTyGoal<'tcx>), - [input] TargetFeaturesWhitelist, + [eval_always] TargetFeaturesWhitelist, [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> }, - [input] Features, + [eval_always] Features, [] ProgramClausesFor(DefId), [] ProgramClausesForEnv(traits::Environment<'tcx>), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8a2f79e6793c0..db81a9d826f8c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -388,10 +388,7 @@ impl DepGraph { |_| None, |data, key, fingerprint, _| { let mut current = data.borrow_mut(); - let krate_idx = current.node_to_node_index[ - &DepNode::new_no_params(DepKind::Krate) - ]; - current.alloc_node(key, smallvec![krate_idx], fingerprint) + current.alloc_node(key, smallvec![], fingerprint) }, hash_result) } @@ -576,7 +573,7 @@ impl DepGraph { tcx: TyCtxt<'_, '_, '_>, dep_node: &DepNode ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!dep_node.kind.is_input()); + debug_assert!(!dep_node.kind.is_eval_always()); // Return None if the dep graph is disabled let data = self.data.as_ref()?; @@ -620,8 +617,8 @@ impl DepGraph { debug_assert!(data.colors.get(prev_dep_node_index).is_none()); } - // We never try to mark inputs as green - debug_assert!(!dep_node.kind.is_input()); + // We never try to mark eval_always nodes as green + debug_assert!(!dep_node.kind.is_eval_always()); debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node); @@ -658,8 +655,8 @@ impl DepGraph { let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index); // We don't know the state of this dependency. If it isn't - // an input node, let's try to mark it green recursively. - if !dep_dep_node.kind.is_input() { + // an eval_always node, let's try to mark it green recursively. + if !dep_dep_node.kind.is_eval_always() { debug!("try_mark_previous_green({:?}) --- state of dependency {:?} \ is unknown, trying to mark it green", dep_node, dep_dep_node); @@ -694,7 +691,7 @@ impl DepGraph { } } _ => { - // For other kinds of inputs it's OK to be + // For other kinds of nodes it's OK to be // forced. } } @@ -1017,33 +1014,11 @@ impl CurrentDepGraph { task_deps: TaskDeps, fingerprint: Fingerprint ) -> DepNodeIndex { - // If this is an input node, we expect that it either has no - // dependencies, or that it just depends on DepKind::CrateMetadata - // or DepKind::Krate. This happens for some "thin wrapper queries" - // like `crate_disambiguator` which sometimes have zero deps (for - // when called for LOCAL_CRATE) or they depend on a CrateMetadata - // node. - if cfg!(debug_assertions) { - if node.kind.is_input() && task_deps.reads.len() > 0 && - // FIXME(mw): Special case for DefSpan until Spans are handled - // better in general. - node.kind != DepKind::DefSpan && - task_deps.reads.iter().any(|&i| { - !(self.data[i].node.kind == DepKind::CrateMetadata || - self.data[i].node.kind == DepKind::Krate) - }) - { - bug!("Input node {:?} with unexpected reads: {:?}", - node, - task_deps.reads.iter().map(|&i| self.data[i].node).collect::>()) - } - } - self.alloc_node(node, task_deps.reads, fingerprint) } fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { - debug_assert!(!kind.is_input()); + debug_assert!(!kind.is_eval_always()); let mut fingerprint = self.anon_id_seed; let mut hasher = StableHasher::new(); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 747e65ff4b55f..ba47880b9ec0a 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -153,7 +153,7 @@ impl Forest { &self.krate } - /// This is internally in the depedency tracking system. + /// This is used internally in the dependency tracking system. /// Use the `krate` method to ensure your dependency on the /// crate is tracked. pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index e3276ba0bea7b..9a4b038c549b4 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -415,7 +415,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return result; } - if !dep_node.kind.is_input() { + if !dep_node.kind.is_eval_always() { // The diagnostics for this query will be // promoted to the current session during // try_mark_green(), so we can ignore them here. @@ -602,9 +602,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub(super) fn ensure_query>(self, key: Q::Key) -> () { let dep_node = Q::to_dep_node(self, &key); - // Ensuring an "input" or anonymous query makes no sense + if dep_node.kind.is_eval_always() { + let _ = self.get_query::(DUMMY_SP, key); + return; + } + + // Ensuring an anonymous query makes no sense assert!(!dep_node.kind.is_anon()); - assert!(!dep_node.kind.is_input()); if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() { // A None return from `try_mark_green_and_read` means that this is either // a new dep node or that the dep node has already been marked red. From 31d28f45273b34f4e89448c9f96a5c8f520c1793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 14 Mar 2019 03:10:47 +0100 Subject: [PATCH 2/4] Make crate_variances a regular query --- src/librustc/dep_graph/dep_node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 509ccd7da3da5..e48b371bce7b1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -468,7 +468,7 @@ define_dep_nodes!( <'tcx> [] Reachability, [] MirKeys, - [eval_always] CrateVariances, + [] CrateVariances, // Nodes representing bits of computed IR in the tcx. Each shared // table in the tcx (or elsewhere) maps to one of these From 71152631a846039e8286b3108d20ef1e7135e916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 15 Mar 2019 12:17:11 +0100 Subject: [PATCH 3/4] Add an AtomicCell abstraction --- Cargo.lock | 41 +++++++++-------- src/librustc_data_structures/Cargo.toml | 1 + src/librustc_data_structures/sync.rs | 59 ++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27f7f59165b1b..9982c144c3f2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,7 +239,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "crates-io 0.24.0", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -568,13 +568,10 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -592,8 +589,8 @@ name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -612,12 +609,12 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -633,10 +630,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1122,7 +1120,7 @@ name = "ignore" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2235,7 +2233,7 @@ dependencies = [ "cargo 0.36.0", "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", - "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2672,6 +2670,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3585,7 +3584,7 @@ name = "tokio-executor" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3629,7 +3628,7 @@ name = "tokio-reactor" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3675,9 +3674,9 @@ name = "tokio-threadpool" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3690,7 +3689,7 @@ name = "tokio-timer" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4035,13 +4034,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" -"checksum crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2a9ea8f77c7f9efd317a8a5645f515d903a2d86ee14d2337a5facd1bd52c12" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 6002bf69b7069..dcf1294f1edca 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -18,6 +18,7 @@ rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } serialize = { path = "../libserialize" } graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" +crossbeam-utils = { version = "0.6.5", features = ["nightly"] } stable_deref_trait = "1.0.0" rayon = { version = "0.1.2", package = "rustc-rayon" } rayon-core = { version = "0.1.2", package = "rustc-rayon-core" } diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 73247c1469efd..b7dba80741700 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -67,6 +67,59 @@ cfg_if! { use std::ops::Add; use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; + #[derive(Debug)] + pub struct AtomicCell(Cell); + + impl AtomicCell { + #[inline] + pub fn new(v: T) -> Self { + AtomicCell(Cell::new(v)) + } + } + + impl AtomicCell { + pub fn into_inner(self) -> T { + self.0.into_inner() + } + + #[inline] + pub fn load(&self) -> T { + self.0.get() + } + + #[inline] + pub fn store(&self, val: T) { + self.0.set(val) + } + + pub fn swap(&self, val: T) -> T { + self.0.replace(val) + } + } + + impl AtomicCell { + pub fn compare_exchange(&self, + current: T, + new: T) + -> Result { + let read = self.0.get(); + if read == current { + self.0.set(new); + Ok(read) + } else { + Err(read) + } + } + } + + impl + Copy> AtomicCell { + pub fn fetch_add(&self, val: T) -> T { + let old = self.0.get(); + self.0.set(old + val); + old + } + } + #[derive(Debug)] pub struct Atomic(Cell); @@ -77,7 +130,7 @@ cfg_if! { } } - impl Atomic { + impl Atomic { pub fn into_inner(self) -> T { self.0.into_inner() } @@ -95,7 +148,9 @@ cfg_if! { pub fn swap(&self, val: T, _: Ordering) -> T { self.0.replace(val) } + } + impl Atomic { pub fn compare_exchange(&self, current: T, new: T, @@ -271,6 +326,8 @@ cfg_if! { pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; + pub use crossbeam_utils::atomic::AtomicCell; + pub use std::sync::Arc as Lrc; pub use std::sync::Weak as Weak; From 30e23f67db5ab1160ff5653ebb4c8fac528bd31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 10 Mar 2019 10:11:15 +0100 Subject: [PATCH 4/4] Turn HIR indexing into a query --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/dep_graph/graph.rs | 2 - src/librustc/hir/map/mod.rs | 36 ++++++++---------- src/librustc/ty/context.rs | 59 +++++++++++++++++++++--------- src/librustc/ty/query/config.rs | 6 +++ src/librustc/ty/query/mod.rs | 2 + src/librustc/ty/query/plumbing.rs | 15 ++++++-- src/librustc_interface/passes.rs | 25 +++++++++---- 8 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e48b371bce7b1..ae08eca76f307 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -440,6 +440,7 @@ define_dep_nodes!( <'tcx> [eval_always] PrivacyAccessLevels(CrateNum), [eval_always] CheckPrivateInPublic(CrateNum), [eval_always] Analysis(CrateNum), + [eval_always] HirMap(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index db81a9d826f8c..20b4af2aae996 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -675,8 +675,6 @@ impl DepGraph { } } else { match dep_dep_node.kind { - DepKind::Hir | - DepKind::HirBody | DepKind::CrateMetadata => { if dep_dep_node.extract_def_id(tcx).is_none() { // If the node does not exist anymore, we diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ba47880b9ec0a..168546d8a705c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -7,8 +7,6 @@ use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace}; -use crate::middle::cstore::CrateStoreDyn; - use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID}; @@ -1231,31 +1229,27 @@ impl Named for StructField { fn name(&self) -> Name { self.ident.name } } impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } -pub fn map_crate<'hir>(sess: &crate::session::Session, - cstore: &CrateStoreDyn, - forest: &'hir Forest, - definitions: &'hir Definitions) - -> Map<'hir> { +pub fn map_crate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Map<'tcx> { // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() + let hir_to_node_id = tcx.hir_defs.node_to_hir_id.iter_enumerated() .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); let (map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore); + let hcx = tcx.create_stable_hashing_context(); - let mut collector = NodeCollector::root(sess, - &forest.krate, - &forest.dep_graph, - &definitions, + let mut collector = NodeCollector::root(tcx.sess, + &tcx.hir_forest.untracked_krate(), + &tcx.dep_graph, + &tcx.hir_defs, &hir_to_node_id, hcx); - intravisit::walk_crate(&mut collector, &forest.krate); + intravisit::walk_crate(&mut collector, &tcx.hir_forest.untracked_krate()); - let crate_disambiguator = sess.local_crate_disambiguator(); - let cmdline_args = sess.opts.dep_tracking_hash(); + let crate_disambiguator = tcx.sess.local_crate_disambiguator(); + let cmdline_args = tcx.sess.opts.dep_tracking_hash(); collector.finalize_and_compute_crate_hash( crate_disambiguator, - cstore, + tcx.cstore, cmdline_args ) }; @@ -1273,15 +1267,15 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, } let map = Map { - forest, - dep_graph: forest.dep_graph.clone(), + forest: &tcx.hir_forest, + dep_graph: tcx.dep_graph.clone(), crate_hash, map, hir_to_node_id, - definitions, + definitions: &tcx.hir_defs, }; - time(sess, "validate hir map", || { + time(tcx.sess, "validate hir map", || { hir_id_validator::check_crate(&map); }); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ecf1d8a980a8d..23de592ebe4bd 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -50,8 +50,9 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; use arena::{TypedArena, SyncDroplessArena}; +use rustc_data_structures::cold_path; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal, AtomicCell}; use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; @@ -93,6 +94,8 @@ impl<'tcx> AllArenas<'tcx> { /// Internal storage #[derive(Default)] pub struct GlobalArenas<'tcx> { + pub hir_map: TypedArena>, + // internings layout: TypedArena, @@ -990,10 +993,10 @@ impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> { } pub struct GlobalCtxt<'tcx> { - global_arenas: &'tcx WorkerLocal>, + pub global_arenas: &'tcx WorkerLocal>, global_interners: CtxtInterners<'tcx>, - cstore: &'tcx CrateStoreDyn, + pub(crate) cstore: &'tcx CrateStoreDyn, pub sess: &'tcx Session, @@ -1011,7 +1014,11 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - hir_map: hir_map::Map<'tcx>, + pub hir_forest: hir::map::Forest, + + pub hir_defs: hir::map::Definitions, + + hir_map: AtomicCell>>, /// A map from DefPathHash -> DefId. Includes DefIds from the local crate /// as well as all upstream crates. Only populated in incremental mode. @@ -1085,7 +1092,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline(always)] pub fn hir(self) -> &'a hir_map::Map<'gcx> { - &self.hir_map + let value = self.hir_map.load(); + if unlikely!(value.is_none()) { + cold_path(|| { + let map = self.hir_map(LOCAL_CRATE); + self.hir_map.store(Some(map)); + map + }) + } else { + value.unwrap() + } } pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { @@ -1189,7 +1205,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas<'tcx>, resolutions: ty::Resolutions, - hir: hir_map::Map<'tcx>, + hir_forest: hir::map::Forest, + hir_defs: hir::map::Definitions, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, tx: mpsc::Sender>, @@ -1200,7 +1217,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }); let interners = CtxtInterners::new(&arenas.interner); let common_types = CommonTypes::new(&interners); - let dep_graph = hir.dep_graph.clone(); + let dep_graph = hir_forest.dep_graph.clone(); let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; @@ -1216,7 +1233,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { upstream_def_path_tables .iter() .map(|&(cnum, ref rc)| (cnum, &**rc)) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))) + .chain(iter::once((LOCAL_CRATE, hir_defs.def_path_table()))) }; // Precompute the capacity of the hashmap so we don't have to @@ -1239,7 +1256,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut trait_map: FxHashMap<_, Lrc>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { - let hir_id = hir.node_to_hir_id(k); + let hir_id = hir_defs.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); Lrc::get_mut(map).unwrap() .insert(hir_id.local_id, @@ -1258,23 +1275,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { (k, Lrc::new(v)) }).collect(), freevars: resolutions.freevars.into_iter().map(|(k, v)| { - (hir.local_def_id(k), Lrc::new(v)) + (hir_defs.local_def_id(k), Lrc::new(v)) }).collect(), maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports .into_iter() - .map(|id| hir.local_def_id(id)) + .map(|id| hir_defs.local_def_id(id)) .collect(), maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates .into_iter() - .map(|(id, sp)| (hir.local_def_id(id), sp)) + .map(|(id, sp)| (hir_defs.local_def_id(id), sp)) .collect(), glob_map: resolutions.glob_map.into_iter().map(|(id, names)| { - (hir.local_def_id(id), names) + (hir_defs.local_def_id(id), names) }).collect(), extern_prelude: resolutions.extern_prelude, - hir_map: hir, + hir_forest, + hir_defs, + hir_map: AtomicCell::new(None), def_path_hash_to_def_id, queries: query::Queries::new( providers, @@ -1369,7 +1388,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> hir_map::DefPath { if id.is_local() { - self.hir().def_path(id) + // FIXME: This is used in some panic path? Don't use hir() + self.hir_defs.def_path(id.index) } else { self.cstore.def_path(id) } @@ -1378,7 +1398,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { if def_id.is_local() { - self.hir().definitions().def_path_hash(def_id.index) + // FIXME: This is used when executing the hir query, can't use hir() here + self.hir_defs.def_path_hash(def_id.index) } else { self.cstore.def_path_hash(def_id) } @@ -1417,11 +1438,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'a> { - let krate = self.gcx.hir_map.forest.untracked_krate(); + // FIXME: This is used when executing the hir query, can't use hir() here. + // Also used when dealing with query cycles + let krate = self.hir_forest.untracked_krate(); StableHashingContext::new(self.sess, krate, - self.hir().definitions(), + &self.hir_defs, self.cstore) } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 6488c0db42bc5..88ea372e48a9c 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -623,6 +623,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::hir_map<'tcx> { + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "indexing HIR".into() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { "computing the lint levels for items in this crate".into() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 8804ed22264ce..ddde7a8733666 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -99,6 +99,8 @@ pub use self::on_disk_cache::OnDiskCache; // as they will raise an fatal error on query cycles instead. define_queries! { <'tcx> Other { + [no_hash] fn hir_map: HirMap(CrateNum) -> &'tcx hir::map::Map<'tcx>, + /// Run analysis passes on the crate [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 9a4b038c549b4..8517df734fb21 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1187,13 +1187,19 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, // FIXME(#45015): We should try move this boilerplate code into a macro // somehow. match dep_node.kind { + // Created by the Hir map query + DepKind::AllLocalTraitImpls | + DepKind::Krate => { + force!(hir_map, LOCAL_CRATE); + } + DepKind::HirBody | + DepKind::Hir => { + force!(hir_map, krate!()); + } + // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already - DepKind::AllLocalTraitImpls | - DepKind::Krate | DepKind::CrateMetadata | - DepKind::HirBody | - DepKind::Hir | // This are anonymous nodes DepKind::TraitSelect | @@ -1363,6 +1369,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); } DepKind::ExtraFileName => { force!(extra_filename, krate!()); } DepKind::Analysis => { force!(analysis, krate!()); } + DepKind::HirMap => { force!(hir_map, krate!()); } DepKind::AllTraitImplementations => { force!(all_trait_implementations, krate!()); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 5bb47bda17b33..e682787cd54dc 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -761,6 +761,7 @@ pub fn prepare_outputs( pub fn default_provide(providers: &mut ty::query::Providers) { providers.analysis = analysis; + providers.hir_map = hir_map; proc_macro_decls::provide(providers); plugin::build::provide(providers); hir::provide(providers); @@ -805,7 +806,7 @@ impl BoxedGlobalCtxt { pub fn create_global_ctxt( compiler: &Compiler, - mut hir_forest: hir::map::Forest, + hir_forest: hir::map::Forest, defs: hir::map::Definitions, resolutions: Resolutions, outputs: OutputFilenames, @@ -824,11 +825,6 @@ pub fn create_global_ctxt( let global_ctxt: Option>; let arenas = AllArenas::new(); - // Construct the HIR map - let hir_map = time(sess, "indexing hir", || { - hir::map::map_crate(sess, cstore, &mut hir_forest, &defs) - }); - let query_result_on_disk_cache = time(sess, "load query result cache", || { rustc_incremental::load_query_result_cache(sess) }); @@ -848,7 +844,8 @@ pub fn create_global_ctxt( extern_providers, &arenas, resolutions, - hir_map, + hir_forest, + defs, query_result_on_disk_cache, &crate_name, tx, @@ -877,6 +874,20 @@ pub fn create_global_ctxt( result } +fn hir_map<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + cnum: CrateNum, +) -> &'tcx hir::map::Map<'tcx> { + assert_eq!(cnum, LOCAL_CRATE); + + // Construct the HIR map + let hir_map = time(tcx.sess, "indexing hir", || { + hir::map::map_crate(tcx) + }); + + tcx.global_arenas.hir_map.alloc(hir_map) +} + /// Runs the resolution, type-checking, region checking and other /// miscellaneous analysis passes on the crate. fn analysis<'tcx>(