diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2023-06-14 21:08:22 +0000 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-11-24 08:57:14 +0100 |
commit | de9fb7983aa72da9b531bbe3d004e0b859615d47 (patch) | |
tree | c3ceab554d16a734d92972d24048d55c5209b2a3 /components/style/gecko/wrapper.rs | |
parent | 8c5a028955939e4716d9caa157d0eafa394f3973 (diff) | |
download | servo-de9fb7983aa72da9b531bbe3d004e0b859615d47.tar.gz servo-de9fb7983aa72da9b531bbe3d004e0b859615d47.zip |
style: Speed up / specialize attribute selector-matching
Inline the attribute lookup code, and only branch on the attribute selector
type if we have found an attribute.
Differential Revision: https://phabricator.services.mozilla.com/D180531
Diffstat (limited to 'components/style/gecko/wrapper.rs')
-rw-r--r-- | components/style/gecko/wrapper.rs | 148 |
1 files changed, 44 insertions, 104 deletions
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 98b5de4f44c..490c063fbe7 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -68,8 +68,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use dom::{DocumentState, ElementState}; use euclid::default::Size2D; use fxhash::FxHashMap; -use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator}; -use selectors::attr::{CaseSensitivity, NamespaceConstraint}; +use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint}; use selectors::matching::VisitedHandlingMode; use selectors::matching::{ElementSelectorFlags, MatchingContext}; use selectors::sink::Push; @@ -590,25 +589,28 @@ impl<'le> GeckoElement<'le> { } #[inline(always)] + fn attrs(&self) -> Option<&structs::AttrArray_Impl> { + unsafe { self.0.mAttrs.mImpl.mPtr.as_ref() } + } + + #[inline(always)] fn non_mapped_attrs(&self) -> &[structs::AttrArray_InternalAttr] { + let attrs = match self.attrs() { + Some(attrs) => attrs, + None => return &[], + }; unsafe { - let attrs = match self.0.mAttrs.mImpl.mPtr.as_ref() { - Some(attrs) => attrs, - None => return &[], - }; - attrs.mBuffer.as_slice(attrs.mAttrCount as usize) } } #[inline(always)] fn mapped_attrs(&self) -> &[structs::AttrArray_InternalAttr] { + let attrs = match self.attrs() { + Some(attrs) => attrs, + None => return &[], + }; unsafe { - let attrs = match self.0.mAttrs.mImpl.mPtr.as_ref() { - Some(attrs) => attrs, - None => return &[], - }; - let attrs = match attrs.mMappedAttrs.as_ref() { Some(attrs) => attrs, None => return &[], @@ -618,6 +620,11 @@ impl<'le> GeckoElement<'le> { } } + #[inline] + fn iter_attrs(&self) -> impl Iterator<Item = &structs::AttrArray_InternalAttr> { + self.non_mapped_attrs().iter().chain(self.mapped_attrs().iter()) + } + #[inline(always)] fn get_part_attr(&self) -> Option<&structs::nsAttrValue> { if !self.has_part_attr() { @@ -924,6 +931,16 @@ fn get_animation_rule( } } +/// Turns a gecko namespace id into an atom. Might panic if you pass any random thing that isn't a +/// namespace id. +#[inline(always)] +pub unsafe fn namespace_id_to_atom(id: i32) -> *mut nsAtom { + unsafe { + let namespace_manager = structs::nsNameSpaceManager_sInstance.mRawPtr; + (*namespace_manager).mURIArray[id as usize].mRawPtr + } +} + impl<'le> TElement for GeckoElement<'le> { type ConcreteNode = GeckoNode<'le>; type TraversalChildrenIterator = GeckoChildrenIterator<'le>; @@ -1004,10 +1021,7 @@ impl<'le> TElement for GeckoElement<'le> { #[inline] fn namespace(&self) -> &WeakNamespace { - unsafe { - let namespace_manager = structs::nsNameSpaceManager_sInstance.mRawPtr; - WeakNamespace::new((*namespace_manager).mURIArray[self.namespace_id() as usize].mRawPtr) - } + unsafe { WeakNamespace::new(namespace_id_to_atom(self.namespace_id())) } } #[inline] @@ -1201,20 +1215,9 @@ impl<'le> TElement for GeckoElement<'le> { where F: FnMut(&AtomIdent), { - for attr in self - .non_mapped_attrs() - .iter() - .chain(self.mapped_attrs().iter()) - { - let is_nodeinfo = attr.mName.mBits & 1 != 0; + for attr in self.iter_attrs() { unsafe { - let atom = if is_nodeinfo { - let node_info = &*((attr.mName.mBits & !1) as *const structs::NodeInfo); - node_info.mInner.mName - } else { - attr.mName.mBits as *const nsAtom - }; - AtomIdent::with(atom, |a| callback(a)) + AtomIdent::with(attr.mName.name(), |a| callback(a)) } } } @@ -1847,73 +1850,25 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } } + fn has_attr_in_no_namespace(&self, local_name: &LocalName) -> bool { + for attr in self.iter_attrs() { + if attr.mName.mBits == local_name.as_ptr() as usize { + return true; + } + } + false + } + fn attr_matches( &self, ns: &NamespaceConstraint<&Namespace>, local_name: &LocalName, operation: &AttrSelectorOperation<&AttrValue>, ) -> bool { - unsafe { - match *operation { - AttrSelectorOperation::Exists => { - bindings::Gecko_HasAttr(self.0, ns.atom_or_null(), local_name.as_ptr()) - }, - AttrSelectorOperation::WithValue { - operator, - case_sensitivity, - value, - } => { - let ignore_case = match case_sensitivity { - CaseSensitivity::CaseSensitive => false, - CaseSensitivity::AsciiCaseInsensitive => true, - }; - match operator { - AttrSelectorOperator::Equal => bindings::Gecko_AttrEquals( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - AttrSelectorOperator::Includes => bindings::Gecko_AttrIncludes( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - AttrSelectorOperator::DashMatch => bindings::Gecko_AttrDashEquals( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - AttrSelectorOperator::Prefix => bindings::Gecko_AttrHasPrefix( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - AttrSelectorOperator::Suffix => bindings::Gecko_AttrHasSuffix( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - AttrSelectorOperator::Substring => bindings::Gecko_AttrHasSubstring( - self.0, - ns.atom_or_null(), - local_name.as_ptr(), - value.as_ptr(), - ignore_case, - ), - } - }, - } + if self.attrs().is_none() { + return false; } + snapshot_helpers::attr_matches(self.iter_attrs(), ns, local_name, operation) } #[inline] @@ -2168,18 +2123,3 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { self.is_root_of_native_anonymous_subtree() } } - -/// A few helpers to help with attribute selectors and snapshotting. -pub trait NamespaceConstraintHelpers { - /// Returns the namespace of the selector, or null otherwise. - fn atom_or_null(&self) -> *mut nsAtom; -} - -impl<'a> NamespaceConstraintHelpers for NamespaceConstraint<&'a Namespace> { - fn atom_or_null(&self) -> *mut nsAtom { - match *self { - NamespaceConstraint::Any => ptr::null_mut(), - NamespaceConstraint::Specific(ref ns) => ns.0.as_ptr(), - } - } -} |