Skip to content

Commit

Permalink
Revert "Auto merge of rust-lang#43184 - nikomatsakis:incr-comp-anonym…
Browse files Browse the repository at this point in the history
…ize-trait-selection, r=michaelwoerister"

This reverts commit b4502f7, reversing
changes made to 23ecebd.
  • Loading branch information
arielb1 committed Aug 17, 2017
1 parent 64e40c2 commit 80a0504
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 83 deletions.
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ define_dep_nodes!( <'tcx>
// imprecision in our dep-graph tracking. The important thing is
// that for any given trait-ref, we always map to the **same**
// trait-select node.
[anon] TraitSelect,
[] TraitSelect { trait_def_id: DefId, input_def_id: DefId },

// For proj. cache, we just keep a list of all def-ids, since it is
// not a hotspot.
Expand Down
40 changes: 31 additions & 9 deletions src/librustc/dep_graph/dep_tracking_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,24 @@ use rustc_data_structures::fx::FxHashMap;
use std::cell::RefCell;
use std::hash::Hash;
use std::marker::PhantomData;
use ty::TyCtxt;
use util::common::MemoizationMap;

use super::{DepKind, DepNodeIndex, DepGraph};
use super::{DepNode, DepGraph};

/// A DepTrackingMap offers a subset of the `Map` API and ensures that
/// we make calls to `read` and `write` as appropriate. We key the
/// maps with a unique type for brevity.
pub struct DepTrackingMap<M: DepTrackingMapConfig> {
phantom: PhantomData<M>,
graph: DepGraph,
map: FxHashMap<M::Key, (M::Value, DepNodeIndex)>,
map: FxHashMap<M::Key, M::Value>,
}

pub trait DepTrackingMapConfig {
type Key: Eq + Hash + Clone;
type Value: Clone;
fn to_dep_kind() -> DepKind;
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode;
}

impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
Expand All @@ -39,6 +40,27 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
map: FxHashMap(),
}
}

/// Registers a (synthetic) read from the key `k`. Usually this
/// is invoked automatically by `get`.
fn read(&self, tcx: TyCtxt, k: &M::Key) {
let dep_node = M::to_dep_node(tcx, k);
self.graph.read(dep_node);
}

pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> {
self.read(tcx, k);
self.map.get(k)
}

pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool {
self.read(tcx, k);
self.map.contains_key(k)
}

pub fn keys(&self) -> Vec<M::Key> {
self.map.keys().cloned().collect()
}
}

impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
Expand Down Expand Up @@ -76,22 +98,22 @@ impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
/// The key is the line marked `(*)`: the closure implicitly
/// accesses the body of the item `item`, so we register a read
/// from `Hir(item_def_id)`.
fn memoize<OP>(&self, key: M::Key, op: OP) -> M::Value
fn memoize<OP>(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value
where OP: FnOnce() -> M::Value
{
let graph;
{
let this = self.borrow();
if let Some(&(ref result, dep_node)) = this.map.get(&key) {
this.graph.read_index(dep_node);
if let Some(result) = this.map.get(&key) {
this.read(tcx, &key);
return result.clone();
}
graph = this.graph.clone();
}

let (result, dep_node) = graph.with_anon_task(M::to_dep_kind(), op);
self.borrow_mut().map.insert(key, (result.clone(), dep_node));
graph.read_index(dep_node);
let _task = graph.in_task(M::to_dep_node(tcx, &key));
let result = op();
self.borrow_mut().map.insert(key, result.clone());
result
}
}
88 changes: 24 additions & 64 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
VtableClosureData, VtableDefaultImplData, VtableFnPointerData};
use super::util;

use dep_graph::{DepNodeIndex, DepKind};
use hir::def_id::DefId;
use infer;
use infer::{InferCtxt, InferOk, TypeFreshener};
Expand Down Expand Up @@ -106,7 +105,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
#[derive(Clone)]
pub struct SelectionCache<'tcx> {
hashmap: RefCell<FxHashMap<ty::TraitRef<'tcx>,
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
}

/// The selection process begins by considering all impls, where
Expand Down Expand Up @@ -370,7 +369,7 @@ impl EvaluationResult {

#[derive(Clone)]
pub struct EvaluationCache<'tcx> {
hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, EvaluationResult>>
}

impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Expand Down Expand Up @@ -467,6 +466,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
assert!(!obligation.predicate.has_escaping_regions());

let tcx = self.tcx();
let dep_node = obligation.predicate.dep_node(tcx);
let _task = tcx.dep_graph.in_task(dep_node);

let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
let ret = match self.candidate_from_obligation(&stack)? {
Expand Down Expand Up @@ -709,12 +710,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
return result;
}

let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
let result = self.evaluate_stack(&stack);

debug!("CACHE MISS: EVAL({:?})={:?}",
fresh_trait_ref,
result);
self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, result);

result
}
Expand Down Expand Up @@ -869,23 +870,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
trait_ref: ty::PolyTraitRef<'tcx>)
-> Option<EvaluationResult>
{
let tcx = self.tcx();
if self.can_use_global_caches(param_env) {
let cache = tcx.evaluation_cache.hashmap.borrow();
let cache = self.tcx().evaluation_cache.hashmap.borrow();
if let Some(cached) = cache.get(&trait_ref) {
return Some(cached.get(tcx));
let dep_node = trait_ref
.to_poly_trait_predicate()
.dep_node(self.tcx());
self.tcx().hir.dep_graph.read(dep_node);
return Some(cached.clone());
}
}
self.infcx.evaluation_cache.hashmap
.borrow()
.get(&trait_ref)
.map(|v| v.get(tcx))
self.infcx.evaluation_cache.hashmap.borrow().get(&trait_ref).cloned()
}

