<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[164268] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/164268">164268</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-02-17 20:10:04 -0800 (Mon, 17 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>SelectorCompiler incorrectly saves a backtracking register for a child chain without descendant relation on the right
https://bugs.webkit.org/show_bug.cgi?id=128944

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2014-02-17
Reviewed by Andreas Kling.

Source/WebCore: 

When resolving the backtracking relations, the value of ancestorPositionSinceDescendantRelation was incorrect for the
rightmost child chain.
What was happenning is updateChainStates() would increment ancestorPositionSinceDescendantRelation even if there was
no descendant relation previously in the chain. As a result, the second SelectorFragment in the fragment chain would
save a backtracking register.

Previously this would just be a wasted register but since <a href="http://trac.webkit.org/projects/webkit/changeset/163850">r163850</a>, the number of registers available for compilation
is defined by SelectorCompiler::minimumRegisterRequirements(). Since we would have one less register available than computed,
we could run out of register and RegisterAllocator would invoke WTFCrash to avoid generating incorrect code.

This patch fixes the issue by not updating ancestorPositionSinceDescendantRelation until the first descendant relation
is seen. There was no need to fix the Adjacent relation because adjacentPositionSinceIndirectAdjacentTreeWalk already
had the correct guard.

Test: fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::updateChainStates):
(WebCore::SelectorCompiler::isFirstAdjacent): The name was a bad copy-paste, fix it.

LayoutTests: 

* fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt: Added.
* fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastselectorsquerySelectorrightmostchildchainattributematchingexpectedtxt">trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsquerySelectorrightmostchildchainattributematchinghtml">trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (164267 => 164268)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-02-18 03:50:41 UTC (rev 164267)
+++ trunk/LayoutTests/ChangeLog        2014-02-18 04:10:04 UTC (rev 164268)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-02-17  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        SelectorCompiler incorrectly saves a backtracking register for a child chain without descendant relation on the right
+        https://bugs.webkit.org/show_bug.cgi?id=128944
+
+        Reviewed by Andreas Kling.
+
+        * fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt: Added.
+        * fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html: Added.
+
</ins><span class="cx"> 2014-02-17  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Constrain replaced element layout to from-intrinsic aspect ratio if specified
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsquerySelectorrightmostchildchainattributematchingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt (0 => 164268)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching-expected.txt        2014-02-18 04:10:04 UTC (rev 164268)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+The CSS JIT was incorrectly saving a backtracking entry point for the rightmost chain of simple selectors with child relation.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS document.querySelectorAll(&quot;[data-webkit][data-rocks]&gt;[data-when]&gt;[data-it-does-not-crash]&quot;).length is 1
+PASS document.querySelectorAll(&quot;[data-webkit][data-rocks]&gt;[data-when]&gt;[data-it-does-not-crash]&quot;)[0].id is &quot;target&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsquerySelectorrightmostchildchainattributematchinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html (0 => 164268)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html        2014-02-18 04:10:04 UTC (rev 164268)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;style&gt;
+[data-webkit][data-rocks]&gt;[data-when]&gt;[data-it-does-not-crash] {
+    background-color:green;
+}
+&lt;/style&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div style=&quot;display:none&quot;&gt;
+  &lt;div data-rocks data-webkit&gt;
+    &lt;ul data-when&gt;
+      &lt;li&gt;&lt;/li&gt;
+      &lt;li data-it-does-not-crash id=target&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+    &lt;!-- Lacks the data-when --&gt;
+    &lt;ul&gt;
+      &lt;li data-it-does-not-crash&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+  &lt;/div&gt;
+  &lt;!-- Lacks the data-webkit --&gt;
+  &lt;div data-rocks&gt;
+    &lt;ul data-when&gt;
+      &lt;li&gt;&lt;/li&gt;
+      &lt;li data-it-does-not-crash&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+  &lt;/div&gt;
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('The CSS JIT was incorrectly saving a backtracking entry point for the rightmost chain of simple selectors with child relation.');
+
+shouldBe('document.querySelectorAll(&quot;[data-webkit][data-rocks]&gt;[data-when]&gt;[data-it-does-not-crash]&quot;).length', '1');
+shouldBeEqualToString('document.querySelectorAll(&quot;[data-webkit][data-rocks]&gt;[data-when]&gt;[data-it-does-not-crash]&quot;)[0].id', 'target');
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (164267 => 164268)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-02-18 03:50:41 UTC (rev 164267)
+++ trunk/Source/WebCore/ChangeLog        2014-02-18 04:10:04 UTC (rev 164268)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2014-02-17  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        SelectorCompiler incorrectly saves a backtracking register for a child chain without descendant relation on the right
+        https://bugs.webkit.org/show_bug.cgi?id=128944
+
+        Reviewed by Andreas Kling.
+
+        When resolving the backtracking relations, the value of ancestorPositionSinceDescendantRelation was incorrect for the
+        rightmost child chain.
+        What was happenning is updateChainStates() would increment ancestorPositionSinceDescendantRelation even if there was
+        no descendant relation previously in the chain. As a result, the second SelectorFragment in the fragment chain would
+        save a backtracking register.
+
+        Previously this would just be a wasted register but since r163850, the number of registers available for compilation
+        is defined by SelectorCompiler::minimumRegisterRequirements(). Since we would have one less register available than computed,
+        we could run out of register and RegisterAllocator would invoke WTFCrash to avoid generating incorrect code.
+
+        This patch fixes the issue by not updating ancestorPositionSinceDescendantRelation until the first descendant relation
+        is seen. There was no need to fix the Adjacent relation because adjacentPositionSinceIndirectAdjacentTreeWalk already
+        had the correct guard.
+
+        Test: fast/selectors/querySelector-rightmost-child-chain-attribute-matching.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::updateChainStates):
+        (WebCore::SelectorCompiler::isFirstAdjacent): The name was a bad copy-paste, fix it.
+
</ins><span class="cx"> 2014-02-17  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Constrain replaced element layout to from-intrinsic aspect ratio if specified
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (164267 => 164268)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-02-18 03:50:41 UTC (rev 164267)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-02-18 04:10:04 UTC (rev 164268)
</span><span class="lines">@@ -446,7 +446,8 @@
</span><span class="cx">         hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain = false;
</span><span class="cx">         break;
</span><span class="cx">     case FragmentRelation::Child:
</span><del>-        ++ancestorPositionSinceDescendantRelation;
</del><ins>+        if (hasDescendantRelationOnTheRight)
+            ++ancestorPositionSinceDescendantRelation;
</ins><span class="cx">         hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain = false;
</span><span class="cx">         break;
</span><span class="cx">     case FragmentRelation::DirectAdjacent:
</span><span class="lines">@@ -464,9 +465,9 @@
</span><span class="cx">     return ancestorPositionSinceDescendantRelation == 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool isFirstAdjacent(unsigned ancestorPositionSinceDescendantRelation)
</del><ins>+static inline bool isFirstAdjacent(unsigned adjacentPositionSinceIndirectAdjacentTreeWalk)
</ins><span class="cx"> {
</span><del>-    return ancestorPositionSinceDescendantRelation == 1;
</del><ins>+    return adjacentPositionSinceIndirectAdjacentTreeWalk == 1;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static inline bool isAfterChildRelation(unsigned ancestorPositionSinceDescendantRelation)
</span></span></pre>
</div>
</div>

</body>
</html>