diff options
author | Oriol Brufau <obrufau@igalia.com> | 2023-05-16 23:20:00 +0200 |
---|---|---|
committer | Oriol Brufau <obrufau@igalia.com> | 2023-05-16 23:40:23 +0200 |
commit | e23a8bf0ad5fcfc23395b74dccb571fe360ee0bb (patch) | |
tree | 29d93077cab51f4c297482cb7f2fa9afbaf2dced /components/selectors/parser.rs | |
parent | a7ca8022d3db119a77afdba6bdb70b82a90c58ac (diff) | |
download | servo-e23a8bf0ad5fcfc23395b74dccb571fe360ee0bb.tar.gz servo-e23a8bf0ad5fcfc23395b74dccb571fe360ee0bb.zip |
style: Add attribute names to the bloom filter
Safari does this. This reduces the runtime in the example linked from
comment 0 quite a lot (40ms on a local opt build, from ~130ms on a
release nightly build).
I added a pref because there's a slight chance of performance
regressions on pages that do not use attribute selectors, as we're now
doing more unconditional work per element (adding the attributes to the
bloom filter). But the trade-off should be worth it, I think.
Differential Revision: https://phabricator.services.mozilla.com/D111689
Diffstat (limited to 'components/selectors/parser.rs')
-rw-r--r-- | components/selectors/parser.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index e99b1b18412..73c1239035c 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -212,6 +212,12 @@ macro_rules! with_all_bounds { /// pseudo-elements type PseudoElement: $($CommonBounds)* + PseudoElement<Impl = Self>; + + /// Whether attribute hashes should be collected for filtering + /// purposes. + fn should_collect_attr_hash(_name: &Self::LocalName) -> bool { + false + } } } } @@ -482,6 +488,26 @@ where Component::Class(ref class) if quirks_mode != QuirksMode::Quirks => { class.precomputed_hash() }, + Component::AttributeInNoNamespace { ref local_name, .. } if Impl::should_collect_attr_hash(local_name) => { + // AttributeInNoNamespace is only used when local_name == + // local_name_lower. + local_name.precomputed_hash() + }, + Component::AttributeInNoNamespaceExists { ref local_name, ref local_name_lower, .. } => { + // Only insert the local-name into the filter if it's all + // lowercase. Otherwise we would need to test both hashes, and + // our data structures aren't really set up for that. + if local_name != local_name_lower || !Impl::should_collect_attr_hash(local_name) { + continue; + } + local_name.precomputed_hash() + }, + Component::AttributeOther(ref selector) => { + if selector.local_name != selector.local_name_lower || !Impl::should_collect_attr_hash(&selector.local_name) { + continue; + } + selector.local_name.precomputed_hash() + }, Component::Is(ref list) | Component::Where(ref list) => { // :where and :is OR their selectors, so we can't put any hash // in the filter if there's more than one selector, as that'd |