Auto merge of #43584 - arielb1:unused-reads, r=eddyb

Fix quadratic performance with lots of use statements

This fixes 2 problems that caused quadratic performance when lots of use-statements were present. After this patch, performance is linear (and very fast) even with 1M uses.

Fixes #43572.
Fixes #43573.

r? @eddyb
This commit is contained in:
bors 2017-08-02 05:56:06 +00:00
commit 0b5c0874b8
3 changed files with 23 additions and 19 deletions

View File

@ -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<ast::NodeId, hir::HirId>,
macro_def_scopes: FxHashMap<Mark, DefId>,
expansions: FxHashMap<DefIndex, Mark>,
keys_created: FxHashSet<DefKey>,
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,20 +516,20 @@ 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 {
parent: Some(parent),
disambiguated_data: DisambiguatedDefPathData {
data,
disambiguator: 0
}
// 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
};
while self.keys_created.contains(&key) {
key.disambiguated_data.disambiguator += 1;
}
self.keys_created.insert(key.clone());
let key = DefKey {
parent: Some(parent),
disambiguated_data: DisambiguatedDefPathData {
data, disambiguator
}
};
let parent_hash = self.table.def_path_hash(parent);
let def_path_hash = key.compute_stable_hash(parent_hash);

View File

@ -561,8 +561,9 @@ impl CodeMapper for CodeMap {
sp
}
fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool {
let src = self.file_loader.read_file(Path::new(&file_map.name)).ok();
return file_map.add_external_src(src)
file_map.add_external_src(
|| self.file_loader.read_file(Path::new(&file_map.name)).ok()
)
}
}

View File

@ -618,8 +618,11 @@ impl FileMap {
/// If the hash of the input doesn't match or no input is supplied via None,
/// it is interpreted as an error and the corresponding enum variant is set.
/// The return value signifies whether some kind of source is present.
pub fn add_external_src(&self, src: Option<String>) -> bool {
pub fn add_external_src<F>(&self, get_src: F) -> bool
where F: FnOnce() -> Option<String>
{
if *self.external_src.borrow() == ExternalSource::AbsentOk {
let src = get_src();
let mut external_src = self.external_src.borrow_mut();
if let Some(src) = src {
let mut hasher: StableHasher<u128> = StableHasher::new();