diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2017-04-17 12:35:53 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2017-04-21 17:26:53 -0400 |
| commit | f4c183b742cf08c5d06d50b4fbada3561722af81 (patch) | |
| tree | ca7e0426a573623dff194fd8fc5908c25cfbedca | |
| parent | e48a759f51ae23f817339eda1485fa3afe6d8d04 (diff) | |
| download | rust-f4c183b742cf08c5d06d50b4fbada3561722af81.tar.gz rust-f4c183b742cf08c5d06d50b4fbada3561722af81.zip | |
move the trans trait caches into tcx
Arguably these could become custom queries, but I chose not to do that because the relationship of queries and trait system is not yet fleshed out enough. For now it seems fine to have them be `DepTrackingMap` using the memoize pattern.
| -rw-r--r-- | src/librustc/traits/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc/traits/trans/mod.rs | 73 | ||||
| -rw-r--r-- | src/librustc/ty/context.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/context.rs | 66 | ||||
| -rw-r--r-- | src/librustc_trans/monomorphize.rs | 24 |
5 files changed, 89 insertions, 78 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 0ff379b30ff..18f0a749f70 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -55,6 +55,7 @@ mod object_safety; mod select; mod specialize; mod structural_impls; +pub mod trans; mod util; /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs new file mode 100644 index 00000000000..8517f573e60 --- /dev/null +++ b/src/librustc/traits/trans/mod.rs @@ -0,0 +1,73 @@ +use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; +use hir::def_id::DefId; +use std::cell::RefCell; +use std::marker::PhantomData; +use traits::Vtable; +use ty::{self, Ty}; + +/// Specializes caches used in trans -- in particular, they assume all +/// types are fully monomorphized and that free regions can be erased. +pub struct TransTraitCaches<'tcx> { + pub trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>, + pub project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>, +} + +impl<'tcx> TransTraitCaches<'tcx> { + pub fn new(graph: DepGraph) -> Self { + TransTraitCaches { + trait_cache: RefCell::new(DepTrackingMap::new(graph.clone())), + project_cache: RefCell::new(DepTrackingMap::new(graph)), + } + } +} + +// Implement DepTrackingMapConfig for `trait_cache` +pub struct TraitSelectionCache<'tcx> { + data: PhantomData<&'tcx ()> +} + +impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { + type Key = ty::PolyTraitRef<'tcx>; + type Value = Vtable<'tcx, ()>; + fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> { + key.to_poly_trait_predicate().dep_node() + } +} + +// # Global Cache + +pub struct ProjectionCache<'gcx> { + data: PhantomData<&'gcx ()> +} + +impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { + type Key = Ty<'gcx>; + type Value = Ty<'gcx>; + fn to_dep_node(key: &Self::Key) -> DepNode<DefId> { + // Ideally, we'd just put `key` into the dep-node, but we + // can't put full types in there. So just collect up all the + // def-ids of structs/enums as well as any traits that we + // project out of. It doesn't matter so much what we do here, + // except that if we are too coarse, we'll create overly + // coarse edges between impls and the trans. For example, if + // we just used the def-id of things we are projecting out of, + // then the key for `<Foo as SomeTrait>::T` and `<Bar as + // SomeTrait>::T` would both share a dep-node + // (`TraitSelect(SomeTrait)`), and hence the impls for both + // `Foo` and `Bar` would be considered inputs. So a change to + // `Bar` would affect things that just normalized `Foo`. + // Anyway, this heuristic is not ideal, but better than + // nothing. + let def_ids: Vec<DefId> = + key.walk() + .filter_map(|t| match t.sty { + ty::TyAdt(adt_def, _) => Some(adt_def.did), + ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), + _ => None, + }) + .collect(); + + DepNode::ProjectionCache { def_ids: def_ids } + } +} + diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a4162925871..e836bf23a5a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -407,6 +407,8 @@ pub struct GlobalCtxt<'tcx> { pub specializes_cache: RefCell<traits::SpecializesCache>, + pub trans_trait_caches: traits::trans::TransTraitCaches<'tcx>, + pub dep_graph: DepGraph, /// Common types, pre-interned for your convenience. @@ -689,6 +691,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { providers[LOCAL_CRATE] = local_providers; tls::enter_global(GlobalCtxt { sess: s, + trans_trait_caches: traits::trans::TransTraitCaches::new(dep_graph.clone()), specializes_cache: RefCell::new(traits::SpecializesCache::new()), global_arenas: arenas, global_interners: interners, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 3769c8b026d..ceb292c13c1 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -10,7 +10,7 @@ use llvm; use llvm::{ContextRef, ModuleRef, ValueRef}; -use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, DepTrackingMapConfig}; +use rustc::dep_graph::{DepGraph, DepGraphSafe}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::traits; @@ -34,7 +34,6 @@ use util::nodemap::{NodeSet, DefIdMap, FxHashMap}; use std::ffi::{CStr, CString}; use std::cell::{Cell, RefCell}; -use std::marker::PhantomData; use std::ptr; use std::iter; use std::str; @@ -84,9 +83,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { check_overflow: bool, use_dll_storage_attrs: bool, - - trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>, - project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>, } /// The local portion of a `CrateContext`. There is one `LocalCrateContext` @@ -171,56 +167,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { symbol_cache: &'a SymbolCache<'a, 'tcx>, } -// Implement DepTrackingMapConfig for `trait_cache` -pub struct TraitSelectionCache<'tcx> { - data: PhantomData<&'tcx ()> -} - -impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { - type Key = ty::PolyTraitRef<'tcx>; - type Value = traits::Vtable<'tcx, ()>; - fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> { - key.to_poly_trait_predicate().dep_node() - } -} - -// # Global Cache - -pub struct ProjectionCache<'gcx> { - data: PhantomData<&'gcx ()> -} - -impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { - type Key = Ty<'gcx>; - type Value = Ty<'gcx>; - fn to_dep_node(key: &Self::Key) -> DepNode<DefId> { - // Ideally, we'd just put `key` into the dep-node, but we - // can't put full types in there. So just collect up all the - // def-ids of structs/enums as well as any traits that we - // project out of. It doesn't matter so much what we do here, - // except that if we are too coarse, we'll create overly - // coarse edges between impls and the trans. For example, if - // we just used the def-id of things we are projecting out of, - // then the key for `<Foo as SomeTrait>::T` and `<Bar as - // SomeTrait>::T` would both share a dep-node - // (`TraitSelect(SomeTrait)`), and hence the impls for both - // `Foo` and `Bar` would be considered inputs. So a change to - // `Bar` would affect things that just normalized `Foo`. - // Anyway, this heuristic is not ideal, but better than - // nothing. - let def_ids: Vec<DefId> = - key.walk() - .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), - _ => None, - }) - .collect(); - - DepNode::ProjectionCache { def_ids: def_ids } - } -} - /// A CrateContext value binds together one LocalCrateContext with the /// SharedCrateContext. It exists as a convenience wrapper, so we don't have to /// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans. @@ -382,8 +328,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { tcx: tcx, check_overflow: check_overflow, use_dll_storage_attrs: use_dll_storage_attrs, - trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), - project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), } } @@ -403,14 +347,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.exported_symbols } - pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>> { - &self.trait_cache - } - - pub fn project_cache(&self) -> &RefCell<DepTrackingMap<ProjectionCache<'tcx>>> { - &self.project_cache - } - pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 382ca8ef010..33626e7c39f 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -117,7 +117,7 @@ fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Remove any references to regions; this helps improve caching. let trait_ref = tcx.erase_regions(&trait_ref); - scx.trait_cache().memoize(trait_ref, || { + tcx.trans_trait_caches.trait_cache.memoize(trait_ref, || { debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", trait_ref, trait_ref.def_id()); @@ -307,7 +307,7 @@ pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>, debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value); let substituted = value.subst(tcx, param_substs); let substituted = scx.tcx().erase_regions(&substituted); - AssociatedTypeNormalizer::new(scx).fold(&substituted) + AssociatedTypeNormalizer::new(tcx).fold(&substituted) } /// Returns the normalized type of a struct field @@ -319,15 +319,13 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.normalize_associated_type(&f.ty(tcx, param_substs)) } -struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> { - shared: &'a SharedCrateContext<'b, 'gcx>, +struct AssociatedTypeNormalizer<'a, 'gcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'gcx>, } -impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> { - fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self { - AssociatedTypeNormalizer { - shared: shared, - } +impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> { + fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self { + AssociatedTypeNormalizer { tcx } } fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T { @@ -339,18 +337,18 @@ impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> { } } -impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> { +impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> { - self.shared.tcx() + self.tcx } fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> { if !ty.has_projection_types() { ty } else { - self.shared.project_cache().memoize(ty, || { + self.tcx.trans_trait_caches.project_cache.memoize(ty, || { debug!("AssociatedTypeNormalizer: ty={:?}", ty); - self.shared.tcx().normalize_associated_type(&ty) + self.tcx.normalize_associated_type(&ty) }) } } |
