diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2016-11-23 12:18:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-23 12:18:09 +0100 |
| commit | 496a411e4e471fd497bda3785f6b1d205baee3f1 (patch) | |
| tree | 70333d821d23ab8b7ba9ec1ff981e4704e7a1cdb | |
| parent | 464cce99f1fe09db35d56ca07ae4c05f591eb651 (diff) | |
| parent | f72685f2ffd1e79c2d4e099770490d4cf00795fa (diff) | |
| download | rust-496a411e4e471fd497bda3785f6b1d205baee3f1.tar.gz rust-496a411e4e471fd497bda3785f6b1d205baee3f1.zip | |
Rollup merge of #37760 - nnethercote:TypeWalker-SmallVector, r=arielb1
Type walker small vector These two changes avoid allocations on some hot paths and speed up a few workloads (some from rustc-benchmarks, as well as the workload from #36799) by 1--2%.
| -rw-r--r-- | src/librustc/ty/mod.rs | 3 | ||||
| -rw-r--r-- | src/librustc/ty/walk.rs | 21 | ||||
| -rw-r--r-- | src/librustc_data_structures/small_vec.rs | 12 |
3 files changed, 27 insertions, 9 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e94e93158c4..ebf8c96def7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -48,6 +48,7 @@ use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_const_math::ConstInt; +use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; use hir; use hir::itemlikevisit::ItemLikeVisitor; @@ -1887,7 +1888,7 @@ impl<'tcx> TyS<'tcx> { /// Iterator that walks the immediate children of `self`. Hence /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]` /// (but not `i32`, like `walk`). - pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> { + pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> { walk::walk_shallow(self) } diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index a6ecfd2fb70..2f9468dbe58 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -12,17 +12,22 @@ //! WARNING: this does not keep track of the region depth. use ty::{self, Ty}; -use std::iter::Iterator; -use std::vec::IntoIter; +use rustc_data_structures::small_vec::SmallVec; +use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; + +// The TypeWalker's stack is hot enough that it's worth going to some effort to +// avoid heap allocations. +pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8]; +pub type TypeWalkerStack<'tcx> = SmallVec<TypeWalkerArray<'tcx>>; pub struct TypeWalker<'tcx> { - stack: Vec<Ty<'tcx>>, + stack: TypeWalkerStack<'tcx>, last_subtree: usize, } impl<'tcx> TypeWalker<'tcx> { pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> { - TypeWalker { stack: vec![ty], last_subtree: 1, } + TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, } } /// Skips the subtree of types corresponding to the last type @@ -61,8 +66,8 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { } } -pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> { - let mut stack = vec![]; +pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> { + let mut stack = SmallVec::new(); push_subtypes(&mut stack, ty); stack.into_iter() } @@ -73,7 +78,7 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> { // known to be significant to any code, but it seems like the // natural order one would expect (basically, the order of the // types as they are written). -fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) { +fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => { @@ -112,7 +117,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) { } } -fn push_sig_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, sig: &ty::PolyFnSig<'tcx>) { +fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: &ty::PolyFnSig<'tcx>) { stack.push(sig.0.output); stack.extend(sig.0.inputs.iter().cloned().rev()); } diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index 565a3c443a3..4e2b3786021 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -130,6 +130,18 @@ impl<A: Array> SmallVec<A> { self.set_len(len + 1); } } + + pub fn truncate(&mut self, len: usize) { + unsafe { + while len < self.len() { + // Decrement len before the drop_in_place(), so a panic on Drop + // doesn't re-drop the just-failed value. + let newlen = self.len() - 1; + self.set_len(newlen); + ::std::ptr::drop_in_place(self.get_unchecked_mut(newlen)); + } + } + } } impl<A: Array> Deref for SmallVec<A> { |
