Title: [166537] trunk/Source/WebCore
Revision
166537
Author
[email protected]
Date
2014-03-31 15:19:04 -0700 (Mon, 31 Mar 2014)

Log Message

CSS JIT: compile the first-child pseudo class
https://bugs.webkit.org/show_bug.cgi?id=130954

Reviewed by Andreas Kling.

* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::collectMatchingRules):
The compiler use the context's style directly when resolving style. An error introduced
in the rule collector would cause a crash in the compiled code which would be hard to debug.
Add an assertion early in the stack to catch errors where it is easier to debug them.

* css/StyleResolver.cpp:
(WebCore::StyleResolver::State::initForStyleResolve):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoType):
(WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacentElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacent):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
Refactor those to be able to reuse the code getting a sibling element preceding the current element.

(WebCore::SelectorCompiler::SelectorCodeGenerator::jumpIfNotResolvingStyle):
Extract the code checking the current mode from SelectorCodeGenerator::markParentElementIfResolvingStyle()
in a separate function. This will be useful for all the pseudo class with marking.

(WebCore::SelectorCompiler::SelectorCodeGenerator::markParentElementIfResolvingStyle):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::setFirstChildState):
This is the slow path for when the first-child pseudo class is on a fragment that is not
the rightmost.
The reason to use a slow path is accessing renderStyle() is not trivial and this case isn't not
as common. We should improve this later.

(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsFirstChild):
This is just implementing the test for first-child plus the tree marking. Nothing fancy,
this is basically the same thing as SelectorChecker.

* dom/Element.cpp:
(WebCore::Element::setChildrenAffectedByFirstChildRules):
* dom/Element.h:
C++ fallback to set the flag, to be improved later with the other flags.

* rendering/style/RenderStyle.h:
I accidentaly put noninheritedFlagsMemoryOffset() as private in the RenderStyle refactoring.

Also update the flags accessor to make them easier to work with from the compiler. In particular,
setFirstChildStateFlags() sets both isUnique and firstChild. Currently the JIT does not need to access
the value so individual flags are made private.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (166536 => 166537)


--- trunk/Source/WebCore/ChangeLog	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/ChangeLog	2014-03-31 22:19:04 UTC (rev 166537)
@@ -1,3 +1,55 @@
+2014-03-31  Benjamin Poulain  <[email protected]>
+
+        CSS JIT: compile the first-child pseudo class
+        https://bugs.webkit.org/show_bug.cgi?id=130954
+
+        Reviewed by Andreas Kling.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::collectMatchingRules):
+        The compiler use the context's style directly when resolving style. An error introduced
+        in the rule collector would cause a crash in the compiled code which would be hard to debug.
+        Add an assertion early in the stack to catch errors where it is easier to debug them.
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::State::initForStyleResolve):
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoType):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacentElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacent):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
+        Refactor those to be able to reuse the code getting a sibling element preceding the current element.
+
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::jumpIfNotResolvingStyle):
+        Extract the code checking the current mode from SelectorCodeGenerator::markParentElementIfResolvingStyle()
+        in a separate function. This will be useful for all the pseudo class with marking.
+
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::markParentElementIfResolvingStyle):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::setFirstChildState):
+        This is the slow path for when the first-child pseudo class is on a fragment that is not
+        the rightmost.
+        The reason to use a slow path is accessing renderStyle() is not trivial and this case isn't not
+        as common. We should improve this later.
+
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsFirstChild):
+        This is just implementing the test for first-child plus the tree marking. Nothing fancy,
+        this is basically the same thing as SelectorChecker.
+
+        * dom/Element.cpp:
+        (WebCore::Element::setChildrenAffectedByFirstChildRules):
+        * dom/Element.h:
+        C++ fallback to set the flag, to be improved later with the other flags.
+
+        * rendering/style/RenderStyle.h:
+        I accidentaly put noninheritedFlagsMemoryOffset() as private in the RenderStyle refactoring.
+
+        Also update the flags accessor to make them easier to work with from the compiler. In particular,
+        setFirstChildStateFlags() sets both isUnique and firstChild. Currently the JIT does not need to access
+        the value so individual flags are made private.
+
 2014-03-31  Dean Jackson  <[email protected]>
 
         Remove WEB_ANIMATIONS

Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (166536 => 166537)


--- trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-03-31 22:19:04 UTC (rev 166537)
@@ -145,6 +145,7 @@
 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
 {
     ASSERT(matchRequest.ruleSet);
+    ASSERT_WITH_MESSAGE(!(m_mode == SelectorChecker::ResolvingStyle && !m_style), "When resolving style, the SelectorChecker must have a style to set the pseudo elements and/or to do marking. The SelectorCompiler also rely on that behavior.");
 
     const AtomicString& pseudoId = m_element.shadowPseudoId();
     if (!pseudoId.isEmpty())

Modified: trunk/Source/WebCore/css/StyleResolver.cpp (166536 => 166537)


--- trunk/Source/WebCore/css/StyleResolver.cpp	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/css/StyleResolver.cpp	2014-03-31 22:19:04 UTC (rev 166537)
@@ -419,7 +419,7 @@
     RenderStyle* docStyle = document.renderStyle();
     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
 
-    m_style = 0;
+    m_style = nullptr;
     m_pendingImageProperties.clear();
     m_fontDirty = false;
 }

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (166536 => 166537)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-03-31 22:19:04 UTC (rev 166537)
@@ -49,6 +49,7 @@
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
+#include <wtf/text/CString.h>
 
 namespace WebCore {
 namespace SelectorCompiler {
@@ -155,6 +156,7 @@
     void generateParentElementTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateAncestorTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&);
 
+    void generateWalkToPreviousAdjacentElement(Assembler::JumpList& failureCases, Assembler::RegisterID);
     void generateWalkToPreviousAdjacent(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateDirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateIndirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&);
@@ -169,6 +171,7 @@
     void generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr);
+    void generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateSynchronizeStyleAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
     void generateSynchronizeAllAnimatedSVGAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
     void generateElementAttributesMatching(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const SelectorFragment&);
@@ -181,6 +184,9 @@
     void generateElementHasClasses(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const Vector<const AtomicStringImpl*>& classNames);
     void generateElementIsLink(Assembler::JumpList& failureCases);
 
+    // Helpers.
+    Assembler::Jump jumpIfNotResolvingStyle(Assembler::RegisterID checkingContextRegister);
+
     Assembler m_assembler;
     RegisterAllocator m_registerAllocator;
     StackAllocator m_stackAllocator;
@@ -238,7 +244,7 @@
     return std::max(a, b);
 }
 
-static inline FunctionType addPseudoType(CSSSelector::PseudoType type, SelectorFragment& pseudoClasses)
+static inline FunctionType addPseudoType(CSSSelector::PseudoType type, SelectorFragment& pseudoClasses, SelectorContext selectorContext)
 {
     switch (type) {
     // Unoptimized pseudo selector. They are just function call to a simple testing function.
@@ -304,6 +310,12 @@
         pseudoClasses.pseudoClasses.add(type);
         return FunctionType::SimpleSelectorChecker;
 
+    case CSSSelector::PseudoFirstChild:
+        pseudoClasses.pseudoClasses.add(type);
+        if (selectorContext == SelectorContext::QuerySelector)
+            return FunctionType::SimpleSelectorChecker;
+        return FunctionType::SelectorCheckerWithCheckingContext;
+
     default:
         break;
     }
@@ -345,7 +357,7 @@
             fragment.classNames.append(selector->value().impl());
             break;
         case CSSSelector::PseudoClass:
-            m_functionType = mostRestrictiveFunctionType(m_functionType, addPseudoType(selector->pseudoType(), fragment));
+            m_functionType = mostRestrictiveFunctionType(m_functionType, addPseudoType(selector->pseudoType(), fragment, m_selectorContext));
             if (m_functionType == FunctionType::CannotCompile || m_functionType == FunctionType::CannotMatchAnything)
                 return;
             break;
@@ -769,6 +781,14 @@
     tagMatchingLocalFailureCases.linkTo(loopStart, &m_assembler);
 }
 
