From 6f6fa8b9546e0b1005732caa774c39944325a63f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 21 Oct 2021 23:08:57 +0200 Subject: [PATCH] Use SortedMap in HIR. --- compiler/rustc_ast_lowering/src/index.rs | 24 ++++------------- compiler/rustc_ast_lowering/src/item.rs | 3 +-- compiler/rustc_ast_lowering/src/lib.rs | 18 +++++++------ .../rustc_data_structures/src/sorted_map.rs | 27 +++++++++++++++---- compiler/rustc_hir/src/hir.rs | 8 +++--- compiler/rustc_middle/src/hir/map/mod.rs | 24 +++++++---------- compiler/rustc_query_system/src/ich/hcx.rs | 6 ++--- .../rustc_query_system/src/ich/impls_hir.rs | 2 +- 8 files changed, 55 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index dc2b1a730fbd6..8a9dad2cdd7d8 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -1,4 +1,5 @@ use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions; @@ -9,14 +10,13 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; -use std::iter::repeat; use tracing::debug; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { /// Source map source_map: &'a SourceMap, - bodies: &'a IndexVec>>, + bodies: &'a SortedMap>, /// Outputs nodes: IndexVec>>, @@ -30,21 +30,11 @@ pub(super) struct NodeCollector<'a, 'hir> { definitions: &'a definitions::Definitions, } -fn insert_vec_map(map: &mut IndexVec>, k: K, v: V) { - let i = k.index(); - let len = map.len(); - if i >= len { - map.extend(repeat(None).take(i - len + 1)); - } - debug_assert!(map[k].is_none()); - map[k] = Some(v); -} - pub(super) fn index_hir<'hir>( sess: &Session, definitions: &definitions::Definitions, item: hir::OwnerNode<'hir>, - bodies: &IndexVec>>, + bodies: &SortedMap>, ) -> (IndexVec>>, FxHashMap) { let mut nodes = IndexVec::new(); // This node's parent should never be accessed: the owner's parent is computed by the @@ -94,11 +84,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - insert_vec_map( - &mut self.nodes, - hir_id.local_id, - ParentedNode { parent: self.parent_node, node: node }, - ); + self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node: node }); } fn with_parent(&mut self, parent_node_id: HirId, f: F) { @@ -144,7 +130,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_nested_body(&mut self, id: BodyId) { debug_assert_eq!(id.hir_id.owner, self.owner); - let body = self.bodies[id.hir_id.local_id].unwrap(); + let body = self.bodies[&id.hir_id.local_id]; self.visit_body(body); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e8747f2c5f8f9..63b20cd320b37 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -974,8 +974,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body = hir::Body { generator_kind: self.generator_kind, params, value }; let id = body.id(); debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner); - self.bodies.ensure_contains_elem(id.hir_id.local_id, || None); - self.bodies[id.hir_id.local_id] = Some(self.arena.alloc(body)); + self.bodies.push((id.hir_id.local_id, self.arena.alloc(body))); id } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 92e08da7a97ab..79464a7517217 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -44,6 +44,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability}; @@ -66,7 +67,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; -use std::collections::BTreeMap; use tracing::{debug, trace}; macro_rules! arena_vec { @@ -103,9 +103,9 @@ struct LoweringContext<'a, 'hir: 'a> { /// The items being lowered are collected here. owners: IndexVec>>, /// Bodies inside the owner being lowered. - bodies: IndexVec>>, + bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. - attrs: BTreeMap, + attrs: SortedMap, generator_kind: Option, @@ -300,8 +300,8 @@ pub fn lower_crate<'a, 'hir>( nt_to_tokenstream, arena, owners, - bodies: IndexVec::new(), - attrs: BTreeMap::default(), + bodies: Vec::new(), + attrs: SortedMap::new(), catch_scope: None, loop_scope: None, is_in_loop_condition: false, @@ -478,7 +478,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); - let bodies = std::mem::take(&mut self.bodies); + let mut bodies = std::mem::take(&mut self.bodies); let local_node_ids = std::mem::take(&mut self.local_node_ids); let trait_map = local_node_ids .into_iter() @@ -490,13 +490,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); #[cfg(debug_assertions)] - for (&id, attrs) in attrs.iter() { + for (id, attrs) in attrs.iter() { // Verify that we do not store empty slices in the map. if attrs.is_empty() { panic!("Stored empty attributes for {:?}", id); } } + bodies.sort_by_key(|(k, _)| *k); + let bodies = SortedMap::from_presorted_elements(bodies); let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies); let (nodes, parenting) = index::index_hir(self.sess, self.resolver.definitions(), node, &bodies); @@ -517,7 +519,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn hash_owner( &mut self, node: hir::OwnerNode<'hir>, - bodies: &IndexVec>>, + bodies: &SortedMap>, ) -> (Fingerprint, Fingerprint) { let mut hcx = self.resolver.create_stable_hashing_context(); let mut stable_hasher = StableHasher::new(); diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 20e2a3b9696e8..9efea1228ab29 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,3 +1,4 @@ +use crate::stable_hasher::{HashStable, StableHasher}; use std::borrow::Borrow; use std::cmp::Ordering; use std::iter::FromIterator; @@ -16,17 +17,26 @@ pub use index_map::SortedIndexMultiMap; /// stores data in a more compact way. It also supports accessing contiguous /// ranges of elements as a slice, and slices of already sorted elements can be /// inserted efficiently. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)] -pub struct SortedMap { +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +pub struct SortedMap { data: Vec<(K, V)>, } -impl SortedMap { +impl Default for SortedMap { + #[inline] + fn default() -> SortedMap { + SortedMap { data: Vec::new() } + } +} + +impl SortedMap { #[inline] - pub fn new() -> SortedMap { - SortedMap { data: vec![] } + pub const fn new() -> SortedMap { + SortedMap { data: Vec::new() } } +} +impl SortedMap { /// Construct a `SortedMap` from a presorted set of elements. This is faster /// than creating an empty map and then inserting the elements individually. /// @@ -281,5 +291,12 @@ impl FromIterator<(K, V)> for SortedMap { } } +impl, V: HashStable, CTX> HashStable for SortedMap { + #[inline] + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.data.hash_stable(ctx, hasher); + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6f25715fbecc4..a441a635c1eb3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -12,6 +12,7 @@ pub use rustc_ast::{CaptureBy, Movability, Mutability}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; @@ -22,7 +23,6 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; -use std::collections::BTreeMap; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] @@ -676,13 +676,13 @@ pub struct ParentedNode<'tcx> { /// Attributes owned by a HIR owner. #[derive(Debug)] pub struct AttributeMap<'tcx> { - pub map: BTreeMap, + pub map: SortedMap, pub hash: Fingerprint, } impl<'tcx> AttributeMap<'tcx> { pub const EMPTY: &'static AttributeMap<'static> = - &AttributeMap { map: BTreeMap::new(), hash: Fingerprint::ZERO }; + &AttributeMap { map: SortedMap::new(), hash: Fingerprint::ZERO }; #[inline] pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { @@ -705,7 +705,7 @@ pub struct OwnerNodes<'tcx> { // used. pub nodes: IndexVec>>, /// Content of local bodies. - pub bodies: IndexVec>>, + pub bodies: SortedMap>, } /// Full information resulting from lowering an AST node. diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index fad7e875fa1c0..8f52e16c2ebe4 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -376,7 +376,7 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[id.hir_id.local_id].unwrap() + self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { @@ -495,13 +495,10 @@ impl<'hir> Map<'hir> { .iter_enumerated() .flat_map(move |(owner, owner_info)| { let bodies = &owner_info.as_ref()?.nodes.bodies; - Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| { - if body.is_none() { - return None; - } + Some(bodies.iter().map(move |&(local_id, _)| { let hir_id = HirId { owner, local_id }; let body_id = BodyId { hir_id }; - Some(self.body_owner_def_id(body_id)) + self.body_owner_def_id(body_id) })) }) .flatten() @@ -515,13 +512,10 @@ impl<'hir> Map<'hir> { par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| { let owner = LocalDefId::new(owner); if let Some(owner_info) = owner_info { - par_iter(&owner_info.nodes.bodies.raw).enumerate().for_each(|(local_id, body)| { - if body.is_some() { - let local_id = ItemLocalId::new(local_id); - let hir_id = HirId { owner, local_id }; - let body_id = BodyId { hir_id }; - f(self.body_owner_def_id(body_id)) - } + par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { + let hir_id = HirId { owner, local_id: *local_id }; + let body_id = BodyId { hir_id }; + f(self.body_owner_def_id(body_id)) }) } }); @@ -578,8 +572,8 @@ impl<'hir> Map<'hir> { let krate = self.krate(); for (owner, info) in krate.owners.iter_enumerated() { if let Some(info) = info { - for (&local_id, attrs) in info.attrs.map.iter() { - let id = HirId { owner, local_id }; + for (local_id, attrs) in info.attrs.map.iter() { + let id = HirId { owner, local_id: *local_id }; for a in *attrs { visitor.visit_attribute(id, a) } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index cfef2073373cc..5f31fa04b8a6e 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,12 +1,12 @@ use crate::ich; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::{DefPathHash, Definitions}; -use rustc_index::vec::IndexVec; use rustc_session::cstore::CrateStore; use rustc_session::Session; use rustc_span::source_map::SourceMap; @@ -51,7 +51,7 @@ pub(super) enum BodyResolver<'tcx> { Traverse { hash_bodies: bool, owner: LocalDefId, - bodies: &'tcx IndexVec>>, + bodies: &'tcx SortedMap>, }, } @@ -122,7 +122,7 @@ impl<'a> StableHashingContext<'a> { &mut self, hash_bodies: bool, owner: LocalDefId, - bodies: &'a IndexVec>>, + bodies: &'a SortedMap>, f: impl FnOnce(&mut Self), ) { let prev = self.body_resolver; diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs index 24f3a2e7de0a9..3a0aab81fdb7b 100644 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -33,7 +33,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { BodyResolver::Traverse { hash_bodies: false, .. } => {} BodyResolver::Traverse { hash_bodies: true, owner, bodies } => { assert_eq!(id.hir_id.owner, owner); - bodies[id.hir_id.local_id].unwrap().hash_stable(hcx, hasher); + bodies[&id.hir_id.local_id].hash_stable(hcx, hasher); } } }