Skip to content

Commit

Permalink
Auto merge of #37373 - nnethercote:html5ever-more-more, r=nrc
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors authored Oct 29, 2016
2 parents f0ab4a4 + c440a7a commit e9b2fcb
Showing 4 changed files with 51 additions and 21 deletions.
14 changes: 6 additions & 8 deletions src/libsyntax/ext/tt/macro_parser.rs
Original file line number Diff line number Diff line change
@@ -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
7 changes: 4 additions & 3 deletions src/libsyntax/ext/tt/transcribe.rs
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
#![feature(specialization)]
#![feature(dotdot_in_tuple_patterns)]

extern crate core;
extern crate serialize;
extern crate term;
extern crate libc;
50 changes: 40 additions & 10 deletions src/libsyntax/util/small_vector.rs
Original file line number Diff line number Diff line change
@@ -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>;

0 comments on commit e9b2fcb

Please sign in to comment.