+inline void SelectorCodeGenerator::generateWalkToPreviousAdjacentElement(Assembler::JumpList& failureCases, Assembler::RegisterID workRegister)
+{
+    Assembler::Label loopStart = m_assembler.label();
+    m_assembler.loadPtr(Assembler::Address(workRegister, Node::previousSiblingMemoryOffset()), workRegister);
+    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, workRegister));
+    testIsElementFlagOnNode(Assembler::Zero, m_assembler, workRegister).linkTo(loopStart, &m_assembler);
+}
+
 void SelectorCodeGenerator::generateWalkToPreviousAdjacent(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
 {
     //    do {
@@ -788,10 +808,9 @@
     } else
         previousSibling = elementAddressRegister;
 
-    Assembler::Label loopStart = m_assembler.label();
-    m_assembler.loadPtr(Assembler::Address(previousSibling, Node::previousSiblingMemoryOffset()), previousSibling);
-    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, previousSibling));
-    testIsElementFlagOnNode(Assembler::Zero, m_assembler, previousSibling).linkTo(loopStart, &m_assembler);
+    Assembler::JumpList traversalFailureCases;
+    generateWalkToPreviousAdjacentElement(traversalFailureCases, previousSibling);
+    linkFailures(failureCases, fragment.traversalBacktrackingAction, traversalFailureCases);
 
     // On success, move previousSibling over to elementAddressRegister if we could not work on elementAddressRegister directly.
     if (!useTailOnTraversalFailure) {
@@ -804,9 +823,7 @@
 {
     markParentElementIfResolvingStyle(Element::setChildrenAffectedByDirectAdjacentRules);
 
-    Assembler::JumpList traversalFailureCases;
-    generateWalkToPreviousAdjacent(traversalFailureCases, fragment);
-    linkFailures(failureCases, fragment.traversalBacktrackingAction, traversalFailureCases);
+    generateWalkToPreviousAdjacent(failureCases, fragment);
 
     Assembler::JumpList matchingFailureCases;
     generateElementMatching(matchingFailureCases, fragment);
@@ -822,9 +839,7 @@
 
     Assembler::Label loopStart(m_assembler.label());
 
-    Assembler::JumpList traversalFailureCases;
-    generateWalkToPreviousAdjacent(traversalFailureCases, fragment);
-    linkFailures(failureCases, fragment.traversalBacktrackingAction, traversalFailureCases);
+    generateWalkToPreviousAdjacent(failureCases, fragment);
 
     if (fragment.backtrackingFlags & BacktrackingFlag::IndirectAdjacentEntryPoint)
         m_indirectAdjacentEntryPoint = m_assembler.label();
@@ -834,6 +849,18 @@
     localFailureCases.linkTo(loopStart, &m_assembler);
 }
 
+Assembler::Jump SelectorCodeGenerator::jumpIfNotResolvingStyle(Assembler::RegisterID checkingContext)
+{
+    RELEASE_ASSERT(m_selectorContext == SelectorContext::RuleCollector);
+
+    // Get the checking context.
+    unsigned offsetToCheckingContext = m_stackAllocator.offsetToStackReference(m_checkingContextStackReference);
+    m_assembler.loadPtr(Assembler::Address(Assembler::stackPointerRegister, offsetToCheckingContext), checkingContext);
+
+    // If we not resolving style, skip the whole marking.
+    return m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, resolvingMode)), Assembler::TrustedImm32(SelectorChecker::ResolvingStyle));
+}
+
 void SelectorCodeGenerator::markParentElementIfResolvingStyle(JSC::FunctionPtr markingFunction)
 {
     if (m_selectorContext == SelectorContext::QuerySelector)
@@ -843,19 +870,15 @@
     //         Element* parent = element->parentNode();
     //         markingFunction(parent);
     //     }
-    Assembler::JumpList failedToGetParent;
+
     Assembler::Jump notResolvingStyle;
     {
-        // Get the checking context.
-        unsigned offsetToCheckingContext = m_stackAllocator.offsetToStackReference(m_checkingContextStackReference);
         LocalRegister checkingContext(m_registerAllocator);
-        m_assembler.loadPtr(Assembler::Address(Assembler::stackPointerRegister, offsetToCheckingContext), checkingContext);
-
-        // If we not resolving style, skip the whole marking.
-        notResolvingStyle = m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, resolvingMode)), Assembler::TrustedImm32(SelectorChecker::ResolvingStyle));
+        notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
     }
 
     // Get the parent element in a temporary register.
+    Assembler::JumpList failedToGetParent;
     Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister();
     generateWalkToParentElement(failedToGetParent, parentElement);
 
