mirror of
https://github.com/servo/servo.git
synced 2025-08-02 04:00:32 +01:00
Use FNV hash in SelectorMap
This commit is contained in:
parent
a175c9981e
commit
dec28a13ea
1 changed files with 27 additions and 29 deletions
|
@ -16,8 +16,8 @@ use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement};
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS};
|
use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS};
|
||||||
use selectors::matching::{StyleRelations, matches_compound_selector};
|
use selectors::matching::{StyleRelations, matches_complex_selector};
|
||||||
use selectors::parser::{Selector, SimpleSelector, LocalName, CompoundSelector};
|
use selectors::parser::{Selector, SimpleSelector, LocalName, ComplexSelector};
|
||||||
use sink::Push;
|
use sink::Push;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
@ -32,6 +32,8 @@ use style_traits::viewport::ViewportConstraints;
|
||||||
use stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet};
|
use stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet};
|
||||||
use viewport::{MaybeNew, ViewportRuleCascade};
|
use viewport::{MaybeNew, ViewportRuleCascade};
|
||||||
|
|
||||||
|
pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<::fnv::FnvHasher>>;
|
||||||
|
|
||||||
/// This structure holds all the selectors and device characteristics
|
/// This structure holds all the selectors and device characteristics
|
||||||
/// for a given document. The selectors are converted into `Rule`s
|
/// for a given document. The selectors are converted into `Rule`s
|
||||||
/// (defined in rust-selectors), and introduced in a `SelectorMap`
|
/// (defined in rust-selectors), and introduced in a `SelectorMap`
|
||||||
|
@ -61,19 +63,15 @@ pub struct Stylist {
|
||||||
|
|
||||||
/// The selector maps corresponding to a given pseudo-element
|
/// The selector maps corresponding to a given pseudo-element
|
||||||
/// (depending on the implementation)
|
/// (depending on the implementation)
|
||||||
pseudos_map: HashMap<PseudoElement,
|
pseudos_map: FnvHashMap<PseudoElement, PerPseudoElementSelectorMap>,
|
||||||
PerPseudoElementSelectorMap,
|
|
||||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
|
||||||
|
|
||||||
/// A map with all the animations indexed by name.
|
/// A map with all the animations indexed by name.
|
||||||
animations: HashMap<Atom, KeyframesAnimation>,
|
animations: FnvHashMap<Atom, KeyframesAnimation>,
|
||||||
|
|
||||||
/// Applicable declarations for a given non-eagerly cascaded pseudo-element.
|
/// Applicable declarations for a given non-eagerly cascaded pseudo-element.
|
||||||
/// These are eagerly computed once, and then used to resolve the new
|
/// These are eagerly computed once, and then used to resolve the new
|
||||||
/// computed values on the fly on layout.
|
/// computed values on the fly on layout.
|
||||||
precomputed_pseudo_element_decls: HashMap<PseudoElement,
|
precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<DeclarationBlock>>,
|
||||||
Vec<DeclarationBlock>,
|
|
||||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
|
||||||
|
|
||||||
rules_source_order: usize,
|
rules_source_order: usize,
|
||||||
|
|
||||||
|
@ -98,9 +96,9 @@ impl Stylist {
|
||||||
quirks_mode: false,
|
quirks_mode: false,
|
||||||
|
|
||||||
element_map: PerPseudoElementSelectorMap::new(),
|
element_map: PerPseudoElementSelectorMap::new(),
|
||||||
pseudos_map: HashMap::with_hasher(Default::default()),
|
pseudos_map: Default::default(),
|
||||||
animations: HashMap::with_hasher(Default::default()),
|
animations: Default::default(),
|
||||||
precomputed_pseudo_element_decls: HashMap::with_hasher(Default::default()),
|
precomputed_pseudo_element_decls: Default::default(),
|
||||||
rules_source_order: 0,
|
rules_source_order: 0,
|
||||||
state_deps: DependencySet::new(),
|
state_deps: DependencySet::new(),
|
||||||
|
|
||||||
|
@ -124,13 +122,13 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.element_map = PerPseudoElementSelectorMap::new();
|
self.element_map = PerPseudoElementSelectorMap::new();
|
||||||
self.pseudos_map = HashMap::with_hasher(Default::default());
|
self.pseudos_map = Default::default();
|
||||||
self.animations = HashMap::with_hasher(Default::default());
|
self.animations = Default::default();
|
||||||
TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||||
self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
|
self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
|
||||||
});
|
});
|
||||||
|
|
||||||
self.precomputed_pseudo_element_decls = HashMap::with_hasher(Default::default());
|
self.precomputed_pseudo_element_decls = Default::default();
|
||||||
self.rules_source_order = 0;
|
self.rules_source_order = 0;
|
||||||
self.state_deps.clear();
|
self.state_deps.clear();
|
||||||
|
|
||||||
|
@ -456,7 +454,7 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn animations(&self) -> &HashMap<Atom, KeyframesAnimation> {
|
pub fn animations(&self) -> &FnvHashMap<Atom, KeyframesAnimation> {
|
||||||
&self.animations
|
&self.animations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,12 +609,12 @@ impl PerPseudoElementSelectorMap {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct SelectorMap {
|
pub struct SelectorMap {
|
||||||
// TODO: Tune the initial capacity of the HashMap
|
// TODO: Tune the initial capacity of the HashMap
|
||||||
id_hash: HashMap<Atom, Vec<Rule>>,
|
id_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||||
class_hash: HashMap<Atom, Vec<Rule>>,
|
class_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||||
local_name_hash: HashMap<Atom, Vec<Rule>>,
|
local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||||
/// Same as local_name_hash, but keys are lower-cased.
|
/// Same as local_name_hash, but keys are lower-cased.
|
||||||
/// For HTML elements in HTML documents.
|
/// For HTML elements in HTML documents.
|
||||||
lower_local_name_hash: HashMap<Atom, Vec<Rule>>,
|
lower_local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||||
/// Rules that don't have ID, class, or element selectors.
|
/// Rules that don't have ID, class, or element selectors.
|
||||||
other_rules: Vec<Rule>,
|
other_rules: Vec<Rule>,
|
||||||
/// Whether this hash is empty.
|
/// Whether this hash is empty.
|
||||||
|
@ -712,7 +710,7 @@ impl SelectorMap {
|
||||||
let init_len = matching_rules_list.len();
|
let init_len = matching_rules_list.len();
|
||||||
|
|
||||||
for rule in self.other_rules.iter() {
|
for rule in self.other_rules.iter() {
|
||||||
if rule.selector.simple_selectors.is_empty() &&
|
if rule.selector.compound_selector.is_empty() &&
|
||||||
rule.selector.next.is_none() {
|
rule.selector.next.is_none() {
|
||||||
matching_rules_list.push(rule.declarations.clone());
|
matching_rules_list.push(rule.declarations.clone());
|
||||||
}
|
}
|
||||||
|
@ -725,7 +723,7 @@ impl SelectorMap {
|
||||||
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
|
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
hash: &HashMap<Str, Vec<Rule>>,
|
hash: &FnvHashMap<Str, Vec<Rule>>,
|
||||||
key: &BorrowedStr,
|
key: &BorrowedStr,
|
||||||
matching_rules: &mut Vector,
|
matching_rules: &mut Vector,
|
||||||
relations: &mut StyleRelations)
|
relations: &mut StyleRelations)
|
||||||
|
@ -753,7 +751,7 @@ impl SelectorMap {
|
||||||
V: VecLike<DeclarationBlock>
|
V: VecLike<DeclarationBlock>
|
||||||
{
|
{
|
||||||
for rule in rules.iter() {
|
for rule in rules.iter() {
|
||||||
if matches_compound_selector(&*rule.selector,
|
if matches_complex_selector(&*rule.selector,
|
||||||
element, parent_bf, relations) {
|
element, parent_bf, relations) {
|
||||||
matching_rules.push(rule.declarations.clone());
|
matching_rules.push(rule.declarations.clone());
|
||||||
}
|
}
|
||||||
|
@ -786,7 +784,7 @@ impl SelectorMap {
|
||||||
|
|
||||||
/// Retrieve the first ID name in Rule, or None otherwise.
|
/// Retrieve the first ID name in Rule, or None otherwise.
|
||||||
fn get_id_name(rule: &Rule) -> Option<Atom> {
|
fn get_id_name(rule: &Rule) -> Option<Atom> {
|
||||||
for ss in &rule.selector.simple_selectors {
|
for ss in &rule.selector.compound_selector {
|
||||||
// TODO(pradeep): Implement case-sensitivity based on the
|
// TODO(pradeep): Implement case-sensitivity based on the
|
||||||
// document type and quirks mode.
|
// document type and quirks mode.
|
||||||
if let SimpleSelector::ID(ref id) = *ss {
|
if let SimpleSelector::ID(ref id) = *ss {
|
||||||
|
@ -799,7 +797,7 @@ impl SelectorMap {
|
||||||
|
|
||||||
/// Retrieve the FIRST class name in Rule, or None otherwise.
|
/// Retrieve the FIRST class name in Rule, or None otherwise.
|
||||||
fn get_class_name(rule: &Rule) -> Option<Atom> {
|
fn get_class_name(rule: &Rule) -> Option<Atom> {
|
||||||
for ss in &rule.selector.simple_selectors {
|
for ss in &rule.selector.compound_selector {
|
||||||
// TODO(pradeep): Implement case-sensitivity based on the
|
// TODO(pradeep): Implement case-sensitivity based on the
|
||||||
// document type and quirks mode.
|
// document type and quirks mode.
|
||||||
if let SimpleSelector::Class(ref class) = *ss {
|
if let SimpleSelector::Class(ref class) = *ss {
|
||||||
|
@ -812,7 +810,7 @@ impl SelectorMap {
|
||||||
|
|
||||||
/// Retrieve the name if it is a type selector, or None otherwise.
|
/// Retrieve the name if it is a type selector, or None otherwise.
|
||||||
fn get_local_name(rule: &Rule) -> Option<LocalName<TheSelectorImpl>> {
|
fn get_local_name(rule: &Rule) -> Option<LocalName<TheSelectorImpl>> {
|
||||||
for ss in &rule.selector.simple_selectors {
|
for ss in &rule.selector.compound_selector {
|
||||||
if let SimpleSelector::LocalName(ref n) = *ss {
|
if let SimpleSelector::LocalName(ref n) = *ss {
|
||||||
return Some(LocalName {
|
return Some(LocalName {
|
||||||
name: n.name.clone(),
|
name: n.name.clone(),
|
||||||
|
@ -830,8 +828,8 @@ impl SelectorMap {
|
||||||
pub struct Rule {
|
pub struct Rule {
|
||||||
// This is an Arc because Rule will essentially be cloned for every element
|
// This is an Arc because Rule will essentially be cloned for every element
|
||||||
// that it matches. Selector contains an owned vector (through
|
// that it matches. Selector contains an owned vector (through
|
||||||
// CompoundSelector) and we want to avoid the allocation.
|
// ComplexSelector) and we want to avoid the allocation.
|
||||||
pub selector: Arc<CompoundSelector<TheSelectorImpl>>,
|
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
|
||||||
pub declarations: DeclarationBlock,
|
pub declarations: DeclarationBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,6 +898,6 @@ impl<'a> DoubleEndedIterator for DeclarationBlockIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_push<Str: Eq + Hash>(map: &mut HashMap<Str, Vec<Rule>>, key: Str, value: Rule) {
|
fn find_push<Str: Eq + Hash>(map: &mut FnvHashMap<Str, Vec<Rule>>, key: Str, value: Rule) {
|
||||||
map.entry(key).or_insert_with(Vec::new).push(value)
|
map.entry(key).or_insert_with(Vec::new).push(value)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue