<!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>[166463] 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/166463">166463</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-03-30 11:43:41 -0700 (Sun, 30 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Land the stackmap register liveness glue with the uses of the liveness disabled
https://bugs.webkit.org/show_bug.cgi?id=130924

Source/JavaScriptCore: 

Reviewed by Oliver Hunt.
        
Add the liveness and fix other bugs I found.

* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFor):
* ftl/FTLCompile.cpp:
(JSC::FTL::usedRegistersFor):
(JSC::FTL::fixFunctionBasedOnStackMaps):
* ftl/FTLSlowPathCall.cpp:
* ftl/FTLSlowPathCallKey.cpp:
(JSC::FTL::SlowPathCallKey::dump):
* ftl/FTLSlowPathCallKey.h:
(JSC::FTL::SlowPathCallKey::SlowPathCallKey):
(JSC::FTL::SlowPathCallKey::argumentRegisters):
(JSC::FTL::SlowPathCallKey::withCallTarget):
* ftl/FTLStackMaps.cpp:
(JSC::FTL::StackMaps::Record::locationSet):
(JSC::FTL::StackMaps::Record::liveOutsSet):
(JSC::FTL::StackMaps::Record::usedRegisterSet):
* ftl/FTLStackMaps.h:
* ftl/FTLThunks.cpp:
(JSC::FTL::registerClobberCheck):
(JSC::FTL::slowPathCallThunkGenerator):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::stackRegisters):
(JSC::RegisterSet::reservedHardwareRegisters):
(JSC::RegisterSet::runtimeRegisters):
(JSC::RegisterSet::specialRegisters):
(JSC::RegisterSet::dump):
* jit/RegisterSet.h:
(JSC::RegisterSet::RegisterSet):
(JSC::RegisterSet::setAny):
(JSC::RegisterSet::setMany):
* jit/Repatch.cpp:
(JSC::tryCacheGetByID):
(JSC::tryCachePutByID):
(JSC::tryRepatchIn):
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
* runtime/Options.h:

Tools: 

Reviewed by Oliver Hunt.

