style: Finer grained invalidation for attribute changes.

This should help out quite a bit with uBO, which has lots of very
general attribute selectors. We invalidate per attribute name rather
than using a SelectorMap, which prevents matching for attribute
selectors that can't have changed.

The idea is that this should be generally cheaper, though there are
cases where this would be a slight pesimization. For example, if there's
an attribute selector like:

  my-specific-element[my-attribute] { /* ... */ }

And you change `my-attribute` in an element that isn't a
`my-specific-element`, before that the SelectorMap would've prevented us
from selector-matching completely. Now we'd still run selector-matching
for that (though the matching would be pretty cheap).

However I think this should speed up things generally, let's see what
the perf tests think before landing this though.

Differential Revision: https://phabricator.services.mozilla.com/D76825
This commit is contained in:
Emilio Cobos Álvarez 2020-05-27 09:17:47 +00:00
parent 4cf9aeeaf7
commit 964716f72a
5 changed files with 68 additions and 113 deletions

View file

@ -70,11 +70,15 @@ impl GeckoElementSnapshot {
self.mClassAttributeChanged()
}
/// Returns true if the snapshot recorded an attribute change which isn't a
/// class / id
/// Executes the callback once for each attribute that changed.
#[inline]
pub fn other_attr_changed(&self) -> bool {
self.mOtherAttributeChanged()
pub fn each_attr_changed<F>(&self, mut callback: F)
where
F: FnMut(&Atom),
{
for attr in self.mChangedAttrNames.iter() {
unsafe { Atom::with(attr.mRawPtr, &mut callback) }
}
}
/// selectors::Element::attr_matches