about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-04-17 19:11:20 -0700
committerbors <bors@rust-lang.org>2016-04-17 19:11:20 -0700
commit63760acf31e605c8a91bb5cbcbcb4bfb95435e48 (patch)
tree26ee481c87ddb93c740d43ad775d49fe7dbdba13
parented7c56796ef17f13227a50dc1a72a018b1d5e33f (diff)
parent6ae80273a08c9cb0b75b8aec464f1e7d838a2bda (diff)
downloadrust-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.rs36
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 {