Move the ancestor hashes out of Selector.

MozReview-Commit-ID: 5mipXnjgSED
This commit is contained in:
Bobby Holley 2017-06-01 13:56:21 -07:00
parent e3d3c5a7b2
commit 713c9a63f6
8 changed files with 153 additions and 79 deletions

View file

@ -262,8 +262,8 @@ impl StylesheetInvalidationSet {
match *rule {
Style(ref lock) => {
let style_rule = lock.read_with(guard);
for selector in &style_rule.selectors.0 {
self.collect_scopes(selector);
for selector_and_hashes in &style_rule.selectors.0 {
self.collect_scopes(&selector_and_hashes.selector);
if self.fully_invalid {
return;
}

View file

@ -22,7 +22,8 @@ use selectors::Element;
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
use selectors::matching::{RelevantLinkStatus, VisitedHandlingMode, matches_selector};
use selectors::parser::{Combinator, Component, Selector, SelectorInner, SelectorMethods};
use selectors::parser::{AncestorHashes, Combinator, Component};
use selectors::parser::{Selector, SelectorAndHashes, SelectorInner, SelectorMethods};
use selectors::visitor::SelectorVisitor;
use smallvec::SmallVec;
use std::cell::Cell;
@ -867,7 +868,9 @@ impl Sensitivities {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Dependency {
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
selector: SelectorInner<SelectorImpl>,
selector: Selector<SelectorImpl>,
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
hashes: AncestorHashes,
/// The hint associated with this dependency.
pub hint: RestyleHint,
/// The sensitivities associated with this dependency.
@ -875,9 +878,13 @@ pub struct Dependency {
}
impl SelectorMapEntry for Dependency {
fn selector(&self) -> &SelectorInner<SelectorImpl> {
fn selector(&self) -> &Selector<SelectorImpl> {
&self.selector
}
fn hashes(&self) -> &AncestorHashes {
&self.hashes
}
}
/// The following visitor visits all the simple selectors for a given complex
@ -940,9 +947,9 @@ pub enum HintComputationContext<'a, E: 'a>
impl DependencySet {
/// Adds a selector to this `DependencySet`.
pub fn note_selector(&mut self, selector: &Selector<SelectorImpl>) {
pub fn note_selector(&mut self, selector_and_hashes: &SelectorAndHashes<SelectorImpl>) {
let mut combinator = None;
let mut iter = selector.inner.complex.iter();
let mut iter = selector_and_hashes.selector.inner.complex.iter();
let mut index = 0;
let mut child_combinators_seen = 0;
let mut saw_descendant_combinator = false;
@ -992,17 +999,25 @@ impl DependencySet {
None => RestyleHint::for_self(),
};
let dep_selector = if sequence_start == 0 {
let (dep_selector, hashes) = if sequence_start == 0 {
// Reuse the bloom hashes if this is the base selector.
selector.inner.clone()
(selector_and_hashes.selector.clone(),
selector_and_hashes.hashes.clone())
} else {
SelectorInner::new(selector.inner.complex.slice_from(sequence_start))
let inner = SelectorInner::new(selector_and_hashes.selector
.inner
.complex.slice_from(sequence_start));
let selector = Selector { inner: inner };
let hashes = AncestorHashes::new(&selector);
(selector, hashes)
};
self.dependencies.insert(Dependency {
sensitivities: visitor.sensitivities,
hint: hint,
selector: dep_selector,
hashes: hashes,
});
}
@ -1130,14 +1145,18 @@ impl DependencySet {
MatchingContext::new_for_visited(MatchingMode::Normal, None,
VisitedHandlingMode::AllLinksUnvisited);
let matched_then =
matches_selector(&dep.selector, &snapshot_el,
matches_selector(&dep.selector.inner,
&dep.hashes,
&snapshot_el,
&mut then_context,
&mut |_, _| {});
let mut now_context =
MatchingContext::new_for_visited(MatchingMode::Normal, bloom_filter,
VisitedHandlingMode::AllLinksUnvisited);
let matches_now =
matches_selector(&dep.selector, el,
matches_selector(&dep.selector.inner,
&dep.hashes,
el,
&mut now_context,
&mut |_, _| {});
@ -1162,12 +1181,16 @@ impl DependencySet {
dep.sensitivities.states.intersects(IN_VISITED_OR_UNVISITED_STATE) {
then_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
let matched_then =
matches_selector(&dep.selector, &snapshot_el,
matches_selector(&dep.selector.inner,
&dep.hashes,
&snapshot_el,
&mut then_context,
&mut |_, _| {});
now_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
let matches_now =
matches_selector(&dep.selector, el,
matches_selector(&dep.selector.inner,
&dep.hashes,
el,
&mut now_context,
&mut |_, _| {});
if matched_then != matches_now {

View file

@ -12,7 +12,7 @@ use pdqsort::sort_by;
use rule_tree::CascadeLevel;
use selector_parser::SelectorImpl;
use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags};
use selectors::parser::{Component, Combinator, SelectorInner};
use selectors::parser::{AncestorHashes, Component, Combinator, Selector, SelectorAndHashes};
use selectors::parser::LocalName as LocalNameSelector;
use smallvec::VecLike;
use std::borrow::Borrow;
@ -22,13 +22,20 @@ use stylist::{ApplicableDeclarationBlock, Rule};
/// A trait to abstract over a given selector map entry.
pub trait SelectorMapEntry : Sized + Clone {
/// Get the selector we should use to index in the selector map.
fn selector(&self) -> &SelectorInner<SelectorImpl>;
/// Gets the selector we should use to index in the selector map.
fn selector(&self) -> &Selector<SelectorImpl>;
/// Gets the ancestor hashes associated with the selector.
fn hashes(&self) -> &AncestorHashes;
}
impl SelectorMapEntry for SelectorInner<SelectorImpl> {
fn selector(&self) -> &SelectorInner<SelectorImpl> {
self
impl SelectorMapEntry for SelectorAndHashes<SelectorImpl> {
fn selector(&self) -> &Selector<SelectorImpl> {
&self.selector
}
fn hashes(&self) -> &AncestorHashes {
&self.hashes
}
}
@ -225,6 +232,7 @@ impl SelectorMap<Rule> {
{
for rule in rules {
if matches_selector(&rule.selector.inner,
&rule.hashes,
element,
context,
flags_setter) {
@ -390,12 +398,12 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
///
/// Effectively, pseudo-elements are ignored, given only state pseudo-classes
/// may appear before them.
fn find_from_right<F, R>(selector: &SelectorInner<SelectorImpl>,
fn find_from_right<F, R>(selector: &Selector<SelectorImpl>,
mut f: F)
-> Option<R>
where F: FnMut(&Component<SelectorImpl>) -> Option<R>,
{
let mut iter = selector.complex.iter();
let mut iter = selector.inner.complex.iter();
for ss in &mut iter {
if let Some(r) = f(ss) {
return Some(r)
@ -414,7 +422,7 @@ fn find_from_right<F, R>(selector: &SelectorInner<SelectorImpl>,
}
/// Retrieve the first ID name in the selector, or None otherwise.
pub fn get_id_name(selector: &SelectorInner<SelectorImpl>)
pub fn get_id_name(selector: &Selector<SelectorImpl>)
-> Option<Atom> {
find_from_right(selector, |ss| {
// TODO(pradeep): Implement case-sensitivity based on the
@ -427,7 +435,7 @@ pub fn get_id_name(selector: &SelectorInner<SelectorImpl>)
}
/// Retrieve the FIRST class name in the selector, or None otherwise.
pub fn get_class_name(selector: &SelectorInner<SelectorImpl>)
pub fn get_class_name(selector: &Selector<SelectorImpl>)
-> Option<Atom> {
find_from_right(selector, |ss| {
// TODO(pradeep): Implement case-sensitivity based on the
@ -440,7 +448,7 @@ pub fn get_class_name(selector: &SelectorInner<SelectorImpl>)
}
/// Retrieve the name if it is a type selector, or None otherwise.
pub fn get_local_name(selector: &SelectorInner<SelectorImpl>)
pub fn get_local_name(selector: &Selector<SelectorImpl>)
-> Option<LocalNameSelector<SelectorImpl>> {
find_from_right(selector, |ss| {
if let Component::LocalName(ref n) = *ss {

View file

@ -28,7 +28,8 @@ use selectors::attr::NamespaceConstraint;
use selectors::bloom::BloomFilter;
use selectors::matching::{ElementSelectorFlags, matches_selector, MatchingContext, MatchingMode};
use selectors::matching::AFFECTED_BY_PRESENTATIONAL_HINTS;
use selectors::parser::{Combinator, Component, Selector, SelectorInner, SelectorIter, SelectorMethods};
use selectors::parser::{AncestorHashes, Combinator, Component, Selector, SelectorAndHashes};
use selectors::parser::{SelectorIter, SelectorMethods};
use selectors::visitor::SelectorVisitor;
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use sink::Push;
@ -159,7 +160,7 @@ pub struct Stylist {
/// on state that is not otherwise visible to the cache, like attributes or
/// tree-structural state like child index and pseudos).
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
selectors_for_cache_revalidation: SelectorMap<SelectorInner<SelectorImpl>>,
selectors_for_cache_revalidation: SelectorMap<SelectorAndHashes<SelectorImpl>>,
/// The total number of selectors.
num_selectors: usize,
@ -454,10 +455,10 @@ impl Stylist {
CssRule::Style(ref locked) => {
let style_rule = locked.read_with(&guard);
self.num_declarations += style_rule.block.read_with(&guard).len();
for selector in &style_rule.selectors.0 {
for selector_and_hashes in &style_rule.selectors.0 {
self.num_selectors += 1;
let map = if let Some(pseudo) = selector.pseudo_element() {
let map = if let Some(pseudo) = selector_and_hashes.selector.pseudo_element() {
self.pseudos_map
.entry(pseudo.canonical())
.or_insert_with(PerPseudoElementSelectorMap::new)
@ -466,20 +467,21 @@ impl Stylist {
self.element_map.borrow_for_origin(&stylesheet.origin)
};
map.insert(Rule::new(selector.clone(),
map.insert(Rule::new(selector_and_hashes.selector.clone(),
selector_and_hashes.hashes.clone(),
locked.clone(),
self.rules_source_order));
self.dependencies.note_selector(selector);
if needs_revalidation(selector) {
self.selectors_for_cache_revalidation.insert(selector.inner.clone());
self.dependencies.note_selector(selector_and_hashes);
if needs_revalidation(&selector_and_hashes.selector) {
self.selectors_for_cache_revalidation.insert(selector_and_hashes.clone());
}
selector.visit(&mut AttributeAndStateDependencyVisitor {
selector_and_hashes.selector.visit(&mut AttributeAndStateDependencyVisitor {
attribute_dependencies: &mut self.attribute_dependencies,
style_attribute_dependency: &mut self.style_attribute_dependency,
state_dependencies: &mut self.state_dependencies,
});
selector.visit(&mut MappedIdVisitor {
selector_and_hashes.selector.visit(&mut MappedIdVisitor {
mapped_ids: &mut self.mapped_ids,
});
}
@ -1130,8 +1132,9 @@ impl Stylist {
// the lookups, which means that the bitvecs are comparable. We verify
// this in the caller by asserting that the bitvecs are same-length.
let mut results = BitVec::new();
self.selectors_for_cache_revalidation.lookup(*element, &mut |selector| {
results.push(matches_selector(selector,
self.selectors_for_cache_revalidation.lookup(*element, &mut |selector_and_hashes| {
results.push(matches_selector(&selector_and_hashes.selector.inner,
&selector_and_hashes.hashes,
element,
&mut matching_context,
flags_setter));
@ -1410,6 +1413,9 @@ pub struct Rule {
/// can ruin performance when there are a lot of rules.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub selector: Selector<SelectorImpl>,
/// The ancestor hashes associated with the selector.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
pub hashes: AncestorHashes,
/// The actual style rule.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub style_rule: Arc<Locked<StyleRule>>,
@ -1418,8 +1424,12 @@ pub struct Rule {
}
impl SelectorMapEntry for Rule {
fn selector(&self) -> &SelectorInner<SelectorImpl> {
&self.selector.inner
fn selector(&self) -> &Selector<SelectorImpl> {
&self.selector
}
fn hashes(&self) -> &AncestorHashes {
&self.hashes
}
}
@ -1444,12 +1454,14 @@ impl Rule {
/// Creates a new Rule.
pub fn new(selector: Selector<SelectorImpl>,
hashes: AncestorHashes,
style_rule: Arc<Locked<StyleRule>>,
source_order: usize)
-> Self
{
Rule {
selector: selector,
hashes: hashes,
style_rule: style_rule,
source_order: source_order,
}