Title: [199583] trunk/Source/WebCore
Revision
199583
Author
[email protected]
Date
2016-04-15 00:54:20 -0700 (Fri, 15 Apr 2016)

Log Message

AffectsNextSibling style relation marking is inefficient
https://bugs.webkit.org/show_bug.cgi?id=156593

Reviewed by Benjamin Poulain.

We currently add a Style::Relation entry for each sibling to mark. With long sibling lists this can be inefficient
in terms of both memory and speed. Instead make a single entry that includes the sibling count to mark.

* css/SelectorChecker.cpp:
(WebCore::addStyleRelation):

    When adding AffectsNextSibling entry check if the last entry in the style relation vector has the
    same type and is part of the same sibling chain. If so just update the existing entry.

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelation):

    The same thing in hand-crafted macro assembler.

* cssjit/SelectorCompiler.h:

    Stop lying about the constness of the CheckingContext.

* style/StyleRelations.cpp:
(WebCore::Style::commitRelations):

    Mark as many sibling elements as the value indicates.

* style/StyleRelations.h:
(WebCore::Style::Relation::Relation):

    Make element a pointer so we can udpate it.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (199582 => 199583)


--- trunk/Source/WebCore/ChangeLog	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/ChangeLog	2016-04-15 07:54:20 UTC (rev 199583)
@@ -1,3 +1,38 @@
+2016-04-14  Antti Koivisto  <[email protected]>
+
+        AffectsNextSibling style relation marking is inefficient
+        https://bugs.webkit.org/show_bug.cgi?id=156593
+
+        Reviewed by Benjamin Poulain.
+
+        We currently add a Style::Relation entry for each sibling to mark. With long sibling lists this can be inefficient
+        in terms of both memory and speed. Instead make a single entry that includes the sibling count to mark.
+
+        * css/SelectorChecker.cpp:
+        (WebCore::addStyleRelation):
+
+            When adding AffectsNextSibling entry check if the last entry in the style relation vector has the
+            same type and is part of the same sibling chain. If so just update the existing entry.
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelation):
+
+            The same thing in hand-crafted macro assembler.
+
+        * cssjit/SelectorCompiler.h:
+
+            Stop lying about the constness of the CheckingContext.
+
+        * style/StyleRelations.cpp:
+        (WebCore::Style::commitRelations):
+
+            Mark as many sibling elements as the value indicates.
+
+        * style/StyleRelations.h:
+        (WebCore::Style::Relation::Relation):
+
+            Make element a pointer so we can udpate it.
+
 2016-04-15  Brady Eidson  <[email protected]>
 
         Add the message property to DOMError.

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (199582 => 199583)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2016-04-15 07:54:20 UTC (rev 199583)
@@ -89,6 +89,14 @@
     ASSERT(value == 1 || type == Style::Relation::NthChildIndex || type == Style::Relation::AffectedByEmpty);
     if (checkingContext.resolvingMode != SelectorChecker::Mode::ResolvingStyle)
         return;
+    if (type == Style::Relation::AffectsNextSibling && !checkingContext.styleRelations.isEmpty()) {
+        auto& last = checkingContext.styleRelations.last();
+        if (last.type == Style::Relation::AffectsNextSibling && last.element == element.nextElementSibling()) {
+            ++last.value;
+            last.element = &element;
+            return;
+        }
+    }
     checkingContext.styleRelations.append({ element, type, value });
 }
 

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (199582 => 199583)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-04-15 07:54:20 UTC (rev 199583)
@@ -2198,16 +2198,56 @@
 {
     ASSERT(m_selectorContext != SelectorContext::QuerySelector);
 
+    Assembler::Address vectorAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, styleRelations));
+    auto dataAddress = vectorAddress.withOffset(Style::Relations::dataMemoryOffset());
+    auto sizeAddress = vectorAddress.withOffset(Style::Relations::sizeMemoryOffset());
+
+    // For AffectsNextSibling we just increment the count if the previous added relation was in the same sibling chain.
+    Assembler::JumpList mergeSuccess;
+    if (relationType == Style::Relation::AffectsNextSibling) {
+        Assembler::JumpList mergeFailure;
+
+        LocalRegister lastRelation(m_registerAllocator);
+        m_assembler.load32(sizeAddress, lastRelation);
+
+        // if (!checkingContext.styleRelations.isEmpty())
+        mergeFailure.append(m_assembler.branchTest32(Assembler::Zero, lastRelation));
+
+        // Style::Relation& lastRelation = checkingContext.styleRelations.last();
+        m_assembler.sub32(Assembler::TrustedImm32(1), lastRelation);
+        m_assembler.mul32(Assembler::TrustedImm32(sizeof(Style::Relation)), lastRelation, lastRelation);
+        m_assembler.addPtr(dataAddress, lastRelation);
+
+        // if (lastRelation.type == Style::Relation::AffectsNextSibling)
+        Assembler::Address typeAddress(lastRelation, OBJECT_OFFSETOF(Style::Relation, type));
+        mergeFailure.append(m_assembler.branch32(Assembler::NotEqual, typeAddress, Assembler::TrustedImm32(Style::Relation::AffectsNextSibling)));
+
+        Assembler::Address elementAddress(lastRelation, OBJECT_OFFSETOF(Style::Relation, element));
+        {
+            // if (element.nextSiblingElement() == lastRelation.element)
+            LocalRegister nextSiblingElement(m_registerAllocator);
+            m_assembler.move(element, nextSiblingElement);
+            generateWalkToNextAdjacentElement(mergeFailure, nextSiblingElement);
+            mergeFailure.append(m_assembler.branchPtr(Assembler::NotEqual, nextSiblingElement, elementAddress));
+        }
+
+        // ++lastRelation.value;
+        Assembler::Address valueAddress(lastRelation, OBJECT_OFFSETOF(Style::Relation, value));
+        m_assembler.add32(Assembler::TrustedImm32(1), valueAddress);
+
+        // lastRelation.element = &element;
+        m_assembler.storePtr(element, elementAddress);
+
+        mergeSuccess.append(m_assembler.jump());
+        mergeFailure.link(&m_assembler);
+    }
+
     // FIXME: Append to vector without a function call at least when there is sufficient capacity.
     FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
     functionCall.setFunctionAddress(addStyleRelationFunction);
     functionCall.setTwoArguments(checkingContext, element);
     functionCall.call();
 
