]> git.lizzy.rs Git - rust.git/commitdiff
Use `SmallVector` for `TtReader::stack`.
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 21 Oct 2016 08:25:53 +0000 (19:25 +1100)
committerNicholas Nethercote <nnethercote@mozilla.com>
Tue, 25 Oct 2016 00:48:25 +0000 (11:48 +1100)
This avoids 800,000 heap allocations when compiling html5ever. It
requires tweaking `SmallVector` a little.

src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/lib.rs
src/libsyntax/util/small_vector.rs

index 38a926b6e87c9ce1f9d00f430a2b1982d3592b1f..8a6a8e53a3e4c1b122aa2c33030b4724e94a1449 100644 (file)
 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.
index 6e671c9efdcf87b2a5e3abfa0ebd64b9c0f164f5..169388d72b6a6b118152cb08f8adc75a0a7d7d6e 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(specialization)]
 
+extern crate core;
 extern crate serialize;
 extern crate term;
 extern crate libc;
index 373dfc4ddfac5c0dfcbd796101279515eee1087c..57258c76335a1a4c39bb1bcd9a84c50404f250f5 100644 (file)
@@ -11,6 +11,7 @@
 use self::SmallVectorRepr::*;
 use self::IntoIterRepr::*;
 
+use core::ops;
 use std::iter::{IntoIterator, FromIterator};
 use std::mem;
 use std::slice;
 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 @@ pub fn many(vs: Vec<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 @@ pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> SmallVector<U> {
     }
 }
 
+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>;