Use SmallVector for TtReader::stack.
This avoids 800,000 heap allocations when compiling html5ever. It requires tweaking `SmallVector` a little.
This commit is contained in:
parent
0a16a11c39
commit
3fd90d8aa5
3 changed files with 45 additions and 13 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(specialization)]
|
||||
|
||||
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
Add a link
Reference in a new issue