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] 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>(