@@ -963,6 +986,9 @@
         generateElementFunctionCallTest(failureCases, fragment.unoptimizedPseudoClasses[i]);
 
     generateElementDataMatching(failureCases, fragment);
+
+    if (fragment.pseudoClasses.contains(CSSSelector::PseudoFirstChild))
+        generateElementIsFirstChild(failureCases, fragment);
 }
 
 void SelectorCodeGenerator::generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
@@ -1381,6 +1407,82 @@
     failureCases.append(functionCall.callAndBranchOnCondition(Assembler::Zero));
 }
 
+static void setFirstChildState(Element* element)
+{
+    if (RenderStyle* style = element->renderStyle())
+        style->setFirstChildState();
+}
+
+void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+    if (m_selectorContext == SelectorContext::QuerySelector) {
+        Assembler::JumpList successCase;
+        LocalRegister previousSibling(m_registerAllocator);
+        m_assembler.move(elementAddressRegister, previousSibling);
+        generateWalkToPreviousAdjacentElement(successCase, previousSibling);
+        failureCases.append(m_assembler.jump());
+        successCase.link(&m_assembler);
+        LocalRegister parent(m_registerAllocator);
+        generateWalkToParentElement(failureCases, parent);
+        return;
+    }
+
+    Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister();
+    generateWalkToParentElement(failureCases, parentElement);
+
+    // Zero in isFirstChildRegister is the success case. The register is set to non-zero if a sibling if found.
+    LocalRegister isFirstChildRegister(m_registerAllocator);
+    m_assembler.move(Assembler::TrustedImm32(0), isFirstChildRegister);
+
+    {
+        Assembler::JumpList successCase;
+        LocalRegister previousSibling(m_registerAllocator);
+        m_assembler.move(elementAddressRegister, previousSibling);
+        generateWalkToPreviousAdjacentElement(successCase, previousSibling);
+
+        // If there was a sibling element, the element was not the first child -> failure case.
+        m_assembler.move(Assembler::TrustedImm32(1), isFirstChildRegister);
+
+        successCase.link(&m_assembler);
+    }
+
+    LocalRegister checkingContext(m_registerAllocator);
+    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
+
+    m_registerAllocator.deallocateRegister(parentElement);
+    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+    functionCall.setFunctionAddress(Element::setChildrenAffectedByFirstChildRules);
+    functionCall.setOneArgument(parentElement);
+    functionCall.call();
+
+    // The parent marking is unconditional. If the matching is not a success, we can now fail.
+    // Otherwise we need to apply setFirstChildState() on the RenderStyle.
+    failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isFirstChildRegister));
+
+    if (fragment.relationToRightFragment == FragmentRelation::Rightmost) {
+        LocalRegister childStyle(m_registerAllocator);
+        m_assembler.loadPtr(Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, elementStyle)), childStyle);
+
+        // FIXME: We should look into doing something smart in MacroAssembler instead.
+        LocalRegister flags(m_registerAllocator);
+        Assembler::Address flagAddress(childStyle, RenderStyle::noninheritedFlagsMemoryOffset() + RenderStyle::NonInheritedFlags::flagsMemoryOffset());
+        m_assembler.load64(flagAddress, flags);
+        LocalRegister isFirstChildStateFlagImmediate(m_registerAllocator);
+        m_assembler.move(Assembler::TrustedImm64(RenderStyle::NonInheritedFlags::setFirstChildStateFlags()), isFirstChildStateFlagImmediate);
+        m_assembler.or64(isFirstChildStateFlagImmediate, flags);
+        m_assembler.store64(flags, flagAddress);
+    } else {
+        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+        functionCall.setFunctionAddress(setFirstChildState);
+        Assembler::RegisterID elementAddress = elementAddressRegister;
+        functionCall.setOneArgument(elementAddress);
+        functionCall.call();
+    }
+
+    notResolvingStyle.link(&m_assembler);
+    failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isFirstChildRegister));
+}
+
 inline void SelectorCodeGenerator::generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch)
 {
     if (nameToMatch == anyQName())

Modified: trunk/Source/WebCore/dom/Element.cpp (166536 => 166537)


--- trunk/Source/WebCore/dom/Element.cpp	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/dom/Element.cpp	2014-03-31 22:19:04 UTC (rev 166537)
@@ -2066,6 +2066,11 @@
     ensureElementRareData().setChildrenAffectedByDrag(true);
 }
 
