Skip to content

Commit 3fd90d8

Browse files
committed
Use SmallVector for TtReader::stack.
This avoids 800,000 heap allocations when compiling html5ever. It requires tweaking `SmallVector` a little.
1 parent 0a16a11 commit 3fd90d8

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

src/libsyntax/ext/tt/transcribe.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
use self::LockstepIterSize::*;
1111

1212
use ast::Ident;
13-
use syntax_pos::{Span, DUMMY_SP};
1413
use errors::{Handler, DiagnosticBuilder};
1514
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
1615
use parse::token::{DocComment, MatchNt, SubstNt};
1716
use parse::token::{Token, Interpolated, NtIdent, NtTT};
1817
use parse::token;
1918
use parse::lexer::TokenAndSpan;
19+
use syntax_pos::{Span, DUMMY_SP};
2020
use tokenstream::{self, TokenTree};
21+
use util::small_vector::SmallVector;
2122

2223
use std::rc::Rc;
2324
use std::ops::Add;
@@ -36,7 +37,7 @@ struct TtFrame {
3637
pub struct TtReader<'a> {
3738
pub sp_diag: &'a Handler,
3839
/// the unzipped tree:
39-
stack: Vec<TtFrame>,
40+
stack: SmallVector<TtFrame>,
4041
/* for MBE-style macro transcription */
4142
interpolations: HashMap<Ident, Rc<NamedMatch>>,
4243

@@ -74,7 +75,7 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler,
7475
-> TtReader {
7576
let mut r = TtReader {
7677
sp_diag: sp_diag,
77-
stack: vec!(TtFrame {
78+
stack: SmallVector::one(TtFrame {
7879
forest: TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
7980
tts: src,
8081
// doesn't matter. This merely holds the root unzipping.

src/libsyntax/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![feature(rustc_diagnostic_macros)]
3636
#![feature(specialization)]
3737

38+
extern crate core;
3839
extern crate serialize;
3940
extern crate term;
4041
extern crate libc;

src/libsyntax/util/small_vector.rs

+40-10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use self::SmallVectorRepr::*;
1212
use self::IntoIterRepr::*;
1313

14+
use core::ops;
1415
use std::iter::{IntoIterator, FromIterator};
1516
use std::mem;
1617
use std::slice;
@@ -19,10 +20,12 @@ use std::vec;
1920
use util::move_map::MoveMap;
2021

2122
/// A vector type optimized for cases where the size is almost always 0 or 1
23+
#[derive(Clone)]
2224
pub struct SmallVector<T> {
2325
repr: SmallVectorRepr<T>,
2426
}
2527

28+
#[derive(Clone)]
2629
enum SmallVectorRepr<T> {
2730
Zero,
2831
One(T),
@@ -75,16 +78,11 @@ impl<T> SmallVector<T> {
7578
}
7679

7780
pub fn as_slice(&self) -> &[T] {
78-
match self.repr {
79-
Zero => {
80-
let result: &[T] = &[];
81-
result
82-
}
83-
One(ref v) => {
84-
unsafe { slice::from_raw_parts(v, 1) }
85-
}
86-
Many(ref vs) => vs
87-
}
81+
self
82+
}
83+
84+
pub fn as_mut_slice(&mut self) -> &mut [T] {
85+
self
8886
}
8987

9088
pub fn pop(&mut self) -> Option<T> {
@@ -163,6 +161,38 @@ impl<T> SmallVector<T> {
163161
}
164162
}
165163

164+
impl<T> ops::Deref for SmallVector<T> {
165+
type Target = [T];
166+
167+
fn deref(&self) -> &[T] {
168+
match self.repr {
169+
Zero => {
170+
let result: &[T] = &[];
171+
result
172+
}
173+
One(ref v) => {
174+
unsafe { slice::from_raw_parts(v, 1) }
175+
}
176+
Many(ref vs) => vs
177+
}
178+
}
179+
}
180+
181+
impl<T> ops::DerefMut for SmallVector<T> {
182+
fn deref_mut(&mut self) -> &mut [T] {
183+
match self.repr {
184+
Zero => {
185+
let result: &mut [T] = &mut [];
186+
result
187+
}
188+
One(ref mut v) => {
189+
unsafe { slice::from_raw_parts_mut(v, 1) }
190+
}
191+
Many(ref mut vs) => vs
192+
}
193+
}
194+
}
195+
166196
impl<T> IntoIterator for SmallVector<T> {
167197
type Item = T;
168198
type IntoIter = IntoIter<T>;

0 commit comments

Comments
 (0)