about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-10-15 15:38:52 -0700
committerGitHub <noreply@github.com>2016-10-15 15:38:52 -0700
commit98a3502da1456b209ff031604cabbbcb9d0eddf1 (patch)
treee48daea06a2f6ce76cc64ab12833fbec97945661
parent5bfe10740168eb8213101c827302b4c45b1b5b74 (diff)
parenta61d85b2fe5ebc25bcc54c7a9e6ce3b98ce00b7c (diff)
downloadrust-98a3502da1456b209ff031604cabbbcb9d0eddf1.tar.gz
rust-98a3502da1456b209ff031604cabbbcb9d0eddf1.zip
Auto merge of #37152 - arielb1:drop-cache, r=pnkfelix
add a per-param-env cache to `impls_bound`

There used to be only a global cache, which led to uncached calls to
trait selection when there were type parameters.

This causes a 20% decrease in borrow-checking time and an overall 0.5% performance increase during bootstrapping (as borrow-checking tends to be a tiny part of compilation time).

Fixes #37106 (drop elaboration times are now ~half of borrow checking,
so might still be worthy of optimization, but not critical).

r? @pnkfelix
-rw-r--r--src/librustc/traits/select.rs2
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc/ty/structural_impls.rs17
-rw-r--r--src/librustc/ty/util.rs31
-rw-r--r--src/librustc_typeck/check/mod.rs2
5 files changed, 41 insertions, 27 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 66631111097..dbaa8db3e89 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -336,7 +336,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'tcx> {
+    pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
         self.infcx.param_env()
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7108ac89d82..d1fa2128842 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -34,7 +34,7 @@ use util::nodemap::FnvHashMap;
 
 use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
 use std::hash::{Hash, Hasher};
 use std::iter;
 use std::ops::Deref;
@@ -1220,6 +1220,12 @@ pub struct ParameterEnvironment<'tcx> {
     /// regions don't have this implicit scope and instead introduce
     /// relationships in the environment.
     pub free_id_outlive: CodeExtent,
+
+    /// A cache for `moves_by_default`.
+    pub is_copy_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+
+    /// A cache for `type_is_sized`
+    pub is_sized_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'tcx> {
@@ -1232,6 +1238,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             implicit_region_bound: self.implicit_region_bound,
             caller_bounds: caller_bounds,
             free_id_outlive: self.free_id_outlive,
+            is_copy_cache: RefCell::new(FnvHashMap()),
+            is_sized_cache: RefCell::new(FnvHashMap()),
         }
     }
 
@@ -2773,7 +2781,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             free_substs: Substs::empty(self),
             caller_bounds: Vec::new(),
             implicit_region_bound: self.mk_region(ty::ReEmpty),
-            free_id_outlive: free_id_outlive
+            free_id_outlive: free_id_outlive,
+            is_copy_cache: RefCell::new(FnvHashMap()),
+            is_sized_cache: RefCell::new(FnvHashMap()),
         }
     }
 
@@ -2844,6 +2854,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             implicit_region_bound: tcx.mk_region(ty::ReScope(free_id_outlive)),
             caller_bounds: predicates,
             free_id_outlive: free_id_outlive,
+            is_copy_cache: RefCell::new(FnvHashMap()),
+            is_sized_cache: RefCell::new(FnvHashMap()),
         };
 
         let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index abd5cb51f39..5948e02620e 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -901,23 +901,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'tcx> {
-    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::ParameterEnvironment {
-            free_substs: self.free_substs.fold_with(folder),
-            implicit_region_bound: self.implicit_region_bound.fold_with(folder),
-            caller_bounds: self.caller_bounds.fold_with(folder),
-            free_id_outlive: self.free_id_outlive,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.free_substs.visit_with(visitor) ||
-            self.implicit_region_bound.visit_with(visitor) ||
-            self.caller_bounds.visit_with(visitor)
-    }
-}
-
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         ty::error::ExpectedFound {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index c9ab577a992..5b0f43e3cf1 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -20,9 +20,11 @@ use ty::{Disr, ParameterEnvironment};
 use ty::fold::TypeVisitor;
 use ty::layout::{Layout, LayoutError};
 use ty::TypeVariants::*;
+use util::nodemap::FnvHashMap;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
 
+use std::cell::RefCell;
 use std::cmp;
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
@@ -579,11 +581,24 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
 impl<'a, 'tcx> ty::TyS<'tcx> {
     fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    param_env: &ParameterEnvironment<'tcx>,
-                   bound: ty::BuiltinBound, span: Span) -> bool
+                   bound: ty::BuiltinBound,
+                   cache: &RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+                   span: Span) -> bool
     {
-        tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch).enter(|infcx| {
-            traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
-        })
+        if self.has_param_types() || self.has_self_ty() {
+            if let Some(result) = cache.borrow().get(self) {
+                return *result;
+            }
+        }
+        let result =
+            tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch)
+            .enter(|infcx| {
+                traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
+            });
+        if self.has_param_types() || self.has_self_ty() {
+            cache.borrow_mut().insert(self, result);
+        }
+        return result;
     }
 
     // FIXME (@jroesch): I made this public to use it, not sure if should be private
@@ -610,7 +625,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
             TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) |
             TyClosure(..) | TyAdt(..) | TyAnon(..) |
             TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
-        }.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
+        }.unwrap_or_else(|| {
+            !self.impls_bound(tcx, param_env, ty::BoundCopy, &param_env.is_copy_cache, span)
+        });
 
         if !self.has_param_types() && !self.has_self_ty() {
             self.flags.set(self.flags.get() | if result {
@@ -650,7 +667,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
 
             TyAdt(..) | TyProjection(..) | TyParam(..) |
             TyInfer(..) | TyAnon(..) | TyError => None
-        }.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
+        }.unwrap_or_else(|| {
+            self.impls_bound(tcx, param_env, ty::BoundSized, &param_env.is_sized_cache, span)
+        });
 
         if !self.has_param_types() && !self.has_self_ty() {
             self.flags.set(self.flags.get() | if result {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 95d4416ec33..2224b747210 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1458,7 +1458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> {
+    pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
         &self.parameter_environment
     }