<!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>[168236] 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/168236">168236</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-05-03 20:25:56 -0700 (Sat, 03 May 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>CSS JIT: optimize direct / indirect adjacent's traversal backtracking
https://bugs.webkit.org/show_bug.cgi?id=132319

Patch by Yusuke Suzuki &lt;utatane.tea@gmail.com&gt; on 2014-05-03
Reviewed by Benjamin Poulain.


Source/WebCore: 
Since adjacent backtracking stack reference is pre-allocated
in prologue in http://trac.webkit.org/changeset/166834,
clearing stack phase is not needed. So we can drop
JumpToClearAdjacentTail from backtracking action and simplify
backtracking handling.
And optimize direct / indirect adjacent's traversal backtracking by
using appropriate backtracking height.

When solving adjacent traversal backtracking action,
1) When there's no descendant relation on the right, traversal
failure becomes global failure.
2) When `tagNameMatchedBacktrackingStartHeightFromDescendant` ==
`heightFromDescendant` + 1, the descendant backtracking starts with
the parent of the current element. So we can use the current element
and the backtracking action is JumpToDescendantTreeWalkerEntryPoint.
3) Otherwise, currently we take the conservative approach,
JumpToDescendantTail.

NOTE:
And if `hasDescendantRelationOnTheRight` is true and there's no child
fragment on the right, the backtracking element register is not
effective. So we should ensure that fragment doesn't use the
backtracking element register. Such a fragment fulfills the following
conditions. 1. tagNameMatchedBacktrackingStartHeightFromDescendant is
always 1 (tagNames.size(), that contains only descendant fragment) 2.
heightFromDescendant is always 0 (-- See
computeBacktrackingHeightFromDescendant implementation) Therefore such
a fragment's action always becomes
JumpToDescendantTreeWalkerEntryPoint. So we can ensure that the
backtracking element register is not used.

Test: fast/selectors/backtracking-adjacent.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::solveDescendantBacktrackingActionForChild):
(WebCore::SelectorCompiler::solveAdjacentTraversalBacktrackingAction):
(WebCore::SelectorCompiler::solveBacktrackingAction):
(WebCore::SelectorCompiler::SelectorCodeGenerator::computeBacktrackingInformation):
(WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateAdjacentBacktrackingTail):
(WebCore::SelectorCompiler::isAfterChildRelation): Deleted.

