<!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>[206804] 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/206804">206804</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-10-04 23:16:15 -0700 (Tue, 04 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>String.prototype.toLowerCase should be a DFG/FTL intrinsic
https://bugs.webkit.org/show_bug.cgi?id=162887

Reviewed by Filip Pizlo and Yusuke Suzuki.

JSTests:

* microbenchmarks/to-lower-case.js: Added.
(assert):
(foo):
(bar):
* stress/to-lower-case.js: Added.
(assert):
(foo):

Source/JavaScriptCore:

This patch makes ToLowerCase an intrinsic in the DFG/FTL. On the fast
path, the intrinsic will loop over an 8-bit string ensuring it's already
lower case, and simply return the string. In the slow path, it'll call
into C code to make a new string.

This is a 7-8% speedup on ES6SampleBench/Basic.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToLowerCase):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileToLowerCase):
* jit/JITOperations.h:
* runtime/Intrinsic.h:
* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):

Source/WTF:

This patch exposes a new StringImpl function called convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit
which extracts slow path for the 8-bit part of convertToLowercaseWithoutLocale
into a helper function. I decided to extract this into its own function because
it may be the case that JSCs JITs will want to continue the operation
after it has already ensured that part of an 8-bit string is lower case.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::convertToLowercaseWithoutLocale):
(WTF::StringImpl::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit):
* wtf/text/StringImpl.h:
* wtf/text/WTFString.cpp:
(WTF::String::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit):
* wtf/text/WTFString.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntrinsich">trunk/Source/JavaScriptCore/runtime/Intrinsic.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplcpp">trunk/Source/WTF/wtf/text/StringImpl.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplh">trunk/Source/WTF/wtf/text/StringImpl.h</a></li>
<li><a href="#trunkSourceWTFwtftextWTFStringcpp">trunk/Source/WTF/wtf/text/WTFString.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextWTFStringh">trunk/Source/WTF/wtf/text/WTFString.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkstolowercasejs">trunk/JSTests/microbenchmarks/to-lower-case.js</a></li>
<li><a href="#trunkJSTestsstresstolowercasejs">trunk/JSTests/stress/to-lower-case.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/JSTests/ChangeLog        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-10-04  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        String.prototype.toLowerCase should be a DFG/FTL intrinsic
+        https://bugs.webkit.org/show_bug.cgi?id=162887
+
+        Reviewed by Filip Pizlo and Yusuke Suzuki.
+
+        * microbenchmarks/to-lower-case.js: Added.
+        (assert):
+        (foo):
+        (bar):
+        * stress/to-lower-case.js: Added.
+        (assert):
+        (foo):
+
</ins><span class="cx"> 2016-10-04  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: handle a few corner cases
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkstolowercasejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/to-lower-case.js (0 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/to-lower-case.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/to-lower-case.js        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;);
+}
+noInline(assert);
+
+let tests = [
+    [&quot;foo&quot;, &quot;foo&quot;],
+    [&quot;foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&quot;, &quot;foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&quot;],
+];
+
+function foo(a) {
+    return a.toLowerCase();
+}
+noInline(foo);
+
+function bar(a) {
+    a.toLowerCase();
+    assert(true); // side effects
+    a.toLowerCase();
+}
+noInline(bar);
+
+let start = Date.now();
+for (let i = 0; i &lt; 500000; i++) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        let test = tests[i][0];
+        let result = tests[i][1];
+        assert(foo(test) === result);
+        bar(test);
+    }
+}
+
+const verbose = false;
+if (verbose)
+    print(Date.now() - start);
</ins></span></pre></div>
<a id="trunkJSTestsstresstolowercasejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/to-lower-case.js (0 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/to-lower-case.js                                (rev 0)
+++ trunk/JSTests/stress/to-lower-case.js        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;);
+}
+
+let tests = [
+    [&quot;FOO&quot;, &quot;foo&quot;],
+    [&quot;fff\u00C2&quot;, &quot;fff\u00E2&quot;],
+    [&quot;foo&quot;, &quot;foo&quot;],
+    [&quot;foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&quot;, &quot;foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&quot;],
+    [&quot;BaR&quot;, &quot;bar&quot;],
+    [&quot;FOO\u00A9&quot;, &quot;foo\u00A9&quot;],
+    [&quot;#$#$&quot;, &quot;#$#$&quot;],
+    [&quot;&amp;&amp;&amp;\u00A9&quot;, &quot;&amp;&amp;&amp;\u00A9&quot;],
+    [&quot;&amp;&amp;&amp;\u00C2&quot;, &quot;&amp;&amp;&amp;\u00E2&quot;],
+    [&quot;ABC\u0100&quot;, &quot;abc\u0101&quot;],
+];
+
+function foo(a) {
+    return a.toLowerCase();
+}
+noInline(foo);
+
+for (let i = 0; i &lt; 10000; i++) {
+    for (let i = 0; i &lt; tests.length; i++) {
+        let test = tests[i][0];
+        let result = tests[i][1];
+        assert(foo(test) === result);
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2016-10-04  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        String.prototype.toLowerCase should be a DFG/FTL intrinsic
+        https://bugs.webkit.org/show_bug.cgi?id=162887
+
+        Reviewed by Filip Pizlo and Yusuke Suzuki.
+
+        This patch makes ToLowerCase an intrinsic in the DFG/FTL. On the fast
+        path, the intrinsic will loop over an 8-bit string ensuring it's already
+        lower case, and simply return the string. In the slow path, it'll call
+        into C code to make a new string.
+
+        This is a 7-8% speedup on ES6SampleBench/Basic.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToLowerCase):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileToLowerCase):
+        * jit/JITOperations.h:
+        * runtime/Intrinsic.h:
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
+
</ins><span class="cx"> 2016-10-04  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: don't synchronously send a listing message if we might need to query _WKAutomationDelegate
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1005,6 +1005,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case ToLowerCase: {
+        forNode(node).setType(m_graph, SpecString);
+        break;
+    }
+
</ins><span class="cx">     case LoadFromJSMapBucket:
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -2580,6 +2580,20 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case ToLowerCaseIntrinsic: {
+        if (argumentCountIncludingThis != 1)
+            return false;
+
+        if (m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadType))
+            return false;
+
+        insertChecks();
+        Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
+        Node* result = addToGraph(ToLowerCase, thisString);
+        set(VirtualRegister(resultOperand), result);
+        return true;
+    }
+
</ins><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1291,6 +1291,10 @@
</span><span class="cx">         read(MiscFields);
</span><span class="cx">         def(HeapLocation(MapHasLoc, MiscFields, node-&gt;child1()), LazyNode(node));
</span><span class="cx">         return;
</span><ins>+
+    case ToLowerCase:
+        def(PureValue(node));
+        return;
</ins><span class="cx">         
</span><span class="cx">     case LastNodeType:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -292,6 +292,7 @@
</span><span class="cx">     case StringReplace:
</span><span class="cx">     case StringReplaceRegExp:
</span><span class="cx">     case CreateRest:
</span><ins>+    case ToLowerCase:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1673,6 +1673,15 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case ToLowerCase: {
+            // We currently only support StringUse since that will ensure that
+            // ToLowerCase is a pure operation. If we decide to update this with
+            // more types in the future, we need to ensure that the clobberize rules
+            // are correct.
+            fixEdge&lt;StringUse&gt;(node-&gt;child1());
+            break;
+        }
+
</ins><span class="cx">         case DefineAccessorProperty: {
</span><span class="cx">             fixEdge&lt;CellUse&gt;(m_graph.varArgChild(node, 0));
</span><span class="cx">             Edge&amp; propertyEdge = m_graph.varArgChild(node, 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -396,6 +396,8 @@
</span><span class="cx">     macro(GetMapBucket, NodeResultJS) \
</span><span class="cx">     macro(LoadFromJSMapBucket, NodeResultJS) \
</span><span class="cx">     macro(IsNonEmptyMapBucket, NodeResultBoolean) \
</span><ins>+    \
+    macro(ToLowerCase, NodeResultJS) \
</ins><span class="cx"> 
</span><span class="cx"> // This enum generates a monotonically increasing id for all Node types,
</span><span class="cx"> // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1514,6 +1514,22 @@
</span><span class="cx">     return string-&gt;value(exec).impl();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    const String&amp; inputString = string-&gt;value(exec);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
+    if (lowercasedString.impl() == inputString.impl())
+        return string;
+    scope.release();
+    return jsString(exec, lowercasedString);
+}
+
</ins><span class="cx"> JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -155,6 +155,8 @@
</span><span class="cx"> StringImpl* JIT_OPERATION operationResolveRope(ExecState*, JSString*);
</span><span class="cx"> JSString* JIT_OPERATION operationSingleCharacterString(ExecState*, int32_t);
</span><span class="cx"> 
</span><ins>+JSString* JIT_OPERATION operationToLowerCase(ExecState*, JSString*, uint32_t);
+
</ins><span class="cx"> int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input);
</span><span class="cx"> JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
</span><span class="cx"> JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -754,6 +754,11 @@
</span><span class="cx">             setPrediction(SpecInt32Only);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+
+        case ToLowerCase:
+            setPrediction(SpecString);
+            break;
+
</ins><span class="cx">         case ArithPow:
</span><span class="cx">         case ArithSqrt:
</span><span class="cx">         case ArithFRound:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -361,6 +361,7 @@
</span><span class="cx">     case PutDynamicVar:
</span><span class="cx">     case ResolveScope:
</span><span class="cx">     case MapHash:
</span><ins>+    case ToLowerCase:
</ins><span class="cx">     case GetMapBucket:
</span><span class="cx">     case LoadFromJSMapBucket:
</span><span class="cx">     case IsNonEmptyMapBucket:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1490,6 +1490,60 @@
</span><span class="cx">     jump(notTaken);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileToLowerCase(Node* node)
+{
+    ASSERT(node-&gt;op() == ToLowerCase);
+    SpeculateCellOperand string(this, node-&gt;child1());
+    GPRTemporary temp(this);
+    GPRTemporary index(this);
+    GPRTemporary charReg(this);
+    GPRTemporary length(this);
+
+    GPRReg stringGPR = string.gpr();
+    GPRReg tempGPR = temp.gpr();
+    GPRReg indexGPR = index.gpr();
+    GPRReg charGPR = charReg.gpr();
+    GPRReg lengthGPR = length.gpr();
+
+    speculateString(node-&gt;child1(), stringGPR);
+
+    CCallHelpers::JumpList slowPath;
+
+    m_jit.move(TrustedImmPtr(0), indexGPR);
+
+    m_jit.loadPtr(MacroAssembler::Address(stringGPR, JSString::offsetOfValue()), tempGPR);
+    slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR));
+
+    slowPath.append(m_jit.branchTest32(
+        MacroAssembler::Zero, MacroAssembler::Address(tempGPR, StringImpl::flagsOffset()),
+        MacroAssembler::TrustedImm32(StringImpl::flagIs8Bit())));
+    m_jit.load32(MacroAssembler::Address(tempGPR, StringImpl::lengthMemoryOffset()), lengthGPR);
+    m_jit.loadPtr(MacroAssembler::Address(tempGPR, StringImpl::dataOffset()), tempGPR);
+
+    auto loopStart = m_jit.label();
+    auto loopDone = m_jit.branch32(CCallHelpers::AboveOrEqual, indexGPR, lengthGPR);
+    m_jit.load8(MacroAssembler::BaseIndex(tempGPR, indexGPR, MacroAssembler::TimesOne), charGPR);
+    slowPath.append(m_jit.branchTest32(CCallHelpers::NonZero, charGPR, TrustedImm32(~0x7F)));
+    m_jit.sub32(TrustedImm32('A'), charGPR);
+    slowPath.append(m_jit.branch32(CCallHelpers::BelowOrEqual, charGPR, TrustedImm32('Z' - 'A')));
+
+    m_jit.add32(TrustedImm32(1), indexGPR);
+    m_jit.jump().linkTo(loopStart, &amp;m_jit);
+    
+    slowPath.link(&amp;m_jit);
+    silentSpillAllRegisters(lengthGPR);
+    callOperation(operationToLowerCase, lengthGPR, stringGPR, indexGPR);
+    silentFillAllRegisters(lengthGPR);
+    m_jit.exceptionCheck();
+    auto done = m_jit.jump();
+
+    loopDone.link(&amp;m_jit);
+    m_jit.move(stringGPR, lengthGPR);
+
+    done.link(&amp;m_jit);
+    cellResult(lengthGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compilePeepHoleInt32Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
</span><span class="cx"> {
</span><span class="cx">     BasicBlock* taken = branchNode-&gt;branchData()-&gt;taken.block;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -938,6 +938,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(cell);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(Jss_JITOperation_EJssUi operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(P_JITOperation_EO operation, GPRReg result, GPRReg object)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(object);
</span><span class="lines">@@ -2651,6 +2656,7 @@
</span><span class="cx">     void compileCompareEqPtr(Node*);
</span><span class="cx">     void compileDefineDataProperty(Node*);
</span><span class="cx">     void compileDefineAccessorProperty(Node*);
</span><ins>+    void compileToLowerCase(Node*);
</ins><span class="cx"> 
</span><span class="cx">     void moveTrueTo(GPRReg);
</span><span class="cx">     void moveFalseTo(GPRReg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -2678,6 +2678,11 @@
</span><span class="cx">         } }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    
+    case ToLowerCase: {
+        compileToLowerCase(node);
+        break;
+    }
</ins><span class="cx"> 
</span><span class="cx">     case GetByValWithThis: {
</span><span class="cx">         JSValueOperand base(this, node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -4888,6 +4888,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case ToLowerCase: {
+        compileToLowerCase(node);
+        break;
+    }
+
</ins><span class="cx">     case IsObject: {
</span><span class="cx">         JSValueOperand value(this, node-&gt;child1());
</span><span class="cx">         GPRTemporary result(this, Reuse, value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -101,6 +101,7 @@
</span><span class="cx">     macro(ScopedArgumentsTable_length, ScopedArgumentsTable::offsetOfLength()) \
</span><span class="cx">     macro(StringImpl_data, StringImpl::dataOffset()) \
</span><span class="cx">     macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \
</span><ins>+    macro(StringImpl_length, StringImpl::lengthMemoryOffset()) \
</ins><span class="cx">     macro(Structure_classInfo, Structure::classInfoOffset()) \
</span><span class="cx">     macro(Structure_globalObject, Structure::globalObjectOffset()) \
</span><span class="cx">     macro(Structure_prototype, Structure::prototypeOffset()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -265,6 +265,7 @@
</span><span class="cx">     case CompareStrictEq:
</span><span class="cx">     case DefineDataProperty:
</span><span class="cx">     case DefineAccessorProperty:
</span><ins>+    case ToLowerCase:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1043,6 +1043,9 @@
</span><span class="cx">         case Unreachable:
</span><span class="cx">             compileUnreachable();
</span><span class="cx">             break;
</span><ins>+        case ToLowerCase:
+            compileToLowerCase();
+            break;
</ins><span class="cx"> 
</span><span class="cx">         case PhantomLocal:
</span><span class="cx">         case LoopHint:
</span><span class="lines">@@ -8623,6 +8626,60 @@
</span><span class="cx">         nonSpeculativeCompare(intFunctor, fallbackFunction);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void compileToLowerCase()
+    {
+        LBasicBlock notRope = m_out.newBlock();
+        LBasicBlock is8Bit = m_out.newBlock();
+        LBasicBlock loopTop = m_out.newBlock();
+        LBasicBlock loopBody = m_out.newBlock();
+        LBasicBlock slowPath = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        LValue string = lowString(m_node-&gt;child1());
+        ValueFromBlock startIndex = m_out.anchor(m_out.constInt32(0));
+        ValueFromBlock startIndexForCall = m_out.anchor(m_out.constInt32(0));
+        LValue impl = m_out.loadPtr(string, m_heaps.JSString_value);
+        m_out.branch(m_out.isZero64(impl),
+            unsure(slowPath), unsure(notRope));
+
+        LBasicBlock lastNext = m_out.appendTo(notRope, is8Bit);
+
+        m_out.branch(
+            m_out.testIsZero32(
+                m_out.load32(impl, m_heaps.StringImpl_hashAndFlags),
+                m_out.constInt32(StringImpl::flagIs8Bit())),
+            unsure(slowPath), unsure(is8Bit));
+
+        m_out.appendTo(is8Bit, loopTop);
+        LValue length = m_out.load32(impl, m_heaps.StringImpl_length);
+        LValue buffer = m_out.loadPtr(impl, m_heaps.StringImpl_data);
+        ValueFromBlock fastResult = m_out.anchor(string);
+        m_out.jump(loopTop);
+
+        m_out.appendTo(loopTop, loopBody);
+        LValue index = m_out.phi(Int32, startIndex);
+        ValueFromBlock indexFromBlock = m_out.anchor(index);
+        m_out.branch(m_out.below(index, length),
+            unsure(loopBody), unsure(continuation));
+
+        m_out.appendTo(loopBody, slowPath);
+
+        LValue byte = m_out.load8ZeroExt32(m_out.baseIndex(m_heaps.characters8, buffer, m_out.zeroExtPtr(index)));
+        LValue isInvalidAsciiRange = m_out.bitAnd(byte, m_out.constInt32(~0x7F));
+        LValue isUpperCase = m_out.belowOrEqual(m_out.sub(byte, m_out.constInt32('A')), m_out.constInt32('Z' - 'A'));
+        LValue isBadCharacter = m_out.bitOr(isInvalidAsciiRange, isUpperCase);
+        m_out.addIncomingToPhi(index, m_out.anchor(m_out.add(index, m_out.int32One)));
+        m_out.branch(isBadCharacter, unsure(slowPath), unsure(loopTop));
+
+        m_out.appendTo(slowPath, continuation);
+        LValue slowPathIndex = m_out.phi(Int32, startIndexForCall, indexFromBlock);
+        ValueFromBlock slowResult = m_out.anchor(vmCall(pointerType(), m_out.operation(operationToLowerCase), m_callFrame, string, slowPathIndex));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
+    }
+
</ins><span class="cx">     void compileResolveScope()
</span><span class="cx">     {
</span><span class="cx">         UniquedStringImpl* uid = m_graph.identifiers()[m_node-&gt;identifierNumber()];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -309,6 +309,7 @@
</span><span class="cx"> typedef StringImpl* (JIT_OPERATION *T_JITOperation_EJss)(ExecState*, JSString*);
</span><span class="cx"> typedef JSString* (JIT_OPERATION *Jss_JITOperation_EZ)(ExecState*, int32_t);
</span><span class="cx"> typedef JSString* (JIT_OPERATION *Jss_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
</span><ins>+typedef JSString* (JIT_OPERATION *Jss_JITOperation_EJssUi)(ExecState*, JSString*, uint32_t);
</ins><span class="cx"> 
</span><span class="cx"> // This method is used to lookup an exception hander, keyed by faultLocation, which is
</span><span class="cx"> // the return location from one of the calls out to one of the helper operations above.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">     JSMapHasIntrinsic,
</span><span class="cx">     JSSetHasIntrinsic,
</span><span class="cx">     HasOwnPropertyIntrinsic,
</span><ins>+    ToLowerCaseIntrinsic,
</ins><span class="cx"> 
</span><span class="cx">     // Getter intrinsics.
</span><span class="cx">     TypedArrayLengthIntrinsic,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -142,7 +142,7 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;slice&quot;, stringProtoFuncSlice, DontEnum, 2);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;substr&quot;, stringProtoFuncSubstr, DontEnum, 2);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;substring&quot;, stringProtoFuncSubstring, DontEnum, 2);
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;toLowerCase&quot;, stringProtoFuncToLowerCase, DontEnum, 0);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(&quot;toLowerCase&quot;, stringProtoFuncToLowerCase, DontEnum, 0, ToLowerCaseIntrinsic);
</ins><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;toUpperCase&quot;, stringProtoFuncToUpperCase, DontEnum, 0);
</span><span class="cx"> #if ENABLE(INTL)
</span><span class="cx">     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(&quot;localeCompare&quot;, stringPrototypeLocaleCompareCodeGenerator, DontEnum);
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/WTF/ChangeLog        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-10-04  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        String.prototype.toLowerCase should be a DFG/FTL intrinsic
+        https://bugs.webkit.org/show_bug.cgi?id=162887
+
+        Reviewed by Filip Pizlo and Yusuke Suzuki.
+
+        This patch exposes a new StringImpl function called convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit
+        which extracts slow path for the 8-bit part of convertToLowercaseWithoutLocale
+        into a helper function. I decided to extract this into its own function because
+        it may be the case that JSCs JITs will want to continue the operation
+        after it has already ensured that part of an 8-bit string is lower case.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::convertToLowercaseWithoutLocale):
+        (WTF::StringImpl::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit):
+        * wtf/text/StringImpl.h:
+        * wtf/text/WTFString.cpp:
+        (WTF::String::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit):
+        * wtf/text/WTFString.h:
+
</ins><span class="cx"> 2016-10-04  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement KeyboardEvent.code from the UI Event spec
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -363,39 +363,20 @@
</span><span class="cx"> Ref&lt;StringImpl&gt; StringImpl::convertToLowercaseWithoutLocale()
</span><span class="cx"> {
</span><span class="cx">     // Note: At one time this was a hot function in the Dromaeo benchmark, specifically the
</span><del>-    // no-op code path up through the first 'return' statement.
</del><ins>+    // no-op code path that may return ourself if we find no upper case letters and no invalid
+    // ASCII letters.
</ins><span class="cx"> 
</span><span class="cx">     // First scan the string for uppercase and non-ASCII characters:
</span><span class="cx">     if (is8Bit()) {
</span><del>-        unsigned failingIndex;
</del><span class="cx">         for (unsigned i = 0; i &lt; m_length; ++i) {
</span><span class="cx">             LChar character = m_data8[i];
</span><del>-            if (UNLIKELY((character &amp; ~0x7F) || isASCIIUpper(character))) {
-                failingIndex = i;
-                goto SlowPath;
-            }
</del><ins>+            if (UNLIKELY((character &amp; ~0x7F) || isASCIIUpper(character)))
+                return convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(i);
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         return *this;
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-SlowPath:
-        LChar* data8;
-        auto newImpl = createUninitializedInternalNonEmpty(m_length, data8);
-
-        for (unsigned i = 0; i &lt; failingIndex; ++i)
-            data8[i] = m_data8[i];
-
-        for (unsigned i = failingIndex; i &lt; m_length; ++i) {
-            LChar character = m_data8[i];
-            if (!(character &amp; ~0x7F))
-                data8[i] = toASCIILower(character);
-            else {
-                ASSERT(u_tolower(character) &lt;= 0xFF);
-                data8[i] = static_cast&lt;LChar&gt;(u_tolower(character));
-            }
-        }
-
-        return newImpl;
-    }
</del><span class="cx">     bool noUpper = true;
</span><span class="cx">     unsigned ored = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -441,6 +422,30 @@
</span><span class="cx">     return newImpl;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Ref&lt;StringImpl&gt; StringImpl::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(unsigned failingIndex)
+{
+    ASSERT(is8Bit());
+    LChar* data8;
+    auto newImpl = createUninitializedInternalNonEmpty(m_length, data8);
+
+    for (unsigned i = 0; i &lt; failingIndex; ++i) {
+        ASSERT(!(m_data8[i] &amp; ~0x7F) &amp;&amp; !isASCIIUpper(m_data8[i]));
+        data8[i] = m_data8[i];
+    }
+
+    for (unsigned i = failingIndex; i &lt; m_length; ++i) {
+        LChar character = m_data8[i];
+        if (!(character &amp; ~0x7F))
+            data8[i] = toASCIILower(character);
+        else {
+            ASSERT(u_tolower(character) &lt;= 0xFF);
+            data8[i] = static_cast&lt;LChar&gt;(u_tolower(character));
+        }
+    }
+
+    return newImpl;
+}
+
</ins><span class="cx"> Ref&lt;StringImpl&gt; StringImpl::convertToUppercaseWithoutLocale()
</span><span class="cx"> {
</span><span class="cx">     // This function could be optimized for no-op cases the way
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/WTF/wtf/text/StringImpl.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -682,6 +682,7 @@
</span><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToASCIILowercase();
</span><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToASCIIUppercase();
</span><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToLowercaseWithoutLocale();
</span><ins>+    WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(unsigned);
</ins><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToUppercaseWithoutLocale();
</span><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToLowercaseWithLocale(const AtomicString&amp; localeIdentifier);
</span><span class="cx">     WTF_EXPORT_STRING_API Ref&lt;StringImpl&gt; convertToUppercaseWithLocale(const AtomicString&amp; localeIdentifier);
</span></span></pre></div>
<a id="trunkSourceWTFwtftextWTFStringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/WTFString.cpp (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/WTFString.cpp        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/WTF/wtf/text/WTFString.cpp        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -358,6 +358,13 @@
</span><span class="cx">     return m_impl-&gt;convertToLowercaseWithoutLocale();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String String::convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(unsigned failingIndex) const
+{
+    if (!m_impl)
+        return String();
+    return m_impl-&gt;convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex);
+}
+
</ins><span class="cx"> String String::convertToUppercaseWithoutLocale() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_impl)
</span></span></pre></div>
<a id="trunkSourceWTFwtftextWTFStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/WTFString.h (206803 => 206804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/WTFString.h        2016-10-05 03:13:35 UTC (rev 206803)
+++ trunk/Source/WTF/wtf/text/WTFString.h        2016-10-05 06:16:15 UTC (rev 206804)
</span><span class="lines">@@ -330,6 +330,7 @@
</span><span class="cx">     WTF_EXPORT_STRING_API String convertToASCIILowercase() const;
</span><span class="cx">     WTF_EXPORT_STRING_API String convertToASCIIUppercase() const;
</span><span class="cx">     WTF_EXPORT_STRING_API String convertToLowercaseWithoutLocale() const;
</span><ins>+    WTF_EXPORT_STRING_API String convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(unsigned) const;
</ins><span class="cx">     WTF_EXPORT_STRING_API String convertToUppercaseWithoutLocale() const;
</span><span class="cx">     WTF_EXPORT_STRING_API String convertToLowercaseWithLocale(const AtomicString&amp; localeIdentifier) const;
</span><span class="cx">     WTF_EXPORT_STRING_API String convertToUppercaseWithLocale(const AtomicString&amp; localeIdentifier) const;
</span></span></pre>
</div>
</div>

</body>
</html>