Title: [203211] trunk/Source/WebCore
Revision
203211
Author
benja...@webkit.org
Date
2016-07-13 20:45:13 -0700 (Wed, 13 Jul 2016)

Log Message

[CSS][ARMv7] :nth-child() do not reserve enough registers if it is in backtracking chain
https://bugs.webkit.org/show_bug.cgi?id=159746
rdar://problem/26156169

Reviewed by Andreas Kling.

The generator generateElementIsNthChild() requires 6 registers in style resolution
to mark previous siblings with generateAddStyleRelationIfResolvingStyle() in the loop.

We were only reserving 5, which is a problem is the sixth is taken by the backtracking
register. x86_64 was already requiring 6 for unrelated reasons and ARM64 has so many registers
that you cannot possibly run out of them in CSS JIT.

I generalized the x86_64 path to all architectures.
I did not limit this case to style resolution because the extra register is irrelevant
in most cases. The only difference is one extra push/pop on ARMv7 if you use querySelector
with :nth-child in a backtracking chain.

This problem is covered by the existing test fast/selectors/nth-child-with-backtracking.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::minimumRegisterRequirements): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (203210 => 203211)


--- trunk/Source/WebCore/ChangeLog	2016-07-14 03:43:07 UTC (rev 203210)
+++ trunk/Source/WebCore/ChangeLog	2016-07-14 03:45:13 UTC (rev 203211)
@@ -1,3 +1,28 @@
+2016-07-13  Benjamin Poulain  <benja...@webkit.org>
+
+        [CSS][ARMv7] :nth-child() do not reserve enough registers if it is in backtracking chain
+        https://bugs.webkit.org/show_bug.cgi?id=159746
+        rdar://problem/26156169
+
+        Reviewed by Andreas Kling.
+
+        The generator generateElementIsNthChild() requires 6 registers in style resolution
+        to mark previous siblings with generateAddStyleRelationIfResolvingStyle() in the loop.
+
+        We were only reserving 5, which is a problem is the sixth is taken by the backtracking
+        register. x86_64 was already requiring 6 for unrelated reasons and ARM64 has so many registers
+        that you cannot possibly run out of them in CSS JIT.
+
+        I generalized the x86_64 path to all architectures.
+        I did not limit this case to style resolution because the extra register is irrelevant
+        in most cases. The only difference is one extra push/pop on ARMv7 if you use querySelector
+        with :nth-child in a backtracking chain.
+
+        This problem is covered by the existing test fast/selectors/nth-child-with-backtracking.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::minimumRegisterRequirements): Deleted.
+
 2016-07-13  Chris Dumez  <cdu...@apple.com>
 
         Drop unnecessary check from ContainerNode::removeChild()

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (203210 => 203211)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-07-14 03:43:07 UTC (rev 203210)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-07-14 03:45:13 UTC (rev 203211)
@@ -1066,10 +1066,10 @@
 static const unsigned minimumRequiredRegisterCount = 5;
 // Element + ElementData + scratchRegister + attributeArrayPointer + expectedLocalName + (qualifiedNameImpl && expectedValue).
 static const unsigned minimumRequiredRegisterCountForAttributeFilter = 6;
-#if CPU(X86_64)
-// Element + SiblingCounter + SiblingCounterCopy + divisor + dividend + remainder.
+// On x86, we always need 6 registers: Element + SiblingCounter + SiblingCounterCopy + divisor + dividend + remainder.
+// On other architectures, we need 6 registers for style resolution:
+//     Element + elementCounter + previousSibling + checkingContext + lastRelation + nextSiblingElement.
 static const unsigned minimumRequiredRegisterCountForNthChildFilter = 6;
-#endif
 
 static unsigned minimumRegisterRequirements(const SelectorFragment& selectorFragment)
 {
@@ -1093,10 +1093,8 @@
         minimum = std::max(minimum, attributeMinimum);
     }
 
-#if CPU(X86_64)
     if (!selectorFragment.nthChildFilters.isEmpty() || !selectorFragment.nthChildOfFilters.isEmpty() || !selectorFragment.nthLastChildFilters.isEmpty() || !selectorFragment.nthLastChildOfFilters.isEmpty())
         minimum = std::max(minimum, minimumRequiredRegisterCountForNthChildFilter);
-#endif
 
     // :any pseudo class filters cause some register pressure.
     for (const auto& subFragments : selectorFragment.anyFilters) {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to