LayoutTests: 
* fast/selectors/backtracking-adjacent-expected.txt: Added.
* fast/selectors/backtracking-adjacent.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="#trunkLayoutTestsfastselectorsbacktrackingadjacentexpectedtxt">trunk/LayoutTests/fast/selectors/backtracking-adjacent-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsbacktrackingadjacenthtml">trunk/LayoutTests/fast/selectors/backtracking-adjacent.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (168235 => 168236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-05-04 03:22:04 UTC (rev 168235)
+++ trunk/LayoutTests/ChangeLog        2014-05-04 03:25:56 UTC (rev 168236)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-05-03  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        CSS JIT: optimize direct / indirect adjacent's traversal backtracking
+        https://bugs.webkit.org/show_bug.cgi?id=132319
+
+        Reviewed by Benjamin Poulain.
+
+        * fast/selectors/backtracking-adjacent-expected.txt: Added.
+        * fast/selectors/backtracking-adjacent.html: Added.
+
</ins><span class="cx"> 2014-05-03  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Invalidate scrollbars when custom scrollbar style changes dynamically.
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsbacktrackingadjacentexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/backtracking-adjacent-expected.txt (0 => 168236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/backtracking-adjacent-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/backtracking-adjacent-expected.txt        2014-05-04 03:25:56 UTC (rev 168236)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+The backtracking from adjacent combinators
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Backtracking without tail, succeeded without backtracking
+PASS getComputedStyle(document.getElementById(&quot;target1&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Backtracking without tail without indirect adjacent, failed and restart.
+PASS getComputedStyle(document.getElementById(&quot;target2&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Backtracking without tail, 2 direct adjacents without indirect adjacent, failed and restart backtracking.
+PASS getComputedStyle(document.getElementById(&quot;target3&quot;)).backgroundColor is &quot;rgb(4, 5, 6)&quot;
+Backtracking without tail, indirect adjacent.
+PASS getComputedStyle(document.getElementById(&quot;target4&quot;)).backgroundColor is &quot;rgb(7, 8, 9)&quot;
+Backtracking from direct adjacent without tail. Matches.
+PASS getComputedStyle(document.getElementById(&quot;target6.1&quot;)).backgroundColor is &quot;rgb(10, 11, 12)&quot;
+Backtracking from direct adjacent tag matching without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target6.2&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from direct adjacent traversal without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target6.3&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking without tail. And fails.
+PASS getComputedStyle(document.getElementById(&quot;target7&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking without tail. And Matches.
+PASS getComputedStyle(document.getElementById(&quot;target8&quot;)).backgroundColor is &quot;rgb(13, 14, 15)&quot;
+Backtracking from direct adjacent with tail. And fails.
+PASS getComputedStyle(document.getElementById(&quot;target9&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from direct adjacent with tail. And Matches.
+PASS getComputedStyle(document.getElementById(&quot;target10&quot;)).backgroundColor is &quot;rgb(16, 17, 18)&quot;
+Backtracking from indirect adjacent with tail. And fails.
+PASS getComputedStyle(document.getElementById(&quot;target11&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from indirect adjacent with tail. And Matches.
+PASS getComputedStyle(document.getElementById(&quot;target12&quot;)).backgroundColor is &quot;rgb(19, 20, 21)&quot;
+Backtracking from indirect adjacent without tail. Matches.
+PASS getComputedStyle(document.getElementById(&quot;target13.1&quot;)).backgroundColor is &quot;rgb(22, 23, 24)&quot;
+Backtracking from indirect adjacent tag matching without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target13.2&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from indirect adjacent traversal without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target13.3&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from indirect adjacent without tail. Matches.
+PASS getComputedStyle(document.getElementById(&quot;target14.1&quot;)).backgroundColor is &quot;rgb(25, 26, 27)&quot;
+Backtracking from indirect adjacent tag matching without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target14.2&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from indirect adjacent traversal without tail. Fails.
+PASS getComputedStyle(document.getElementById(&quot;target14.3&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from direct adjacent with tail. And fails.
+PASS getComputedStyle(document.getElementById(&quot;target15&quot;)).backgroundColor is &quot;rgb(0, 0, 0)&quot;
+Backtracking from direct adjacent with tail. And Matches.
+PASS getComputedStyle(document.getElementById(&quot;target16&quot;)).backgroundColor is &quot;rgb(28, 29, 30)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsbacktrackingadjacenthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/backtracking-adjacent.html (0 => 168236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/backtracking-adjacent.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/backtracking-adjacent.html        2014-05-04 03:25:56 UTC (rev 168236)
</span><span class="lines">@@ -0,0 +1,390 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+span.target {
+    background-color:rgb(0,0,0);
+}
+a + b span.target {
+    background-color:rgb(1,2,3);
+}
+c + c + d span.target {
+    background-color:rgb(4,5,6);
+}
+e + f ~ g span.target {
+    background-color:rgb(7,8,9);
+}
+h + span.target {
+    background-color:rgb(10,11,12);
+}
+j+j+j~j&gt;k span.target {
+    background-color:rgb(13,14,15);
+}
+m l+l+l+l~m&gt;m&gt;m span.target {
+    background-color:rgb(16,17,18);
+}
+n o~n&gt;n&gt;n span.target {
+    background-color:rgb(19,20,21);
+}
+p ~ span.target {
+    background-color:rgb(22,23,24);
+}
+q ~ r span.target {
+    background-color:rgb(25,26,27);
+}
+s t+t+t+s&gt;s&gt;s span.target {
+    background-color:rgb(28,29,30);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div style=&quot;display:none&quot;&gt;
+    &lt;!-- a + b span.target --&gt;
+    &lt;target1&gt;
+        &lt;a&gt;&lt;/a&gt;
+        &lt;b&gt;
+            &lt;span class=&quot;target&quot; id=&quot;target1&quot;&gt;&lt;/span&gt;
+        &lt;/b&gt;
+    &lt;/target1&gt;
+
+    &lt;!-- a + b span.target --&gt;
+    &lt;target2&gt;
+        &lt;a&gt;&lt;/a&gt;
+        &lt;b&gt;
+            &lt;b&gt;&lt;/b&gt;  &lt;!-- Fail here and restart backtracking. --&gt;
+            &lt;b&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target2&quot;&gt;&lt;/span&gt;
+            &lt;/b&gt;
+        &lt;/b&gt;
+    &lt;/target2&gt;
+
+    &lt;!-- c + c + d span.target --&gt;
+    &lt;target3&gt;
+        &lt;c&gt;&lt;/c&gt;
+        &lt;c&gt;&lt;/c&gt;
+        &lt;d&gt;
+            &lt;c&gt;&lt;/c&gt;
+            &lt;b&gt;&lt;/b&gt;  &lt;!-- Fail here and restart backtracking with the parent of the current element. --&gt;
+            &lt;d&gt;
+                &lt;b&gt;&lt;/b&gt;  &lt;!-- Fail here and restart backtracking with the parent of the current element. --&gt;
+                &lt;c&gt;&lt;/c&gt;
+                &lt;d&gt;
+                    &lt;span class=&quot;target&quot; id=&quot;target3&quot;&gt;&lt;/span&gt;
+                &lt;/d&gt;
+            &lt;/d&gt;
+        &lt;/d&gt;
+    &lt;/target3&gt;
+
+    &lt;!-- e + f ~ g span.target --&gt;
+    &lt;target4&gt;
+        &lt;d&gt;&lt;/d&gt;
+        &lt;e&gt;&lt;/e&gt;
+        &lt;f&gt;&lt;/f&gt;
+        &lt;d&gt;&lt;/d&gt;
+        &lt;d&gt;&lt;/d&gt;
+        &lt;g&gt;
+            &lt;d&gt;&lt;/d&gt;  &lt;!-- Fail here and restart backtracking indirect adjacent matching. --&gt;
+            &lt;f&gt;&lt;/f&gt;
+            &lt;g&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target4&quot;&gt;&lt;/span&gt;
+            &lt;/g&gt;
+        &lt;/g&gt;
+    &lt;/target4&gt;
+
+    &lt;!-- h + span.target --&gt;
+    &lt;target6&gt;
+        &lt;h&gt;&lt;/h&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target6.1&quot;&gt;&lt;/span&gt;
+    &lt;/target6&gt;
+
+    &lt;!-- h + span.target --&gt;
+    &lt;target6&gt;
+        &lt;a&gt;&lt;/a&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target6.2&quot;&gt;&lt;/span&gt;
+    &lt;/target6&gt;
+
+    &lt;!-- h + span.target --&gt;
+    &lt;target6&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target6.3&quot;&gt;&lt;/span&gt;
+    &lt;/target6&gt;
+
+    &lt;!-- j+j+j~j&gt;k span.target --&gt;
+    &lt;target7&gt;
+        &lt;d&gt;&lt;/d&gt;  &lt;!-- Fail here. --&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;k&gt;
+            &lt;span class=&quot;target&quot; id=&quot;target7&quot;&gt;&lt;/span&gt;
+        &lt;/k&gt;
+    &lt;/target7&gt;
+
+    &lt;!-- j+j+j~j&gt;k span.target --&gt;
+    &lt;target8&gt;
+        &lt;j&gt;&lt;/j&gt;  &lt;!-- Match here. --&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;d&gt;&lt;/d&gt;  &lt;!-- Fail here. --&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;&lt;/j&gt;
+        &lt;j&gt;
+            &lt;k&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target8&quot;&gt;&lt;/span&gt;
+            &lt;/k&gt;
+        &lt;/j&gt;
+    &lt;/target8&gt;
+
+    &lt;!-- m l+l+l+l~m&gt;m&gt;m span.target --&gt;
+    &lt;target9&gt;
+        &lt;m&gt;
+            &lt;l&gt;&lt;/l&gt;  &lt;!-- Fail here --&gt;
+            &lt;l&gt;&lt;/l&gt;
+            &lt;l&gt;&lt;/l&gt;
+            &lt;m&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;m&gt;
+                    &lt;m&gt;
+                        &lt;m&gt;
+                            &lt;span class=&quot;target&quot; id=&quot;target9&quot;&gt;&lt;/span&gt;
+                        &lt;/m&gt;
+                    &lt;/m&gt;
+                &lt;/m&gt;
+            &lt;/m&gt;
+        &lt;/m&gt;
+    &lt;/target9&gt;
+
+    &lt;!-- m l+l+l+l~m&gt;m&gt;m span.target --&gt;
+    &lt;target10&gt;
+        &lt;m&gt;
+            &lt;l&gt;&lt;/l&gt;  &lt;!-- Match here --&gt;
+            &lt;l&gt;&lt;/l&gt;
+            &lt;l&gt;&lt;/l&gt;
+            &lt;l&gt;&lt;/l&gt;
+            &lt;m&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+                &lt;l&gt;&lt;/l&gt;
+                &lt;m&gt;
+                    &lt;m&gt;
+                        &lt;m&gt;
+                            &lt;span class=&quot;target&quot; id=&quot;target10&quot;&gt;&lt;/span&gt;
+                        &lt;/m&gt;
+                    &lt;/m&gt;
+                &lt;/m&gt;
+            &lt;/m&gt;
+        &lt;/m&gt;
+    &lt;/target10&gt;
+
+    &lt;!-- n o~n&gt;n&gt;n span.target --&gt;
+    &lt;target11&gt;
+        &lt;n&gt;
+            &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+            &lt;n&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+                &lt;n&gt;
+                    &lt;n&gt;
+                        &lt;n&gt;
+                            &lt;span class=&quot;target&quot; id=&quot;target11&quot;&gt;&lt;/span&gt;
+                        &lt;/n&gt;
+                    &lt;/n&gt;
+                &lt;/n&gt;
+            &lt;/n&gt;
+        &lt;/n&gt;
+    &lt;/target11&gt;
+
+    &lt;!-- n o~n&gt;n&gt;n span.target --&gt;
+    &lt;target12&gt;
+        &lt;n&gt;
+            &lt;o&gt;&lt;/o&gt;  &lt;!-- Match here --&gt;
+            &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+            &lt;n&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+                &lt;n&gt;
+                    &lt;n&gt;
+                        &lt;n&gt;
+                            &lt;span class=&quot;target&quot; id=&quot;target12&quot;&gt;&lt;/span&gt;
+                        &lt;/n&gt;
+                    &lt;/n&gt;
+                &lt;/n&gt;
+            &lt;/n&gt;
+        &lt;/n&gt;
+    &lt;/target12&gt;
+
+    &lt;!-- p ~ span.target --&gt;
+    &lt;target13&gt;
+        &lt;p&gt;&lt;/p&gt;  &lt;!-- Match here --&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target13.1&quot;&gt;&lt;/span&gt;
+    &lt;/target13&gt;
+
+    &lt;!-- p ~ span.target --&gt;
+    &lt;target13&gt;
+        &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target13.2&quot;&gt;&lt;/span&gt;
+    &lt;/target13&gt;
+
+    &lt;!-- p ~ span.target --&gt;
+    &lt;target13&gt;
+        &lt;!-- Fail here --&gt;
+        &lt;span class=&quot;target&quot; id=&quot;target13.3&quot;&gt;&lt;/span&gt;
+    &lt;/target13&gt;
+
+    &lt;!-- q ~ r span.target --&gt;
+    &lt;target14&gt;
+        &lt;q&gt;&lt;/q&gt;  &lt;!-- Match here --&gt;
+        &lt;a&gt;&lt;/a&gt;
+        &lt;r&gt;
+            &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+            &lt;r&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target14.1&quot;&gt;&lt;/span&gt;
+            &lt;/r&gt;
+        &lt;/r&gt;
+    &lt;/target14&gt;
+
+    &lt;!-- q ~ r span.target --&gt;
+    &lt;target14&gt;
+        &lt;!-- Fail here --&gt;
+        &lt;r&gt;
+            &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here --&gt;
+            &lt;r&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target14.2&quot;&gt;&lt;/span&gt;
+            &lt;/r&gt;
+        &lt;/r&gt;
+    &lt;/target14&gt;
+
+    &lt;!-- q ~ r span.target --&gt;
+    &lt;target14&gt;
+        &lt;!-- Fail here --&gt;
+        &lt;r&gt;
+            &lt;!-- Fail here --&gt;
+            &lt;r&gt;
+                &lt;span class=&quot;target&quot; id=&quot;target14.3&quot;&gt;&lt;/span&gt;
+            &lt;/r&gt;
+        &lt;/r&gt;
+    &lt;/target14&gt;
+
+    &lt;!-- s t+t+t+s&gt;s&gt;s span.target --&gt;
+    &lt;target15&gt;
+        &lt;s&gt;
+            &lt;!-- Fail here and backtrack with the tail --&gt;
+            &lt;t&gt;&lt;/t&gt;
+            &lt;t&gt;&lt;/t&gt;
+            &lt;s&gt;
+                &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;t&gt;&lt;/t&gt;
+                &lt;t&gt;&lt;/t&gt;
+                &lt;s&gt;
+                    &lt;s&gt;
+                        &lt;s&gt;
+                            &lt;span class=&quot;target&quot; id=&quot;target15&quot;&gt;&lt;/span&gt;
+                        &lt;/s&gt;
+                    &lt;/s&gt;
+                &lt;/s&gt;
+            &lt;/s&gt;
+        &lt;/s&gt;
+    &lt;/target15&gt;
+
+    &lt;!-- s t+t+t+s&gt;s&gt;s span.target --&gt;
+    &lt;target16&gt;
+        &lt;s&gt;
+            &lt;t&gt;&lt;/t&gt;  &lt;!-- Match here --&gt;
+            &lt;t&gt;&lt;/t&gt;
+            &lt;t&gt;&lt;/t&gt;
+            &lt;s&gt;
+                &lt;!-- Fail here and backtrack with the tail --&gt;
+                &lt;t&gt;&lt;/t&gt;
+                &lt;t&gt;&lt;/t&gt;
+                &lt;s&gt;
+                    &lt;a&gt;&lt;/a&gt;  &lt;!-- Fail here and backtrack with the tail --&gt;
+                    &lt;t&gt;&lt;/t&gt;
+                    &lt;t&gt;&lt;/t&gt;
+                    &lt;s&gt;
+                        &lt;s&gt;
+                            &lt;s&gt;
+                                &lt;span class=&quot;target&quot; id=&quot;target16&quot;&gt;&lt;/span&gt;
+                            &lt;/s&gt;
+                        &lt;/s&gt;
+                    &lt;/s&gt;
+                &lt;/s&gt;
+            &lt;/s&gt;
+        &lt;/s&gt;
+    &lt;/target16&gt;
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('The backtracking from adjacent combinators');
+
+debug(&quot;Backtracking without tail, succeeded without backtracking&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target1&quot;)).backgroundColor', 'rgb(1, 2, 3)');
+
+debug(&quot;Backtracking without tail without indirect adjacent, failed and restart.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target2&quot;)).backgroundColor', 'rgb(1, 2, 3)');
+
+debug(&quot;Backtracking without tail, 2 direct adjacents without indirect adjacent, failed and restart backtracking.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target3&quot;)).backgroundColor', 'rgb(4, 5, 6)');
+
+debug(&quot;Backtracking without tail, indirect adjacent.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target4&quot;)).backgroundColor', 'rgb(7, 8, 9)');
+
+debug(&quot;Backtracking from direct adjacent without tail. Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target6.1&quot;)).backgroundColor', 'rgb(10, 11, 12)');
+
+debug(&quot;Backtracking from direct adjacent tag matching without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target6.2&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from direct adjacent traversal without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target6.3&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking without tail. And fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target7&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking without tail. And Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target8&quot;)).backgroundColor', 'rgb(13, 14, 15)');
+
+debug(&quot;Backtracking from direct adjacent with tail. And fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target9&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from direct adjacent with tail. And Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target10&quot;)).backgroundColor', 'rgb(16, 17, 18)');
+
+debug(&quot;Backtracking from indirect adjacent with tail. And fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target11&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from indirect adjacent with tail. And Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target12&quot;)).backgroundColor', 'rgb(19, 20, 21)');
+
+debug(&quot;Backtracking from indirect adjacent without tail. Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target13.1&quot;)).backgroundColor', 'rgb(22, 23, 24)');
+
+debug(&quot;Backtracking from indirect adjacent tag matching without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target13.2&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from indirect adjacent traversal without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target13.3&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from indirect adjacent without tail. Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target14.1&quot;)).backgroundColor', 'rgb(25, 26, 27)');
+
+debug(&quot;Backtracking from indirect adjacent tag matching without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target14.2&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from indirect adjacent traversal without tail. Fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target14.3&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from direct adjacent with tail. And fails.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target15&quot;)).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(&quot;Backtracking from direct adjacent with tail. And Matches.&quot;);
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;target16&quot;)).backgroundColor', 'rgb(28, 29, 30)');
+&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 (168235 => 168236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-05-04 03:22:04 UTC (rev 168235)
+++ trunk/Source/WebCore/ChangeLog        2014-05-04 03:25:56 UTC (rev 168236)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2014-05-03  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        CSS JIT: optimize direct / indirect adjacent's traversal backtracking
+        https://bugs.webkit.org/show_bug.cgi?id=132319
+
+        Reviewed by Benjamin Poulain.
+
+        Since adjacent backtracking stack reference is pre-allocated
+        in prologue in http://trac.webkit.org/changeset/166834,
+        clearing stack phase is not needed. So we can drop
+        JumpToClearAdjacentTail from backtracking action and simplify
+        backtracking handling.
+        And optimize direct / indirect adjacent's traversal backtracking by
+        using appropriate backtracking height.
+
+        When solving adjacent traversal backtracking action,
+        1) When there's no descendant relation on the right, traversal
+        failure becomes global failure.
+        2) When `tagNameMatchedBacktrackingStartHeightFromDescendant` ==
+        `heightFromDescendant` + 1, the descendant backtracking starts with
+        the parent of the current element. So we can use the current element
+        and the backtracking action is JumpToDescendantTreeWalkerEntryPoint.
+        3) Otherwise, currently we take the conservative approach,
+        JumpToDescendantTail.
+
+        NOTE:
+        And if `hasDescendantRelationOnTheRight` is true and there's no child
+        fragment on the right, the backtracking element register is not
+        effective. So we should ensure that fragment doesn't use the
+        backtracking element register. Such a fragment fulfills the following
+        conditions. 1. tagNameMatchedBacktrackingStartHeightFromDescendant is
+        always 1 (tagNames.size(), that contains only descendant fragment) 2.
+        heightFromDescendant is always 0 (-- See
+        computeBacktrackingHeightFromDescendant implementation) Therefore such
+        a fragment's action always becomes
+        JumpToDescendantTreeWalkerEntryPoint. So we can ensure that the
+        backtracking element register is not used.
+
+        Test: fast/selectors/backtracking-adjacent.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::solveDescendantBacktrackingActionForChild):
+        (WebCore::SelectorCompiler::solveAdjacentTraversalBacktrackingAction):
+        (WebCore::SelectorCompiler::solveBacktrackingAction):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::computeBacktrackingInformation):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAdjacentBacktrackingTail):
+        (WebCore::SelectorCompiler::isAfterChildRelation): Deleted.
+
</ins><span class="cx"> 2014-05-03  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clear the JSString cache when under memory pressure.
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (168235 => 168236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-05-04 03:22:04 UTC (rev 168235)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-05-04 03:25:56 UTC (rev 168236)
</span><span class="lines">@@ -65,8 +65,7 @@
</span><span class="cx">     JumpToIndirectAdjacentEntryPoint,
</span><span class="cx">     JumpToDescendantTreeWalkerEntryPoint,
</span><span class="cx">     JumpToDescendantTail,
</span><del>-    JumpToDirectAdjacentTail,
-    JumpToClearAdjacentTail
</del><ins>+    JumpToDirectAdjacentTail
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct BacktrackingFlag {
</span><span class="lines">@@ -241,7 +240,6 @@
</span><span class="cx">     Assembler::JumpList m_descendantBacktrackingFailureCases;
</span><span class="cx">     StackAllocator::StackReference m_adjacentBacktrackingStart;
</span><span class="cx">     Assembler::JumpList m_adjacentBacktrackingFailureCases;
</span><del>-    Assembler::JumpList m_clearAdjacentBacktrackingFailureCases;
</del><span class="cx"> 
</span><span class="cx"> #if CSS_SELECTOR_JIT_DEBUGGING
</span><span class="cx">     const CSSSelector* m_originalSelector;
</span><span class="lines">@@ -592,13 +590,8 @@
</span><span class="cx">     return adjacentPositionSinceIndirectAdjacentTreeWalk == 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool isAfterChildRelation(unsigned ancestorPositionSinceDescendantRelation)
</del><ins>+static inline BacktrackingAction solveDescendantBacktrackingActionForChild(const SelectorFragment&amp; fragment, unsigned backtrackingStartHeightFromDescendant)
</ins><span class="cx"> {
</span><del>-    return ancestorPositionSinceDescendantRelation &gt; 0;
-}
-
-static BacktrackingAction solveDescendantBacktrackingActionForChild(const SelectorFragment&amp; fragment, unsigned backtrackingStartHeightFromDescendant)
-{
</del><span class="cx">     // If height is invalid (e.g. There's no tag name).
</span><span class="cx">     if (backtrackingStartHeightFromDescendant == invalidHeight)
</span><span class="cx">         return BacktrackingAction::NoBacktracking;
</span><span class="lines">@@ -614,8 +607,19 @@
</span><span class="cx">     return BacktrackingAction::JumpToDescendantTail;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void solveBacktrackingAction(SelectorFragment&amp; fragment, bool hasDescendantRelationOnTheRight, unsigned ancestorPositionSinceDescendantRelation, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, unsigned adjacentPositionSinceIndirectAdjacentTreeWalk)
</del><ins>+static inline BacktrackingAction solveAdjacentTraversalBacktrackingAction(const SelectorFragment&amp; fragment, bool hasDescendantRelationOnTheRight)
</ins><span class="cx"> {
</span><ins>+    if (!hasDescendantRelationOnTheRight)
+        return BacktrackingAction::NoBacktracking;
+
+    if (fragment.tagNameMatchedBacktrackingStartHeightFromDescendant == (fragment.heightFromDescendant + 1))
+        return BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
+
+    return BacktrackingAction::JumpToDescendantTail;
+}
+
+static inline void solveBacktrackingAction(SelectorFragment&amp; fragment, bool hasDescendantRelationOnTheRight, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, unsigned adjacentPositionSinceIndirectAdjacentTreeWalk)
+{
</ins><span class="cx">     switch (fragment.relationToRightFragment) {
</span><span class="cx">     case FragmentRelation::Rightmost:
</span><span class="cx">     case FragmentRelation::Descendant:
</span><span class="lines">@@ -630,20 +634,7 @@
</span><span class="cx">     case FragmentRelation::DirectAdjacent:
</span><span class="cx">         // Failure on traversal implies no other sibling traversal can match. Matching should resume at the
</span><span class="cx">         // nearest ancestor/descendant traversal.
</span><del>-        if (hasDescendantRelationOnTheRight) {
-            if (!isAfterChildRelation(ancestorPositionSinceDescendantRelation))
-                fragment.traversalBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
-            else {
-                if (!hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain || isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk))
-                    fragment.traversalBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
-                else
-                    fragment.traversalBacktrackingAction = BacktrackingAction::JumpToClearAdjacentTail;
-            }
-        } else {
-            // If we are in a direct adjacent chain with backtracking, we need to clear the backtracking register on the stack.
-            if (hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain &amp;&amp; !isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk))
-                fragment.traversalBacktrackingAction = BacktrackingAction::JumpToClearAdjacentTail;
-        }
</del><ins>+        fragment.traversalBacktrackingAction = solveAdjacentTraversalBacktrackingAction(fragment, hasDescendantRelationOnTheRight);
</ins><span class="cx"> 
</span><span class="cx">         // If the rightmost relation is a indirect adjacent, matching sould resume from there.
</span><span class="cx">         // Otherwise, we resume from the latest ancestor/descendant if any.
</span><span class="lines">@@ -656,24 +647,15 @@
</span><span class="cx">                 fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail;
</span><span class="cx">             }
</span><span class="cx">         } else if (hasDescendantRelationOnTheRight) {
</span><del>-            if (isAfterChildRelation(ancestorPositionSinceDescendantRelation)) {
-                fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
-                fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
-            } else {
-                fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
-                fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
-            }
</del><ins>+            // Since we resume from the latest ancestor/descendant, the action is the same as the traversal action.
+            fragment.matchingTagNameBacktrackingAction = fragment.traversalBacktrackingAction;
+            fragment.matchingPostTagNameBacktrackingAction = fragment.traversalBacktrackingAction;
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     case FragmentRelation::IndirectAdjacent:
</span><span class="cx">         // Failure on traversal implies no other sibling matching will succeed. Matching can resume
</span><span class="cx">         // from the latest ancestor/descendant.
</span><del>-        if (hasDescendantRelationOnTheRight) {
-            if (isAfterChildRelation(ancestorPositionSinceDescendantRelation))
-                fragment.traversalBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
-            else
-                fragment.traversalBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
-        }
</del><ins>+        fragment.traversalBacktrackingAction = solveAdjacentTraversalBacktrackingAction(fragment, hasDescendantRelationOnTheRight);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -830,7 +812,7 @@
</span><span class="cx">         dataLogF(&quot;Computing fragment[%d] backtracking height %u. NotMatched %u / Matched %u\n&quot;, i, fragment.heightFromDescendant, fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant, fragment.tagNameMatchedBacktrackingStartHeightFromDescendant);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-        solveBacktrackingAction(fragment, hasDescendantRelationOnTheRight, ancestorPositionSinceDescendantRelation, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk);
</del><ins>+        solveBacktrackingAction(fragment, hasDescendantRelationOnTheRight, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk);
</ins><span class="cx"> 
</span><span class="cx">         needsAdjacentTail |= requiresAdjacentTail(fragment);
</span><span class="cx">         needsDescendantTail |= requiresDescendantTail(fragment);
</span><span class="lines">@@ -1303,9 +1285,6 @@
</span><span class="cx">     case BacktrackingAction::JumpToDirectAdjacentTail:
</span><span class="cx">         m_adjacentBacktrackingFailureCases.append(localFailureCases);
</span><span class="cx">         break;
</span><del>-    case BacktrackingAction::JumpToClearAdjacentTail:
-        m_clearAdjacentBacktrackingFailureCases.append(localFailureCases);
-        break;
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1317,9 +1296,6 @@
</span><span class="cx">     unsigned offsetToAdjacentBacktrackingStart = m_stackAllocator.offsetToStackReference(m_adjacentBacktrackingStart);
</span><span class="cx">     m_assembler.loadPtr(Assembler::Address(Assembler::stackPointerRegister, offsetToAdjacentBacktrackingStart), elementAddressRegister);
</span><span class="cx">     m_assembler.jump(m_indirectAdjacentEntryPoint);
</span><del>-
-    // Total failure tail.
-    m_clearAdjacentBacktrackingFailureCases.link(&amp;m_assembler);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateDescendantBacktrackingTail()
</span></span></pre>
</div>
</div>

</body>
</html>