Title: [161010] trunk/Source/WebCore
Revision
161010
Author
[email protected]
Date
2013-12-23 12:21:28 -0800 (Mon, 23 Dec 2013)

Log Message

Add id matching to the Selector Code Generator
https://bugs.webkit.org/show_bug.cgi?id=126154

Reviewed by Antti Koivisto.

Compile matching for #id selectors. IDs are Atomic String so it is just a matter
of comparing the pointers.

No attempt is made at optimizing for the double #id case because such problem
do not really happen outside tests.

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
(WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
(WebCore::SelectorCompiler::SelectorCodeGenerator::compile):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementDataMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasId):
* dom/Element.h:
(WebCore::Element::elementDataMemoryOffset):
* dom/ElementData.h:
(WebCore::ElementData::idForStyleResolutionMemoryOffset):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (161009 => 161010)


--- trunk/Source/WebCore/ChangeLog	2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/ChangeLog	2013-12-23 20:21:28 UTC (rev 161010)
@@ -1,3 +1,28 @@
+2013-12-23  Benjamin Poulain  <[email protected]>
+
+        Add id matching to the Selector Code Generator
+        https://bugs.webkit.org/show_bug.cgi?id=126154
+
+        Reviewed by Antti Koivisto.
+
+        Compile matching for #id selectors. IDs are Atomic String so it is just a matter
+        of comparing the pointers.
+
+        No attempt is made at optimizing for the double #id case because such problem
+        do not really happen outside tests.
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::compile):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementDataMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasId):
+        * dom/Element.h:
+        (WebCore::Element::elementDataMemoryOffset):
+        * dom/ElementData.h:
+        (WebCore::ElementData::idForStyleResolutionMemoryOffset):
+
 2013-12-23  Oliver Hunt  <[email protected]>
 
         Update custom setter implementations to perform type checks

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (161009 => 161010)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2013-12-23 20:21:28 UTC (rev 161010)
@@ -87,7 +87,8 @@
         : traversalBacktrackingAction(BacktrackingAction::NoBacktracking)
         , matchingBacktrackingAction(BacktrackingAction::NoBacktracking)
         , backtrackingFlags(0)
-        , tagName(0)
+        , tagName(nullptr)
+        , id(nullptr)
     {
     }
     FragmentRelation relationToLeftFragment;
@@ -98,6 +99,7 @@
     unsigned char backtrackingFlags;
 
     const QualifiedName* tagName;
+    const AtomicString* id;
 };
 
 typedef JSC::MacroAssembler Assembler;
@@ -133,7 +135,9 @@
 
     // Element properties matchers.
     void generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
+    void generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch);
+    void generateElementHasId(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const AtomicString& idToMatch);
 
     Assembler m_assembler;
     RegisterAllocator m_registerAllocator;
@@ -142,6 +146,7 @@
 
     FunctionType m_functionType;
     Vector<SelectorFragment, 8> m_selectorFragments;
+    bool m_selectorCannotMatchAnything;
 
     StackAllocator::StackReference m_checkingContextStackReference;
 
@@ -189,6 +194,7 @@
 inline SelectorCodeGenerator::SelectorCodeGenerator(const CSSSelector* rootSelector)
     : m_stackAllocator(m_assembler)
     , m_functionType(FunctionType::SimpleSelectorChecker)
+    , m_selectorCannotMatchAnything(false)
 #if CSS_SELECTOR_JIT_DEBUGGING
     , m_originalSelector(rootSelector)
 #endif
@@ -205,8 +211,16 @@
             ASSERT(!fragment.tagName);
             fragment.tagName = &(selector->tagQName());
             break;
+        case CSSSelector::Id: {
+            const AtomicString& id = selector->value();
+            if (fragment.id) {
+                if (id != *fragment.id)
+                    goto InconsistentSelector;
+            } else
+                fragment.id = &(selector->value());
+            break;
+        }
         case CSSSelector::Unknown:
-        case CSSSelector::Id:
         case CSSSelector::Class:
         case CSSSelector::Exact:
         case CSSSelector::Set:
@@ -242,14 +256,16 @@
     computeBacktrackingInformation();
 
     return;