-    Assembler::Address vectorAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, styleRelations));
-    auto dataAddress = vectorAddress.withOffset(Style::Relations::dataMemoryOffset());
-    auto sizeAddress = vectorAddress.withOffset(Style::Relations::sizeMemoryOffset());
-
     LocalRegister relationPointer(m_registerAllocator);
     m_assembler.load32(sizeAddress, relationPointer);
     m_assembler.sub32(Assembler::TrustedImm32(1), relationPointer);
@@ -2221,6 +2261,8 @@
         Assembler::Address valueAddress(relationPointer, OBJECT_OFFSETOF(Style::Relation, value));
         m_assembler.store32(*value, valueAddress);
     }
+
+    mergeSuccess.link(&m_assembler);
 }
 
 Assembler::JumpList SelectorCodeGenerator::jumpIfNoPreviousAdjacentElement()

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.h (199582 => 199583)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.h	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.h	2016-04-15 07:54:20 UTC (rev 199583)
@@ -80,7 +80,7 @@
 typedef unsigned (*RuleCollectorSimpleSelectorChecker)(const Element*, unsigned*);
 typedef unsigned (*QuerySelectorSimpleSelectorChecker)(const Element*);
 
-typedef unsigned (*RuleCollectorSelectorCheckerWithCheckingContext)(const Element*, const SelectorChecker::CheckingContext*, unsigned*);
+typedef unsigned (*RuleCollectorSelectorCheckerWithCheckingContext)(const Element*, SelectorChecker::CheckingContext*, unsigned*);
 typedef unsigned (*QuerySelectorSelectorCheckerWithCheckingContext)(const Element*, const SelectorChecker::CheckingContext*);
 
 SelectorCompilationStatus compileSelector(const CSSSelector*, JSC::VM*, SelectorContext, JSC::MacroAssemblerCodeRef& outputCodeRef);

Modified: trunk/Source/WebCore/style/StyleRelations.cpp (199582 => 199583)


--- trunk/Source/WebCore/style/StyleRelations.cpp	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/style/StyleRelations.cpp	2016-04-15 07:54:20 UTC (rev 199583)
@@ -45,7 +45,7 @@
     };
 
     for (auto& relation : relations) {
-        if (&relation.element != &element) {
+        if (relation.element != &element) {
             appendStyleRelation(relation);
             continue;
         }
@@ -91,7 +91,7 @@
     if (!relations)
         return;
     for (auto& relation : *relations) {
-        auto& element = const_cast<Element&>(relation.element);
+        auto& element = const_cast<Element&>(*relation.element);
         switch (relation.type) {
         case Relation::AffectedByActive:
             element.setChildrenAffectedByActive();
@@ -108,9 +108,12 @@
         case Relation::AffectedByPreviousSibling:
             element.setStyleIsAffectedByPreviousSibling();
             break;
-        case Relation::AffectsNextSibling:
-            element.setAffectsNextSiblingElementStyle();
+        case Relation::AffectsNextSibling: {
+            auto* sibling = &element;
+            for (unsigned i = 0; i < relation.value && sibling; ++i, sibling = sibling->nextElementSibling())
+                sibling->setAffectsNextSiblingElementStyle();
             break;
+        }
         case Relation::ChildrenAffectedByBackwardPositionalRules:
             element.setChildrenAffectedByBackwardPositionalRules();
             break;

Modified: trunk/Source/WebCore/style/StyleRelations.h (199582 => 199583)


--- trunk/Source/WebCore/style/StyleRelations.h	2016-04-15 07:26:40 UTC (rev 199582)
+++ trunk/Source/WebCore/style/StyleRelations.h	2016-04-15 07:54:20 UTC (rev 199583)
@@ -44,6 +44,7 @@
         AffectedByEmpty,
         AffectedByHover,
         AffectedByPreviousSibling,
+        // For AffectsNextSibling 'value' tells how many element siblings to mark starting with 'element'.
         AffectsNextSibling,
         ChildrenAffectedByBackwardPositionalRules,
         ChildrenAffectedByFirstChildRules,
@@ -54,12 +55,12 @@
         NthChildIndex,
         Unique,
     };
-    const Element& element;
+    const Element* element;
     Type type;
     unsigned value;
 
     Relation(const Element& element, Type type, unsigned value = 1)
-        : element(element)
+        : element(&element)
         , type(type)
         , value(value)
     { }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to