fn insert_evaluation_cache(&mut self,
param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
dep_node: DepNodeIndex,
result: EvaluationResult)
{
// Avoid caching results that depend on more than just the trait-ref:
Expand All @@ -902,14 +902,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
if self.can_use_global_caches(param_env) {
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
cache.insert(trait_ref, WithDepNode::new(dep_node, result));
cache.insert(trait_ref, result);
return;
}
}

self.infcx.evaluation_cache.hashmap
.borrow_mut()
.insert(trait_ref, WithDepNode::new(dep_node, result));
self.infcx.evaluation_cache.hashmap.borrow_mut().insert(trait_ref, result);
}

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -951,32 +949,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}

// If no match, compute result and insert into cache.
let (candidate, dep_node) = self.in_task(|this| {
this.candidate_from_obligation_no_cache(stack)
});
let candidate = self.candidate_from_obligation_no_cache(stack);

if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
debug!("CACHE MISS: SELECT({:?})={:?}",
cache_fresh_trait_pred, candidate);
self.insert_candidate_cache(stack.obligation.param_env,
cache_fresh_trait_pred,
dep_node,
candidate.clone());
}

candidate
}

fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
where OP: FnOnce(&mut Self) -> R
{
let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || {
op(self)
});
self.tcx().dep_graph.read_index(dep_node);
(result, dep_node)
}

// Treat negative impls as unimplemented
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
Expand Down Expand Up @@ -1166,41 +1151,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
-> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
{
let tcx = self.tcx();
let trait_ref = &cache_fresh_trait_pred.0.trait_ref;
if self.can_use_global_caches(param_env) {
let cache = tcx.selection_cache.hashmap.borrow();
let cache = self.tcx().selection_cache.hashmap.borrow();
if let Some(cached) = cache.get(&trait_ref) {
return Some(cached.get(tcx));
return Some(cached.clone());
}
}
self.infcx.selection_cache.hashmap
.borrow()
.get(trait_ref)
.map(|v| v.get(tcx))
self.infcx.selection_cache.hashmap.borrow().get(trait_ref).cloned()
}

fn insert_candidate_cache(&mut self,
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
dep_node: DepNodeIndex,
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
{
let tcx = self.tcx();
let trait_ref = cache_fresh_trait_pred.0.trait_ref;
if self.can_use_global_caches(param_env) {
let mut cache = tcx.selection_cache.hashmap.borrow_mut();
if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
if let Some(candidate) = tcx.lift_to_global(&candidate) {
cache.insert(trait_ref, WithDepNode::new(dep_node, candidate));
let mut cache = self.tcx().selection_cache.hashmap.borrow_mut();
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
if let Some(candidate) = self.tcx().lift_to_global(&candidate) {
cache.insert(trait_ref, candidate);
return;
}
}
}

self.infcx.selection_cache.hashmap
.borrow_mut()
.insert(trait_ref, WithDepNode::new(dep_node, candidate));
self.infcx.selection_cache.hashmap.borrow_mut().insert(trait_ref, candidate);
}

fn should_update_candidate_cache(&mut self,
Expand Down Expand Up @@ -3161,20 +3138,3 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> {
write!(f, "TraitObligationStack({:?})", self.obligation)
}
}

#[derive(Clone)]
pub struct WithDepNode<T> {
dep_node: DepNodeIndex,
cached_value: T
}

impl<T: Clone> WithDepNode<T> {
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
WithDepNode { dep_node, cached_value }
}

pub fn get(&self, tcx: TyCtxt) -> T {
tcx.dep_graph.read_index(self.dep_node);
self.cached_value.clone()
}
}
39 changes: 32 additions & 7 deletions src/librustc/traits/trans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
// seems likely that they should eventually be merged into more
// general routines.

use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig};
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig,
DepConstructor};
use hir::def_id::DefId;
use infer::TransNormalize;
use std::cell::RefCell;
use std::marker::PhantomData;
Expand All @@ -39,7 +41,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
// Remove any references to regions; this helps improve caching.
let trait_ref = self.erase_regions(&trait_ref);

self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || {
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
trait_ref, trait_ref.def_id());

Expand Down Expand Up @@ -137,7 +139,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
if !ty.has_projection_types() {
ty
} else {
self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || {
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
self.tcx.normalize_associated_type(&ty)
})
Expand Down Expand Up @@ -169,8 +171,8 @@ pub struct TraitSelectionCache<'tcx> {
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
type Key = ty::PolyTraitRef<'tcx>;
type Value = Vtable<'tcx, ()>;
fn to_dep_kind() -> DepKind {
DepKind::TraitSelect
fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode {
key.to_poly_trait_predicate().dep_node(tcx)
}
}

Expand All @@ -183,8 +185,31 @@ pub struct ProjectionCache<'gcx> {
impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
type Key = Ty<'gcx>;
type Value = Ty<'gcx>;
fn to_dep_kind() -> DepKind {
DepKind::TraitSelect
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode {
// 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.item_def_id),
_ => None,
})
.collect();

DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids })
}
}

Loading

0 comments on commit 80a0504

Please sign in to comment.