-
+InconsistentSelector:
+    m_functionType = FunctionType::SimpleSelectorChecker;
+    m_selectorCannotMatchAnything = true;
 CannotHandleSelector:
     m_selectorFragments.clear();
 }
 
 inline SelectorCompilationStatus SelectorCodeGenerator::compile(JSC::VM* vm, JSC::MacroAssemblerCodeRef& codeRef)
 {
-    if (m_selectorFragments.isEmpty())
+    if (m_selectorFragments.isEmpty() && !m_selectorCannotMatchAnything)
         return SelectorCompilationStatus::CannotCompile;
 
     m_registerAllocator.allocateRegister(elementAddressRegister);
@@ -284,12 +300,14 @@
     m_registerAllocator.deallocateRegister(elementAddressRegister);
 
     if (m_functionType == FunctionType::SimpleSelectorChecker) {
-        // Success.
-        m_assembler.move(Assembler::TrustedImm32(1), returnRegister);
-        m_assembler.ret();
+        if (!m_selectorCannotMatchAnything) {
+            // Success.
+            m_assembler.move(Assembler::TrustedImm32(1), returnRegister);
+            m_assembler.ret();
+        }
 
         // Failure.
-        if (!failureCases.empty()) {
+        if (m_selectorCannotMatchAnything || !failureCases.empty()) {
             failureCases.link(&m_assembler);
             m_assembler.move(Assembler::TrustedImm32(0), returnRegister);
             m_assembler.ret();
@@ -724,8 +742,25 @@
 {
     if (fragment.tagName)
         generateElementHasTagName(failureCases, *(fragment.tagName));
+    generateElementDataMatching(failureCases, fragment);
 }
 
+void SelectorCodeGenerator::generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+    if (!fragment.id)
+        return;
+
+    //  Generate:
+    //     elementDataAddress = element->elementData();
+    //     if (!elementDataAddress)
+    //         failure!
+    LocalRegister elementDataAddress(m_registerAllocator);
+    m_assembler.loadPtr(Assembler::Address(elementAddressRegister, Element::elementDataMemoryOffset()), elementDataAddress);
+    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, elementDataAddress));
+
+    generateElementHasId(failureCases, elementDataAddress, *fragment.id);
+}
+
 inline void SelectorCodeGenerator::generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch)
 {
     if (nameToMatch == anyQName())
@@ -752,6 +787,14 @@
     }
 }
 
+void SelectorCodeGenerator::generateElementHasId(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const AtomicString& idToMatch)
+{
+    // Compare the pointers of the AtomicStringImpl from idForStyleResolution with the reference idToMatch.
+    LocalRegister idToMatchRegister(m_registerAllocator);
+    m_assembler.move(Assembler::TrustedImmPtr(idToMatch.impl()), idToMatchRegister);
+    failureCases.append(m_assembler.branchPtr(Assembler::NotEqual, Assembler::Address(elementDataAddress, ElementData::idForStyleResolutionMemoryOffset()), idToMatchRegister));
+}
+
 }; // namespace SelectorCompiler.
 }; // namespace WebCore.
 

Modified: trunk/Source/WebCore/dom/Element.h (161009 => 161010)


--- trunk/Source/WebCore/dom/Element.h	2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/dom/Element.h	2013-12-23 20:21:28 UTC (rev 161010)
@@ -293,6 +293,7 @@
     void stripScriptingAttributes(Vector<Attribute>&) const;
 
     const ElementData* elementData() const { return m_elementData.get(); }
+    static ptrdiff_t elementDataMemoryOffset() { return OBJECT_OFFSETOF(Element, m_elementData); }
     UniqueElementData& ensureUniqueElementData();
 
     void synchronizeAllAttributes() const;

Modified: trunk/Source/WebCore/dom/ElementData.h (161009 => 161010)


--- trunk/Source/WebCore/dom/ElementData.h	2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/dom/ElementData.h	2013-12-23 20:21:28 UTC (rev 161010)
@@ -51,6 +51,7 @@
     const SpaceSplitString& classNames() const { return m_classNames; }
 
     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
+    static ptrdiff_t idForStyleResolutionMemoryOffset() { return OBJECT_OFFSETOF(ElementData, m_idForStyleResolution); }
     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
 
     const StyleProperties* inlineStyle() const { return m_inlineStyle.get(); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to