Skip to content

Commit

Permalink
Add DepNode::TraitSelectSingle variant.
Browse files Browse the repository at this point in the history
This avoids the need for a heap allocation in the common case where the
`TraitSelect` has a single `D`.
  • Loading branch information
nnethercote committed Nov 14, 2016
1 parent a88145d commit 6db12d4
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ pub enum DepNode<D: Clone + Debug> {
TraitItems(D),
ReprHints(D),
TraitSelect(Vec<D>),

// An optional alternative to `TraitSelect` that avoids a heap allocation
// in the case where there is a single D. (Note that `TraitSelect` is still
// allowed to contain a Vec with a single D.)
TraitSelectSingle(D),
}

impl<D: Clone + Debug> DepNode<D> {
Expand Down Expand Up @@ -232,6 +237,7 @@ impl<D: Clone + Debug> DepNode<D> {
let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
Some(TraitSelect(type_ds))
}
TraitSelectSingle(ref d) => op(d).map(TraitSelectSingle),
}
}
}
Expand Down
24 changes: 16 additions & 8 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,18 +873,26 @@ impl<'tcx> TraitPredicate<'tcx> {
// `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`.
// Note that it's always sound to conflate dep-nodes, it just
// leads to more recompilation.
let def_ids: Vec<_> =
//
// This code is hot enough that it's worth going to some effort (i.e.
// the peek()) to use `TraitSelectSingle` and avoid a heap allocation
// when possible.
let mut def_ids_base =
self.input_types()
.flat_map(|t| t.walk())
.filter_map(|t| match t.sty {
ty::TyAdt(adt_def, _) =>
Some(adt_def.did),
_ =>
None
ty::TyAdt(adt_def, _) => Some(adt_def.did),
_ => None
})
.chain(iter::once(self.def_id()))
.collect();
DepNode::TraitSelect(def_ids)
.peekable();
if let Some(_) = def_ids_base.peek() {
let def_ids = def_ids_base
.chain(iter::once(self.def_id()))
.collect();
DepNode::TraitSelect(def_ids)
} else {
DepNode::TraitSelectSingle(self.def_id())
}
}

pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
_ => None,
})
.collect();
// This code is not hot so it's not worth detecting if
// `TraitSelectSingle` could be used instead of `TraitSelect`.
DepNode::TraitSelect(def_ids)
}
}
Expand Down

0 comments on commit 6db12d4

Please sign in to comment.