+void Element::setChildrenAffectedByFirstChildRules(Element* element)
+{
+    element->setChildrenAffectedByFirstChildRules();
+}
+
 void Element::setChildrenAffectedByDirectAdjacentRules(Element* element)
 {
     element->setChildrenAffectedByDirectAdjacentRules();

Modified: trunk/Source/WebCore/dom/Element.h (166536 => 166537)


--- trunk/Source/WebCore/dom/Element.h	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/dom/Element.h	2014-03-31 22:19:04 UTC (rev 166537)
@@ -372,6 +372,7 @@
     void setChildrenAffectedByHover() { setFlag(ChildrenAffectedByHoverRulesFlag); }
     void setChildrenAffectedByActive();
     void setChildrenAffectedByDrag();
+    static void setChildrenAffectedByFirstChildRules(Element*);
     void setChildrenAffectedByFirstChildRules() { setFlag(ChildrenAffectedByFirstChildRulesFlag); }
     void setChildrenAffectedByLastChildRules() { setFlag(ChildrenAffectedByLastChildRulesFlag); }
     static void setChildrenAffectedByDirectAdjacentRules(Element*);

Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (166536 => 166537)


--- trunk/Source/WebCore/rendering/style/RenderStyle.h	2014-03-31 22:17:55 UTC (rev 166536)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h	2014-03-31 22:19:04 UTC (rev 166537)
@@ -278,13 +278,12 @@
         static ETableLayout initialTableLayout() { return TAUTO; }
 
         static ptrdiff_t flagsMemoryOffset() { return OBJECT_OFFSETOF(NonInheritedFlags, m_flags); }
-        static uint8_t flagIsUnique() { return isUniqueOffset; }
-        static uint8_t flagEmptyState() { return emptyStateOffset; }
-        static uint8_t flagFirstChildState() { return firstChildStateOffset; }
-        static uint8_t flagLastChildState() { return lastChildStateOffset; }
-        static uint8_t flagAffectedByHover() { return affectedByHoverOffset; }
-        static uint8_t flagAffectedByActive() { return affectedByActiveOffset; }
-        static uint8_t flagAffectedByDrag() { return affectedByDragOffset; }
+        static uint64_t flagEmptyState() { return oneBitMask << emptyStateOffset; }
+        static uint64_t setFirstChildStateFlags() { return flagFirstChildState() | flagIsUnique(); }
+        static uint64_t flagLastChildState() { return oneBitMask << lastChildStateOffset; }
+        static uint64_t flagAffectedByHover() { return oneBitMask << affectedByHoverOffset; }
+        static uint64_t flagAffectedByActive() { return oneBitMask << affectedByActiveOffset; }
+        static uint64_t flagAffectedByDrag() { return oneBitMask << affectedByDragOffset; }
     private:
         void updateBoolean(bool isSet, uint64_t offset)
         {
@@ -311,6 +310,9 @@
             return static_cast<unsigned>((m_flags >> offset) & positionIndependentMask);
         }
 
+        static uint64_t flagIsUnique() { return oneBitMask << isUniqueOffset; }
+        static uint64_t flagFirstChildState() { return oneBitMask << firstChildStateOffset; }
+
         // To type the bit mask properly on 64bits.
         static const uint64_t _oneBitMask_ = 0x1;
 
@@ -1942,6 +1944,8 @@
     static Isolation initialIsolation() { return IsolationAuto; }
 #endif
 
+    static ptrdiff_t noninheritedFlagsMemoryOffset() { return OBJECT_OFFSETOF(RenderStyle, noninherited_flags); }
+
 private:
     bool changeRequiresLayout(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
     bool changeRequiresPositionedLayoutOnly(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
@@ -2025,8 +2029,6 @@
     Color lightingColor() const { return svgStyle().lightingColor(); }
 
     void appendContent(std::unique_ptr<ContentData>);
-
-    static ptrdiff_t noninheritedFlagsMemoryOffset() { return OBJECT_OFFSETOF(RenderStyle, noninherited_flags); }
 };
 
 inline int adjustForAbsoluteZoom(int value, const RenderStyle& style)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to