* Scripts/run-jsc-stress-tests:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSlowPathCallcpp">trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSlowPathCallKeycpp">trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSlowPathCallKeyh">trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStackMapscpp">trunk/Source/JavaScriptCore/ftl/FTLStackMaps.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStackMapsh">trunk/Source/JavaScriptCore/ftl/FTLStackMaps.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLThunkscpp">trunk/Source/JavaScriptCore/ftl/FTLThunks.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSetcpp">trunk/Source/JavaScriptCore/jit/RegisterSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2014-03-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Land the stackmap register liveness glue with the uses of the liveness disabled
+        https://bugs.webkit.org/show_bug.cgi?id=130924
+
+        Reviewed by Oliver Hunt.
+        
+        Add the liveness and fix other bugs I found.
+
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFor):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::usedRegistersFor):
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        * ftl/FTLSlowPathCall.cpp:
+        * ftl/FTLSlowPathCallKey.cpp:
+        (JSC::FTL::SlowPathCallKey::dump):
+        * ftl/FTLSlowPathCallKey.h:
+        (JSC::FTL::SlowPathCallKey::SlowPathCallKey):
+        (JSC::FTL::SlowPathCallKey::argumentRegisters):
+        (JSC::FTL::SlowPathCallKey::withCallTarget):
+        * ftl/FTLStackMaps.cpp:
+        (JSC::FTL::StackMaps::Record::locationSet):
+        (JSC::FTL::StackMaps::Record::liveOutsSet):
+        (JSC::FTL::StackMaps::Record::usedRegisterSet):
+        * ftl/FTLStackMaps.h:
+        * ftl/FTLThunks.cpp:
+        (JSC::FTL::registerClobberCheck):
+        (JSC::FTL::slowPathCallThunkGenerator):
+        * jit/RegisterSet.cpp:
+        (JSC::RegisterSet::stackRegisters):
+        (JSC::RegisterSet::reservedHardwareRegisters):
+        (JSC::RegisterSet::runtimeRegisters):
+        (JSC::RegisterSet::specialRegisters):
+        (JSC::RegisterSet::dump):
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::RegisterSet):
+        (JSC::RegisterSet::setAny):
+        (JSC::RegisterSet::setMany):
+        * jit/Repatch.cpp:
+        (JSC::tryCacheGetByID):
+        (JSC::tryCachePutByID):
+        (JSC::tryRepatchIn):
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2014-03-28  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         mandreel throws a checksum error on 32-bit x86.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -238,7 +238,10 @@
</span><span class="cx">             result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        if (result.isSet())
</del><ins>+        // We use TakesSlowPath in some cases where the stub was unset. That's weird and
+        // it would be better not to do that. But it means that we have to defend
+        // ourselves here.
+        if (result.isSimple())
</ins><span class="cx">             return result;
</span><span class="cx">     }
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -163,6 +163,13 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static RegisterSet usedRegistersFor(const StackMaps::Record&amp; record)
+{
+    if (Options::assumeAllRegsInFTLICAreLive())
+        return RegisterSet::allRegisters();
+    return record.usedRegisterSet();
+}
+
</ins><span class="cx"> static void fixFunctionBasedOnStackMaps(
</span><span class="cx">     State&amp; state, CodeBlock* codeBlock, JITCode* jitCode, GeneratedFunction generatedFunction,
</span><span class="cx">     StackMaps::RecordMap&amp; recordMap, bool didSeeUnwindInfo)
</span><span class="lines">@@ -300,9 +307,7 @@
</span><span class="cx">             for (unsigned i = 0; i &lt; iter-&gt;value.size(); ++i) {
</span><span class="cx">                 StackMaps::Record&amp; record = iter-&gt;value[i];
</span><span class="cx">             
</span><del>-                // FIXME: Use the liveness information that LLVM gives us.
-                // https://bugs.webkit.org/show_bug.cgi?id=130791
-                RegisterSet usedRegisters = RegisterSet::allRegisters();
</del><ins>+                RegisterSet usedRegisters = usedRegistersFor(record);
</ins><span class="cx">                 
</span><span class="cx">                 GPRReg result = record.locations[0].directGPR();
</span><span class="cx">                 GPRReg base = record.locations[1].directGPR();
</span><span class="lines">@@ -339,9 +344,7 @@
</span><span class="cx">             for (unsigned i = 0; i &lt; iter-&gt;value.size(); ++i) {
</span><span class="cx">                 StackMaps::Record&amp; record = iter-&gt;value[i];
</span><span class="cx">                 
</span><del>-                // FIXME: Use the liveness information that LLVM gives us.
-                // https://bugs.webkit.org/show_bug.cgi?id=130791
-                RegisterSet usedRegisters = RegisterSet::allRegisters();
</del><ins>+                RegisterSet usedRegisters = usedRegistersFor(record);
</ins><span class="cx">                 
</span><span class="cx">                 GPRReg base = record.locations[0].directGPR();
</span><span class="cx">                 GPRReg value = record.locations[1].directGPR();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSlowPathCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -67,7 +67,8 @@
</span><span class="cx">             (std::max(m_numArgs, NUMBER_OF_ARGUMENT_REGISTERS) - NUMBER_OF_ARGUMENT_REGISTERS) * wordSize;
</span><span class="cx">         
</span><span class="cx">         for (unsigned i = std::min(NUMBER_OF_ARGUMENT_REGISTERS, numArgs); i--;)
</span><del>-            m_callingConventionRegisters.set(GPRInfo::toArgumentRegister(i));
</del><ins>+            m_argumentRegisters.set(GPRInfo::toArgumentRegister(i));
+        m_callingConventionRegisters.merge(m_argumentRegisters);
</ins><span class="cx">         if (returnRegister != InvalidGPRReg)
</span><span class="cx">             m_callingConventionRegisters.set(GPRInfo::returnValueGPR);
</span><span class="cx">         m_callingConventionRegisters.filter(m_usedRegisters);
</span><span class="lines">@@ -84,10 +85,8 @@
</span><span class="cx">             stackBytesNeededForReturnAddress +
</span><span class="cx">             (m_usedRegisters.numberOfSetRegisters() - numberOfCallingConventionRegisters) * wordSize;
</span><span class="cx">         
</span><del>-        size_t stackAlignment = 16;
</del><ins>+        m_stackBytesNeeded = (m_stackBytesNeeded + stackAlignmentBytes() - 1) &amp; ~(stackAlignmentBytes() - 1);
</ins><span class="cx">         
</span><del>-        m_stackBytesNeeded = (m_stackBytesNeeded + stackAlignment - 1) &amp; ~(stackAlignment - 1);
-        
</del><span class="cx">         m_jit.subPtr(CCallHelpers::TrustedImm32(m_stackBytesNeeded), CCallHelpers::stackPointerRegister);
</span><span class="cx">         
</span><span class="cx">         m_thunkSaveSet = m_usedRegisters;
</span><span class="lines">@@ -133,7 +132,7 @@
</span><span class="cx">     
</span><span class="cx">     SlowPathCallKey keyWithTarget(void* callTarget) const
</span><span class="cx">     {
</span><del>-        return SlowPathCallKey(usedRegisters(), callTarget, offset());
</del><ins>+        return SlowPathCallKey(usedRegisters(), callTarget, m_argumentRegisters, offset());
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     MacroAssembler::Call makeCall(void* callTarget, MacroAssembler::JumpList* exceptionTarget)
</span><span class="lines">@@ -149,6 +148,7 @@
</span><span class="cx"> private:
</span><span class="cx">     State&amp; m_state;
</span><span class="cx">     RegisterSet m_usedRegisters;
</span><ins>+    RegisterSet m_argumentRegisters;
</ins><span class="cx">     RegisterSet m_callingConventionRegisters;
</span><span class="cx">     CCallHelpers&amp; m_jit;
</span><span class="cx">     unsigned m_numArgs;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSlowPathCallKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SlowPathCallKey::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><del>-    out.print(&quot;&lt;usedRegisters = &quot;, m_usedRegisters, &quot;, offset = &quot;, m_offset, &quot;, callTarget = &quot;, RawPointer(m_callTarget), &quot;&gt;&quot;);
</del><ins>+    out.print(&quot;&lt;usedRegisters = &quot;, m_usedRegisters, &quot;, offset = &quot;, m_offset, &quot;, callTarget = &quot;, RawPointer(m_callTarget), &quot;, argumentRegisters = &quot;, m_argumentRegisters, &quot;&gt;&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSlowPathCallKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.h (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.h        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLSlowPathCallKey.h        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -50,20 +50,24 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    SlowPathCallKey(const RegisterSet&amp; set, void* callTarget, ptrdiff_t offset)
</del><ins>+    SlowPathCallKey(
+        const RegisterSet&amp; set, void* callTarget, const RegisterSet&amp; argumentRegisters,
+        ptrdiff_t offset)
</ins><span class="cx">         : m_usedRegisters(set)
</span><span class="cx">         , m_callTarget(callTarget)
</span><ins>+        , m_argumentRegisters(argumentRegisters)
</ins><span class="cx">         , m_offset(offset)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     const RegisterSet&amp; usedRegisters() const { return m_usedRegisters; }
</span><span class="cx">     void* callTarget() const { return m_callTarget; }
</span><ins>+    const RegisterSet&amp; argumentRegisters() const { return m_argumentRegisters; }
</ins><span class="cx">     ptrdiff_t offset() const { return m_offset; }
</span><span class="cx">     
</span><span class="cx">     SlowPathCallKey withCallTarget(void* callTarget)
</span><span class="cx">     {
</span><del>-        return SlowPathCallKey(usedRegisters(), callTarget, offset());
</del><ins>+        return SlowPathCallKey(usedRegisters(), callTarget, argumentRegisters(), offset());
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="lines">@@ -102,6 +106,7 @@
</span><span class="cx"> private:
</span><span class="cx">     RegisterSet m_usedRegisters;
</span><span class="cx">     void* m_callTarget;
</span><ins>+    RegisterSet m_argumentRegisters;
</ins><span class="cx">     ptrdiff_t m_offset;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStackMapscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLStackMaps.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLStackMaps.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLStackMaps.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -149,6 +149,44 @@
</span><span class="cx">         listDump(liveOuts), &quot;])&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterSet StackMaps::Record::locationSet() const
+{
+    RegisterSet result;
+    for (unsigned i = locations.size(); i--;) {
+        Reg reg = locations[i].dwarfReg.reg();
+        if (!reg)
+            continue;
+        result.set(reg);
+    }
+    return result;
+}
+
+RegisterSet StackMaps::Record::liveOutsSet() const
+{
+    RegisterSet result;
+    for (unsigned i = liveOuts.size(); i--;) {
+        LiveOut liveOut = liveOuts[i];
+        Reg reg = liveOut.dwarfReg.reg();
+        // FIXME: Either assert that size is not greater than sizeof(pointer), or actually
+        // save the high bits of registers.
+        // https://bugs.webkit.org/show_bug.cgi?id=130885
+        if (!reg) {
+            dataLog(&quot;Invalid liveOuts entry in: &quot;, *this, &quot;\n&quot;);
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        result.set(reg);
+    }
+    return result;
+}
+
+RegisterSet StackMaps::Record::usedRegisterSet() const
+{
+    RegisterSet result;
+    result.merge(locationSet());
+    result.merge(liveOutsSet());
+    return result;
+}
+
</ins><span class="cx"> bool StackMaps::parse(DataView* view)
</span><span class="cx"> {
</span><span class="cx">     ParseContext context;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStackMapsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLStackMaps.h (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLStackMaps.h        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLStackMaps.h        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;DataView.h&quot;
</span><span class="cx"> #include &quot;FTLDWARFRegister.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><ins>+#include &quot;RegisterSet.h&quot;
</ins><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -106,6 +107,10 @@
</span><span class="cx">         
</span><span class="cx">         bool parse(ParseContext&amp;);
</span><span class="cx">         void dump(PrintStream&amp;) const;
</span><ins>+        
+        RegisterSet liveOutsSet() const;
+        RegisterSet locationSet() const;
+        RegisterSet usedRegisterSet() const;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     unsigned version;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLThunkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLThunks.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLThunks.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/ftl/FTLThunks.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -106,6 +106,34 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;FTL OSR exit generation thunk&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void registerClobberCheck(AssemblyHelpers&amp; jit, RegisterSet dontClobber)
+{
+    if (!Options::clobberAllRegsInFTLICSlowPath())
+        return;
+    
+    RegisterSet clobber = RegisterSet::allRegisters();
+    clobber.exclude(RegisterSet::reservedHardwareRegisters());
+    clobber.exclude(RegisterSet::stackRegisters());
+    clobber.exclude(RegisterSet::calleeSaveRegisters());
+    clobber.exclude(dontClobber);
+    
+    GPRReg someGPR;
+    for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
+        if (!clobber.get(reg) || !reg.isGPR())
+            continue;
+        
+        jit.move(AssemblyHelpers::TrustedImm32(0x1337beef), reg.gpr());
+        someGPR = reg.gpr();
+    }
+    
+    for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
+        if (!clobber.get(reg) || !reg.isFPR())
+            continue;
+        
+        jit.move64ToDouble(someGPR, reg.fpr());
+    }
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef slowPathCallThunkGenerator(VM&amp; vm, const SlowPathCallKey&amp; key)
</span><span class="cx"> {
</span><span class="cx">     AssemblyHelpers jit(&amp;vm, 0);
</span><span class="lines">@@ -134,13 +162,13 @@
</span><span class="cx">         currentOffset += sizeof(double);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // FIXME: CStack - Need to do soemething like jit.emitFunctionPrologue();
</del><span class="cx">     jit.preserveReturnAddressAfterCall(GPRInfo::nonArgGPR0);
</span><span class="cx">     jit.storePtr(GPRInfo::nonArgGPR0, AssemblyHelpers::Address(MacroAssembler::stackPointerRegister, key.offset()));
</span><span class="cx">     
</span><ins>+    registerClobberCheck(jit, key.argumentRegisters());
+    
</ins><span class="cx">     AssemblyHelpers::Call call = jit.call();
</span><span class="cx"> 
</span><del>-    // FIXME: CStack - Need to do something like jit.emitFunctionEpilogue();
</del><span class="cx">     jit.loadPtr(AssemblyHelpers::Address(MacroAssembler::stackPointerRegister, key.offset()), GPRInfo::nonPreservedNonReturnGPR);
</span><span class="cx">     jit.restoreReturnAddressBeforeReturn(GPRInfo::nonPreservedNonReturnGPR);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -31,43 +31,39 @@
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &lt;wtf/CommaPrinter.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> RegisterSet RegisterSet::stackRegisters()
</span><span class="cx"> {
</span><del>-    RegisterSet result;
-    result.set(MacroAssembler::stackPointerRegister);
-    result.set(MacroAssembler::framePointerRegister);
-    return result;
</del><ins>+    return RegisterSet(
+        MacroAssembler::stackPointerRegister,
+        MacroAssembler::framePointerRegister);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterSet RegisterSet::reservedHardwareRegisters()
</span><span class="cx"> {
</span><del>-    RegisterSet result;
</del><span class="cx"> #if CPU(ARM64)
</span><del>-    result.set(ARM64Registers::lr);
</del><ins>+    return RegisterSet(ARM64Registers::lr);
+#else
+    return RegisterSet();
</ins><span class="cx"> #endif
</span><del>-    return result;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterSet RegisterSet::runtimeRegisters()
</span><span class="cx"> {
</span><del>-    RegisterSet result;
</del><span class="cx"> #if USE(JSVALUE64)
</span><del>-    result.set(GPRInfo::tagTypeNumberRegister);
-    result.set(GPRInfo::tagMaskRegister);
</del><ins>+    return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
+#else
+    return RegisterSet();
</ins><span class="cx"> #endif
</span><del>-    return result;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterSet RegisterSet::specialRegisters()
</span><span class="cx"> {
</span><del>-    RegisterSet result;
-    result.merge(stackRegisters());
-    result.merge(reservedHardwareRegisters());
-    result.merge(runtimeRegisters());
-    return result;
</del><ins>+    return RegisterSet(
+        stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterSet RegisterSet::calleeSaveRegisters()
</span><span class="lines">@@ -155,7 +151,13 @@
</span><span class="cx"> 
</span><span class="cx"> void RegisterSet::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><del>-    m_vector.dump(out);
</del><ins>+    CommaPrinter comma;
+    out.print(&quot;[&quot;);
+    for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
+        if (get(reg))
+            out.print(comma, reg);
+    }
+    out.print(&quot;]&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -39,7 +39,11 @@
</span><span class="cx"> 
</span><span class="cx"> class RegisterSet {
</span><span class="cx"> public:
</span><del>-    RegisterSet() { }
</del><ins>+    template&lt;typename... Regs&gt;
+    explicit RegisterSet(Regs... regs)
+    {
+        setMany(regs...);
+    }
</ins><span class="cx">     
</span><span class="cx">     static RegisterSet stackRegisters();
</span><span class="cx">     static RegisterSet reservedHardwareRegisters();
</span><span class="lines">@@ -55,7 +59,7 @@
</span><span class="cx">         ASSERT(!!reg);
</span><span class="cx">         m_vector.set(reg.index(), value);
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     void set(JSValueRegs regs)
</span><span class="cx">     {
</span><span class="cx">         if (regs.tagGPR() != InvalidGPRReg)
</span><span class="lines">@@ -105,6 +109,16 @@
</span><span class="cx">     unsigned hash() const { return m_vector.hash(); }
</span><span class="cx">     
</span><span class="cx"> private:
</span><ins>+    void setAny(Reg reg) { set(reg); }
+    void setAny(const RegisterSet&amp; set) { merge(set); }
+    void setMany() { }
+    template&lt;typename RegType, typename... Regs&gt;
+    void setMany(RegType reg, Regs... regs)
+    {
+        setAny(reg);
+        setMany(regs...);
+    }
+
</ins><span class="cx">     BitVector m_vector;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -490,6 +490,9 @@
</span><span class="cx"> 
</span><span class="cx"> static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier&amp; propertyName, const PropertySlot&amp; slot, StructureStubInfo&amp; stubInfo)
</span><span class="cx"> {
</span><ins>+    if (Options::forceICFailure())
+        return false;
+    
</ins><span class="cx">     // FIXME: Write a test that proves we need to check for recursion here just
</span><span class="cx">     // like the interpreter does, then add a check for recursion.
</span><span class="cx"> 
</span><span class="lines">@@ -1110,6 +1113,9 @@
</span><span class="cx"> 
</span><span class="cx"> static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier&amp; ident, const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</span><span class="cx"> {
</span><ins>+    if (Options::forceICFailure())
+        return false;
+    
</ins><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx"> 
</span><span class="lines">@@ -1139,6 +1145,8 @@
</span><span class="cx">             
</span><span class="cx">             // Skip optimizing the case where we need realloc, and the structure has
</span><span class="cx">             // indexing storage.
</span><ins>+            // FIXME: We shouldn't skip this!  Implement it!
+            // https://bugs.webkit.org/show_bug.cgi?id=130914
</ins><span class="cx">             if (oldStructure-&gt;couldHaveIndexingHeader())
</span><span class="cx">                 return false;
</span><span class="cx">             
</span><span class="lines">@@ -1340,6 +1348,9 @@
</span><span class="cx">     ExecState* exec, JSCell* base, const Identifier&amp; ident, bool wasFound,
</span><span class="cx">     const PropertySlot&amp; slot, StructureStubInfo&amp; stubInfo)
</span><span class="cx"> {
</span><ins>+    if (Options::forceICFailure())
+        return false;
+    
</ins><span class="cx">     if (!base-&gt;structure()-&gt;propertyAccessesAreCacheable())
</span><span class="cx">         return false;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -206,7 +206,7 @@
</span><span class="cx"> #if !ENABLE(FTL_JIT)
</span><span class="cx">     Options::useFTLJIT() = false;
</span><span class="cx"> #endif
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (Options::showDisassembly()
</span><span class="cx">         || Options::showDFGDisassembly()
</span><span class="cx">         || Options::showFTLDisassembly()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -102,6 +102,7 @@
</span><span class="cx">     v(bool, crashIfCantAllocateJITMemory, false) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, forceDFGCodeBlockLiveness, false) \
</span><ins>+    v(bool, forceICFailure, false) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, dumpGeneratedBytecodes, false) \
</span><span class="cx">     v(bool, dumpBytecodeLivenessResults, false) \
</span><span class="lines">@@ -157,6 +158,8 @@
</span><span class="cx">     v(unsigned, llvmMaxStackSize, 128 * KB) \
</span><span class="cx">     v(bool, llvmDisallowAVX, true) \
</span><span class="cx">     v(bool, ftlCrashes, false) /* fool-proof way of checking that you ended up in the FTL. ;-) */\
</span><ins>+    v(bool, clobberAllRegsInFTLICSlowPath, !ASSERT_DISABLED) \
+    v(bool, assumeAllRegsInFTLICAreLive, true) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, enableConcurrentJIT, true) \
</span><span class="cx">     v(unsigned, numberOfDFGCompilerThreads, computeNumberOfWorkerThreads(2, 2) - 1) \
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Tools/ChangeLog        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2014-03-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Land the stackmap register liveness glue with the uses of the liveness disabled
+        https://bugs.webkit.org/show_bug.cgi?id=130924
+
+        Reviewed by Oliver Hunt.
+
+        * Scripts/run-jsc-stress-tests:
+
</ins><span class="cx"> 2014-03-29  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update WebKit1.StringTruncator for Mountain Lion.
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (166462 => 166463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2014-03-30 16:53:53 UTC (rev 166462)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2014-03-30 18:43:41 UTC (rev 166463)
</span><span class="lines">@@ -250,6 +250,10 @@
</span><span class="cx">     &quot;awk &quot; + Shellwords.shellescape(&quot;{ printf #{(prefix + ': ').inspect}; print }&quot;)
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def redirectAndPrefixCommand(prefix)
+    prefixCommand(prefix) + &quot; 2&gt;&amp;1&quot;
+end
+
</ins><span class="cx"> def pipeAndPrefixCommand(outputFilename, prefix)
</span><span class="cx">     &quot;tee &quot; + Shellwords.shellescape(outputFilename.to_s) + &quot; | &quot; + prefixCommand(prefix)
</span><span class="cx"> end
</span><span class="lines">@@ -276,7 +280,7 @@
</span><span class="cx">         | outp, plan |
</span><span class="cx">         outp.puts &quot;if test -e #{plan.failFile}&quot;
</span><span class="cx">         outp.puts &quot;then&quot;
</span><del>-        outp.puts &quot;    (echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;else&quot;
</span><span class="cx">         outp.puts &quot;    &quot; + plan.successCommand
</span><span class="lines">@@ -293,7 +297,7 @@
</span><span class="cx">         
</span><span class="cx">         outp.puts &quot;if test -e #{plan.failFile}&quot;
</span><span class="cx">         outp.puts &quot;then&quot;
</span><del>-        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;elif test -e ../#{Shellwords.shellescape(expectedFilename)}&quot;
</span><span class="cx">         outp.puts &quot;then&quot;
</span><span class="lines">@@ -302,11 +306,11 @@
</span><span class="cx">         outp.puts &quot;    then&quot;
</span><span class="cx">         outp.puts &quot;    &quot; + plan.successCommand
</span><span class="cx">         outp.puts &quot;    else&quot;
</span><del>-        outp.puts &quot;        (echo \&quot;DIFF FAILURE!\&quot; &amp;&amp; cat #{diffFilename}) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;        (echo \&quot;DIFF FAILURE!\&quot; &amp;&amp; cat #{diffFilename}) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;        &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;    fi&quot;
</span><span class="cx">         outp.puts &quot;else&quot;
</span><del>-        outp.puts &quot;    (echo \&quot;NO EXPECTATION!\&quot; &amp;&amp; cat #{outputFilename}) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (echo \&quot;NO EXPECTATION!\&quot; &amp;&amp; cat #{outputFilename}) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;fi&quot;
</span><span class="cx">     }
</span><span class="lines">@@ -321,11 +325,11 @@
</span><span class="cx"> 
</span><span class="cx">         outp.puts &quot;if test -e #{plan.failFile}&quot;
</span><span class="cx">         outp.puts &quot;then&quot;
</span><del>-        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;elif grep -i -q failed! #{outputFilename}&quot;
</span><span class="cx">         outp.puts &quot;then&quot;
</span><del>-        outp.puts &quot;    (echo Detected failures: &amp;&amp; cat #{outputFilename}) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (echo Detected failures: &amp;&amp; cat #{outputFilename}) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;else&quot;
</span><span class="cx">         outp.puts &quot;    &quot; + plan.successCommand
</span><span class="lines">@@ -347,7 +351,7 @@
</span><span class="cx">         outp.puts &quot;then&quot;
</span><span class="cx">         outp.puts &quot;    &quot; + plan.successCommand
</span><span class="cx">         outp.puts &quot;else&quot;
</span><del>-        outp.puts &quot;    (echo NOTICE: You made this test pass, but it was expected to fail) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (echo NOTICE: You made this test pass, but it was expected to fail) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;fi&quot;
</span><span class="cx">     }
</span><span class="lines">@@ -366,17 +370,17 @@
</span><span class="cx">         outp.puts &quot;    then&quot;
</span><span class="cx">         outp.puts &quot;        if grep -i -q failed! #{outputFilename}&quot;
</span><span class="cx">         outp.puts &quot;        then&quot;
</span><del>-        outp.puts &quot;            (echo Detected failures: &amp;&amp; cat #{outputFilename}) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;            (echo Detected failures: &amp;&amp; cat #{outputFilename}) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;            &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;        else&quot;
</span><span class="cx">         outp.puts &quot;            &quot; + plan.successCommand
</span><span class="cx">         outp.puts &quot;        fi&quot;
</span><span class="cx">         outp.puts &quot;    else&quot;
</span><del>-        outp.puts &quot;        (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;        (cat #{outputFilename} &amp;&amp; echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;        &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;    fi&quot;
</span><span class="cx">         outp.puts &quot;else&quot;
</span><del>-        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Test expected to fail, but returned successfully) | &quot; + prefixCommand(plan.name) + &quot;1&gt;&amp;2&quot;
</del><ins>+        outp.puts &quot;    (cat #{outputFilename} &amp;&amp; echo ERROR: Test expected to fail, but returned successfully) | &quot; + redirectAndPrefixCommand(plan.name)
</ins><span class="cx">         outp.puts &quot;    &quot; + plan.failCommand
</span><span class="cx">         outp.puts &quot;fi&quot;
</span><span class="cx">     }
</span><span class="lines">@@ -610,6 +614,11 @@
</span><span class="cx">     runFTLNoCJIT
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def defaultFTLSpotCheck
+    defaultQuickRun
+    runFTLNoSimpleOpt
+end
+
</ins><span class="cx"> # This is expected to not do eager runs because eager runs can have a lot of recompilations
</span><span class="cx"> # for reasons that don't arise in the real world. It's used for tests that assert convergence
</span><span class="cx"> # by counting recompilations.
</span><span class="lines">@@ -639,7 +648,7 @@
</span><span class="cx">     prepareExtraRelativeFiles([&quot;../#{testName}-expected.txt&quot;], $benchmarkDirectory)
</span><span class="cx">     prepareExtraAbsoluteFiles(LAYOUTTESTS_PATH, [&quot;resources/standalone-pre.js&quot;, &quot;resources/standalone-post.js&quot;])
</span><span class="cx"> 
</span><del>-    args = [pathToVM.to_s] + options +
</del><ins>+    args = [pathToVM.to_s] + NO_FTL_OPTIONS + options +
</ins><span class="cx">         [(Pathname.new(&quot;resources&quot;) + &quot;standalone-pre.js&quot;).to_s,
</span><span class="cx">          $benchmark.to_s,
</span><span class="cx">          (Pathname.new(&quot;resources&quot;) + &quot;standalone-post.js&quot;).to_s]
</span><span class="lines">@@ -721,7 +730,7 @@
</span><span class="cx">         kind = &quot;mozilla&quot;
</span><span class="cx">     end
</span><span class="cx">     prepareExtraRelativeFiles(extraFiles.map{|v| (Pathname(&quot;..&quot;) + v).to_s}, $collection)
</span><del>-    args = [pathToVM.to_s] + options + extraFiles.map{|v| v.to_s} + [$benchmark.to_s]
</del><ins>+    args = [pathToVM.to_s] + NO_FTL_OPTIONS + options + extraFiles.map{|v| v.to_s} + [$benchmark.to_s]
</ins><span class="cx">     case mode
</span><span class="cx">     when :normal
</span><span class="cx">         errorHandler = mozillaErrorHandler
</span></span></pre>
</div>
</div>

</body>
</html>