mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Use a 1-entry smallvec in the selector maps.
MozReview-Commit-ID: 1JPkVxs3cdP
This commit is contained in:
parent
16704bbaaa
commit
2f39213072
1 changed files with 17 additions and 10 deletions
|
@ -16,7 +16,7 @@ use selector_parser::SelectorImpl;
|
||||||
use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags};
|
use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags};
|
||||||
use selectors::parser::{Component, Combinator, SelectorIter};
|
use selectors::parser::{Component, Combinator, SelectorIter};
|
||||||
use selectors::parser::LocalName as LocalNameSelector;
|
use selectors::parser::LocalName as LocalNameSelector;
|
||||||
use smallvec::VecLike;
|
use smallvec::{SmallVec, VecLike};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -49,16 +49,21 @@ pub trait SelectorMapEntry : Sized + Clone {
|
||||||
/// element name, etc. will contain the Selectors that actually match that
|
/// element name, etc. will contain the Selectors that actually match that
|
||||||
/// element.
|
/// element.
|
||||||
///
|
///
|
||||||
|
/// We use a 1-entry SmallVec to avoid a separate heap allocation in the case
|
||||||
|
/// where we only have one entry, which is quite common. See measurements in:
|
||||||
|
/// * https://bugzilla.mozilla.org/show_bug.cgi?id=1363789#c5
|
||||||
|
/// * https://bugzilla.mozilla.org/show_bug.cgi?id=681755
|
||||||
|
///
|
||||||
/// TODO: Tune the initial capacity of the HashMap
|
/// TODO: Tune the initial capacity of the HashMap
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct SelectorMap<T> {
|
pub struct SelectorMap<T> {
|
||||||
/// A hash from an ID to rules which contain that ID selector.
|
/// A hash from an ID to rules which contain that ID selector.
|
||||||
pub id_hash: MaybeCaseInsensitiveHashMap<Atom, Vec<T>>,
|
pub id_hash: MaybeCaseInsensitiveHashMap<Atom, SmallVec<[T; 1]>>,
|
||||||
/// A hash from a class name to rules which contain that class selector.
|
/// A hash from a class name to rules which contain that class selector.
|
||||||
pub class_hash: MaybeCaseInsensitiveHashMap<Atom, Vec<T>>,
|
pub class_hash: MaybeCaseInsensitiveHashMap<Atom, SmallVec<[T; 1]>>,
|
||||||
/// A hash from local name to rules which contain that local name selector.
|
/// A hash from local name to rules which contain that local name selector.
|
||||||
pub local_name_hash: FnvHashMap<LocalName, Vec<T>>,
|
pub local_name_hash: FnvHashMap<LocalName, SmallVec<[T; 1]>>,
|
||||||
/// Rules that don't have ID, class, or element selectors.
|
/// Rules that don't have ID, class, or element selectors.
|
||||||
pub other: Vec<T>,
|
pub other: Vec<T>,
|
||||||
/// The number of entries in this map.
|
/// The number of entries in this map.
|
||||||
|
@ -213,12 +218,12 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
|
|
||||||
if let Some(id_name) = get_id_name(entry.selector()) {
|
if let Some(id_name) = get_id_name(entry.selector()) {
|
||||||
self.id_hash.entry(id_name, quirks_mode).or_insert_with(Vec::new).push(entry);
|
self.id_hash.entry(id_name, quirks_mode).or_insert_with(SmallVec::new).push(entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(class_name) = get_class_name(entry.selector()) {
|
if let Some(class_name) = get_class_name(entry.selector()) {
|
||||||
self.class_hash.entry(class_name, quirks_mode).or_insert_with(Vec::new).push(entry);
|
self.class_hash.entry(class_name, quirks_mode).or_insert_with(SmallVec::new).push(entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,10 +434,12 @@ pub fn get_local_name(iter: SelectorIter<SelectorImpl>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn find_push<Str: Eq + Hash, V>(map: &mut FnvHashMap<Str, Vec<V>>,
|
fn find_push<Str: Eq + Hash, V, VL>(map: &mut FnvHashMap<Str, VL>,
|
||||||
key: Str,
|
key: Str,
|
||||||
value: V) {
|
value: V)
|
||||||
map.entry(key).or_insert_with(Vec::new).push(value)
|
where VL: VecLike<V> + Default
|
||||||
|
{
|
||||||
|
map.entry(key).or_insert_with(VL::default).push(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper for FnvHashMap that does ASCII-case-insensitive lookup in quirks mode.
|
/// Wrapper for FnvHashMap that does ASCII-case-insensitive lookup in quirks mode.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue