diff options
| author | bors <bors@rust-lang.org> | 2016-04-17 19:11:20 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-04-17 19:11:20 -0700 |
| commit | 63760acf31e605c8a91bb5cbcbcb4bfb95435e48 (patch) | |
| tree | 26ee481c87ddb93c740d43ad775d49fe7dbdba13 | |
| parent | ed7c56796ef17f13227a50dc1a72a018b1d5e33f (diff) | |
| parent | 6ae80273a08c9cb0b75b8aec464f1e7d838a2bda (diff) | |
| download | rust-63760acf31e605c8a91bb5cbcbcb4bfb95435e48.tar.gz rust-63760acf31e605c8a91bb5cbcbcb4bfb95435e48.zip | |
Auto merge of #33064 - jseyfried:improve_resolve_performance, r=eddyb
resolve: Improve performance This fixes #33061 by speeding up searchs through all traits in scope, a bottleneck in `resolve`. According to my measurements, this PR improves resolution performance by a factor of 3.4x on `librustc`, which almost completely reverses the 3.75x performance regression reported in #33061. r? @eddyb
| -rw-r--r-- | src/librustc_resolve/lib.rs | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f32cf7aa9f4..c01d9ba5312 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -848,6 +848,9 @@ pub struct ModuleS<'a> { glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>, globs: RefCell<Vec<&'a ImportDirective<'a>>>, + // Used to memoize the traits in this module for faster searches through all traits in scope. + traits: RefCell<Option<Box<[&'a NameBinding<'a>]>>>, + // Whether this module is populated. If not populated, any attempt to // access the children must be preceded with a // `populate_module_if_necessary` call. @@ -875,6 +878,7 @@ impl<'a> ModuleS<'a> { prelude: RefCell::new(None), glob_importers: RefCell::new(Vec::new()), globs: RefCell::new((Vec::new())), + traits: RefCell::new(None), populated: Cell::new(!external), arenas: arenas } @@ -3225,18 +3229,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut search_module = self.current_module; loop { // Look for trait children. - let mut search_in_module = |module: Module<'a>| module.for_each_child(|_, ns, binding| { - if ns != TypeNS { return } - let trait_def_id = match binding.def() { - Some(Def::Trait(trait_def_id)) => trait_def_id, - Some(..) | None => return, - }; - if self.trait_item_map.contains_key(&(name, trait_def_id)) { - add_trait_info(&mut found_traits, trait_def_id, name); - let trait_name = self.get_trait_name(trait_def_id); - self.record_use(trait_name, TypeNS, binding); + let mut search_in_module = |module: Module<'a>| { + let mut traits = module.traits.borrow_mut(); + if traits.is_none() { + let mut collected_traits = Vec::new(); + module.for_each_child(|_, ns, binding| { + if ns != TypeNS { return } + if let Some(Def::Trait(_)) = binding.def() { + collected_traits.push(binding); + } + }); + *traits = Some(collected_traits.into_boxed_slice()); } - }); + + for binding in traits.as_ref().unwrap().iter() { + let trait_def_id = binding.def().unwrap().def_id(); + if self.trait_item_map.contains_key(&(name, trait_def_id)) { + add_trait_info(&mut found_traits, trait_def_id, name); + let trait_name = self.get_trait_name(trait_def_id); + self.record_use(trait_name, TypeNS, binding); + } + } + }; search_in_module(search_module); match search_module.parent_link { |
