Auto merge of #37373 - nnethercote:html5ever-more-more, r=nrc
Avoid more allocations when compiling html5ever These three commits reduce the number of allocations performed when compiling html5ever from 13.2M to 10.8M, which speeds up compilation by about 2%. r? @nrc
This commit is contained in:
commit
e9b2fcb2fe
4 changed files with 51 additions and 21 deletions
|
@ -92,6 +92,7 @@ use parse::token;
|
|||
use print::pprust;
|
||||
use ptr::P;
|
||||
use tokenstream::{self, TokenTree};
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
@ -104,7 +105,7 @@ use std::collections::hash_map::Entry::{Vacant, Occupied};
|
|||
#[derive(Clone)]
|
||||
enum TokenTreeOrTokenTreeVec {
|
||||
Tt(tokenstream::TokenTree),
|
||||
TtSeq(Rc<Vec<tokenstream::TokenTree>>),
|
||||
TtSeq(Vec<tokenstream::TokenTree>),
|
||||
}
|
||||
|
||||
impl TokenTreeOrTokenTreeVec {
|
||||
|
@ -161,7 +162,7 @@ pub fn count_names(ms: &[TokenTree]) -> usize {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn initial_matcher_pos(ms: Rc<Vec<TokenTree>>, sep: Option<Token>, lo: BytePos)
|
||||
pub fn initial_matcher_pos(ms: Vec<TokenTree>, sep: Option<Token>, lo: BytePos)
|
||||
-> Box<MatcherPos> {
|
||||
let match_idx_hi = count_names(&ms[..]);
|
||||
let matches: Vec<_> = (0..match_idx_hi).map(|_| Vec::new()).collect();
|
||||
|
@ -284,12 +285,9 @@ pub fn parse(sess: &ParseSess,
|
|||
mut rdr: TtReader,
|
||||
ms: &[TokenTree])
|
||||
-> NamedParseResult {
|
||||
let mut cur_eis = Vec::new();
|
||||
cur_eis.push(initial_matcher_pos(Rc::new(ms.iter()
|
||||
.cloned()
|
||||
.collect()),
|
||||
None,
|
||||
rdr.peek().sp.lo));
|
||||
let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(),
|
||||
None,
|
||||
rdr.peek().sp.lo));
|
||||
|
||||
loop {
|
||||
let mut bb_eis = Vec::new(); // black-box parsed by parser.rs
|
||||
|
|
|
@ -10,14 +10,15 @@
|
|||
use self::LockstepIterSize::*;
|
||||
|
||||
use ast::Ident;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use errors::{Handler, DiagnosticBuilder};
|
||||
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
|
||||
use parse::token::{DocComment, MatchNt, SubstNt};
|
||||
use parse::token::{Token, Interpolated, NtIdent, NtTT};
|
||||
use parse::token;
|
||||
use parse::lexer::TokenAndSpan;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use tokenstream::{self, TokenTree};
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::ops::Add;
|
||||
|
@ -36,7 +37,7 @@ struct TtFrame {
|
|||
pub struct TtReader<'a> {
|
||||
pub sp_diag: &'a Handler,
|
||||
/// the unzipped tree:
|
||||
stack: Vec<TtFrame>,
|
||||
stack: SmallVector<TtFrame>,
|
||||
/* for MBE-style macro transcription */
|
||||
interpolations: HashMap<Ident, Rc<NamedMatch>>,
|
||||
|
||||
|
@ -74,7 +75,7 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler,
|
|||
-> TtReader {
|
||||
let mut r = TtReader {
|
||||
sp_diag: sp_diag,
|
||||
stack: vec!(TtFrame {
|
||||
stack: SmallVector::one(TtFrame {
|
||||
forest: TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
|
||||
tts: src,
|
||||
// doesn't matter. This merely holds the root unzipping.
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#![feature(specialization)]
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
extern crate core;
|
||||
extern crate serialize;
|
||||
extern crate term;
|
||||
extern crate libc;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use self::SmallVectorRepr::*;
|
||||
use self::IntoIterRepr::*;
|
||||
|
||||
use core::ops;
|
||||
use std::iter::{IntoIterator, FromIterator};
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
@ -19,10 +20,12 @@ use std::vec;
|
|||
use util::move_map::MoveMap;
|
||||
|
||||
/// A vector type optimized for cases where the size is almost always 0 or 1
|
||||
#[derive(Clone)]
|
||||
pub struct SmallVector<T> {
|
||||
repr: SmallVectorRepr<T>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum SmallVectorRepr<T> {
|
||||
Zero,
|
||||
One(T),
|
||||
|
@ -75,16 +78,11 @@ impl<T> SmallVector<T> {
|
|||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
match self.repr {
|
||||
Zero => {
|
||||
let result: &[T] = &[];
|
||||
result
|
||||
}
|
||||
One(ref v) => {
|
||||
unsafe { slice::from_raw_parts(v, 1) }
|
||||
}
|
||||
Many(ref vs) => vs
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
|
@ -163,6 +161,38 @@ impl<T> SmallVector<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for SmallVector<T> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &[T] {
|
||||
match self.repr {
|
||||
Zero => {
|
||||
let result: &[T] = &[];
|
||||
result
|
||||
}
|
||||
One(ref v) => {
|
||||
unsafe { slice::from_raw_parts(v, 1) }
|
||||
}
|
||||
Many(ref vs) => vs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::DerefMut for SmallVector<T> {
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
match self.repr {
|
||||
Zero => {
|
||||
let result: &mut [T] = &mut [];
|
||||
result
|
||||
}
|
||||
One(ref mut v) => {
|
||||
unsafe { slice::from_raw_parts_mut(v, 1) }
|
||||
}
|
||||
Many(ref mut vs) => vs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for SmallVector<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
|
Loading…
Add table
Reference in a new issue