mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Use a SmallVec during selector parsing.
This significantly reduces realloc time at the expense of some additional mmemmoves, but pencils out to a small win on my machine. We wanted to do this anyway, and this avoids needing to remove the smallvec dependency from Selectors and then add it back again. MozReview-Commit-ID: HW4kDxzLACp
This commit is contained in:
parent
cebacc7faa
commit
fe97033aa8
1 changed files with 15 additions and 4 deletions
|
@ -5,6 +5,7 @@
|
||||||
use arcslice::ArcSlice;
|
use arcslice::ArcSlice;
|
||||||
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
||||||
use precomputed_hash::PrecomputedHash;
|
use precomputed_hash::PrecomputedHash;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -886,13 +887,23 @@ fn parse_selector<P, Impl>(parser: &P, input: &mut CssParser) -> Result<Selector
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We use a SmallVec for parsing to avoid extra reallocs compared to using a Vec
|
||||||
|
/// directly. When parsing is done, we convert the SmallVec into a Vec (which is
|
||||||
|
/// free if the vec has already spilled to the heap, and more cache-friendly if
|
||||||
|
/// it hasn't), and then steal the buffer of that vec into a boxed slice.
|
||||||
|
///
|
||||||
|
/// If we parse N <= 4 entries, we save no reallocations.
|
||||||
|
/// If we parse 4 < N <= 8 entries, we save one reallocation.
|
||||||
|
/// If we parse N > 8 entries, we save two reallocations.
|
||||||
|
type ParseVec<Impl> = SmallVec<[Component<Impl>; 8]>;
|
||||||
|
|
||||||
fn parse_complex_selector_and_pseudo_element<P, Impl>(
|
fn parse_complex_selector_and_pseudo_element<P, Impl>(
|
||||||
parser: &P,
|
parser: &P,
|
||||||
input: &mut CssParser)
|
input: &mut CssParser)
|
||||||
-> Result<(ComplexSelector<Impl>, Option<Impl::PseudoElement>), ()>
|
-> Result<(ComplexSelector<Impl>, Option<Impl::PseudoElement>), ()>
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let mut sequence = Vec::new();
|
let mut sequence = ParseVec::new();
|
||||||
let mut pseudo_element;
|
let mut pseudo_element;
|
||||||
'outer_loop: loop {
|
'outer_loop: loop {
|
||||||
// Parse a sequence of simple selectors.
|
// Parse a sequence of simple selectors.
|
||||||
|
@ -935,7 +946,7 @@ fn parse_complex_selector_and_pseudo_element<P, Impl>(
|
||||||
sequence.push(Component::Combinator(combinator));
|
sequence.push(Component::Combinator(combinator));
|
||||||
}
|
}
|
||||||
|
|
||||||
let complex = ComplexSelector(ArcSlice::new(sequence.into_boxed_slice()));
|
let complex = ComplexSelector(ArcSlice::new(sequence.into_vec().into_boxed_slice()));
|
||||||
Ok((complex, pseudo_element))
|
Ok((complex, pseudo_element))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +967,7 @@ impl<Impl: SelectorImpl> ComplexSelector<Impl> {
|
||||||
/// * `Err(())`: Invalid selector, abort
|
/// * `Err(())`: Invalid selector, abort
|
||||||
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
|
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
|
||||||
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
|
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
|
||||||
fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mut Vec<Component<Impl>>)
|
fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mut ParseVec<Impl>)
|
||||||
-> Result<bool, ()>
|
-> Result<bool, ()>
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
|
@ -1170,7 +1181,7 @@ fn parse_negation<P, Impl>(parser: &P,
|
||||||
fn parse_compound_selector<P, Impl>(
|
fn parse_compound_selector<P, Impl>(
|
||||||
parser: &P,
|
parser: &P,
|
||||||
input: &mut CssParser,
|
input: &mut CssParser,
|
||||||
mut sequence: &mut Vec<Component<Impl>>)
|
mut sequence: &mut ParseVec<Impl>)
|
||||||
-> Result<Option<Impl::PseudoElement>, ()>
|
-> Result<Option<Impl::PseudoElement>, ()>
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue