From 70478ca5c83513beb91cce78ae57ade70849fca4 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 1 Aug 2017 14:44:20 +0300 Subject: [PATCH] rustc::hir::map::definitions - fix O(n^2) when disambiguating Instead of finding the next free disambiguator by incrementing it until you find a place, store the next available disambiguator in an hash-map. This avoids O(n^2) performance when lots of items have the same un-disambiguated `DefPathData` - e.g. all `use` items have `DefPathData::Misc`. --- src/librustc/hir/map/definitions.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 91bce64243e3f..cdd5a6e3da7f1 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -18,7 +18,7 @@ use hir; use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace, CRATE_DEF_INDEX}; use ich::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::StableHasher; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -153,7 +153,7 @@ pub struct Definitions { pub(super) node_to_hir_id: IndexVec, macro_def_scopes: FxHashMap, expansions: FxHashMap, - keys_created: FxHashSet, + next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>, } // Unfortunately we have to provide a manual impl of Clone because of the @@ -170,7 +170,7 @@ impl Clone for Definitions { node_to_hir_id: self.node_to_hir_id.clone(), macro_def_scopes: self.macro_def_scopes.clone(), expansions: self.expansions.clone(), - keys_created: self.keys_created.clone(), + next_disambiguator: self.next_disambiguator.clone(), } } } @@ -402,7 +402,7 @@ impl Definitions { node_to_hir_id: IndexVec::new(), macro_def_scopes: FxHashMap(), expansions: FxHashMap(), - keys_created: FxHashSet(), + next_disambiguator: FxHashMap(), } } @@ -516,21 +516,21 @@ impl Definitions { // The root node must be created with create_root_def() assert!(data != DefPathData::CrateRoot); - // Find a unique DefKey. This basically means incrementing the disambiguator - // until we get no match. - let mut key = DefKey { + // Find the next free disambiguator for this key. + let disambiguator = { + let next_disamb = self.next_disambiguator.entry((parent, data.clone())).or_insert(0); + let disambiguator = *next_disamb; + *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); + disambiguator + }; + + let key = DefKey { parent: Some(parent), disambiguated_data: DisambiguatedDefPathData { - data, - disambiguator: 0 + data, disambiguator } }; - while self.keys_created.contains(&key) { - key.disambiguated_data.disambiguator += 1; - } - self.keys_created.insert(key.clone()); - let parent_hash = self.table.def_path_hash(parent); let def_path_hash = key.compute_stable_hash(parent_hash);