Bug 1854151: Optimize the relative selector check path when no relative selector is used. r=emilio

* Lazily calculate changed states and classes when processing pending state & attribute invalidations
* Avoid constructing empty `SmallVec` invalidations when we know there is no invalidation

Differential Revision: https://phabricator.services.mozilla.com/D188733
This commit is contained in:
David Shin 2023-09-20 17:01:09 +00:00
parent 4b221aa6ec
commit 7b67eb8bae
2 changed files with 19 additions and 7 deletions

View file

@ -257,6 +257,10 @@ where
self.add_dependency(dependency, element, *scope); self.add_dependency(dependency, element, *scope);
} }
} }
fn is_empty(&self) -> bool {
self.invalidations.is_empty()
}
} }
impl<'a, E> RelativeSelectorInvalidator<'a, E> impl<'a, E> RelativeSelectorInvalidator<'a, E>
@ -267,9 +271,9 @@ where
pub fn invalidate_relative_selectors_for_this<F>( pub fn invalidate_relative_selectors_for_this<F>(
self, self,
stylist: &'a Stylist, stylist: &'a Stylist,
gather_dependencies: F, mut gather_dependencies: F,
) where ) where
F: Fn( F: FnMut(
&E, &E,
&Option<E>, &Option<E>,
&'a CascadeData, &'a CascadeData,
@ -291,6 +295,9 @@ where
&mut collector, &mut collector,
); );
}); });
if collector.is_empty() {
return;
}
self.invalidate_from_dependencies(collector.get()); self.invalidate_from_dependencies(collector.get());
} }
@ -330,6 +337,9 @@ where
}); });
} }
} }
if collector.is_empty() {
return;
}
self.invalidate_from_dependencies(collector.get()); self.invalidate_from_dependencies(collector.get());
} }

View file

@ -7496,8 +7496,8 @@ fn process_relative_selector_invalidations(
None => return, None => return,
Some(s) => s, Some(s) => s,
}; };
let state_changes = ElementWrapper::new(*element, snapshot_table).state_changes(); let mut states = None;
let classes_changed = classes_changed(element, snapshot_table); let mut classes = None;
let quirks_mode: QuirksMode = data.stylist.quirks_mode(); let quirks_mode: QuirksMode = data.stylist.quirks_mode();
let invalidator = RelativeSelectorInvalidator { let invalidator = RelativeSelectorInvalidator {
@ -7512,6 +7512,8 @@ fn process_relative_selector_invalidations(
&data.stylist, &data.stylist,
|element, scope, data, quirks_mode, collector| { |element, scope, data, quirks_mode, collector| {
let invalidation_map = data.relative_selector_invalidation_map(); let invalidation_map = data.relative_selector_invalidation_map();
let states = *states.get_or_insert_with(|| ElementWrapper::new(*element, snapshot_table).state_changes());
let classes = classes.get_or_insert_with(|| classes_changed(element, snapshot_table));
if snapshot.id_changed() { if snapshot.id_changed() {
relative_selector_dependencies_for_id( relative_selector_dependencies_for_id(
element.id().map(|id| id.as_ptr().cast_const()).unwrap_or(ptr::null()), element.id().map(|id| id.as_ptr().cast_const()).unwrap_or(ptr::null()),
@ -7523,13 +7525,13 @@ fn process_relative_selector_invalidations(
collector, collector,
); );
} }
relative_selector_dependencies_for_class(&classes_changed, element, scope, quirks_mode, invalidation_map, collector); relative_selector_dependencies_for_class(&classes, element, scope, quirks_mode, invalidation_map, collector);
snapshot.each_attr_changed(|attr| add_relative_selector_attribute_dependency(element, &scope, invalidation_map, attr, collector)); snapshot.each_attr_changed(|attr| add_relative_selector_attribute_dependency(element, &scope, invalidation_map, attr, collector));
invalidation_map invalidation_map
.map .map
.state_affecting_selectors .state_affecting_selectors
.lookup_with_additional(*element, quirks_mode, None, &[], state_changes, |dependency| { .lookup_with_additional(*element, quirks_mode, None, &[], states, |dependency| {
if !dependency.state.intersects(state_changes) { if !dependency.state.intersects(states) {
return true; return true;
} }
collector.add_dependency(&dependency.dep, *element, *scope); collector.add_dependency(&dependency.dep, *element, *scope);