<!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>[195298] trunk/Source</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/195298">195298</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-01-19 11:20:35 -0800 (Tue, 19 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL B3 should be just as fast as FTL LLVM on Octane/crypto
https://bugs.webkit.org/show_bug.cgi?id=153113

Reviewed by Saam Barati.

Source/JavaScriptCore:

This is the result of a hacking rampage to close the gap between FTL B3 and FTL LLVM on
Octane/crypto. It was a very successful rampage.

The biggest change in this patch is the introduction of a phase called fixObviousSpills()
that fixes patterns like:

Store register to stack slot and then use stack slot:
    Move %rcx, (stack42)
    Foo use:(stack42) // replace (stack42) with %rcx here.

Load stack slot into register and then use stack slot:
    Move (stack42), %rcx
    Foo use:(stack42) // replace (stack42) with %rcx here.

Store constant into stack slot and then use stack slot:
    Move $42, %rcx
    Move %rcx, (stack42)
    Bar def:%rcx // %rcx isn't available anymore, but we still know that (stack42) is $42
    Foo use:(stack42) // replace (stack42) with $42 here.

This phases does these fixups by doing a global forward flow that propagates sets of
must-aliases.

Also added a phase to report register pressure. It pretty-prints code alongside the set of
in-use registers above each instruction. Using this phase, I found that our register
allocator is actually doing a pretty awesome job. I had previously feared that we'd have to
make substantial changes to register allocation. I don't have such a fear anymore, at least
for Octane/crypto. In the future, we can check how the regalloc is performing just by
enabling logAirRegisterPressure.

Also fixed some FTL codegen pathologies. We were using bitOr where we meant to use a
conditional or. LLVM likes to canonicalize boolean expressions this way. B3, on the other
hand, doesn't do this canonicalization and doesn't have logic to decompose it into sequences
of branches.

Also added strength reductions for checked arithmetic. It turns out that LLVM learned how to
reduce checked multiply to unchecked multiply in some obvious cases that our existing DFG
optimizations lacked. Ideally, our DFG integer range optimization phase would cover this. But
the cases of interest were dead simple - the incoming values to the CheckMul were obviously
too small to cause overflow. I added such reasoning to B3's strength reduction.

Finally, this fixes some bugs with how we were handling subwidth spill slots. The register
allocator was making two mistakes. First, it might cause a Width64 def or use of a 4-byte
spill slot. In that case, it would extend the size of the spill slot to ensure that the use
or def is safe. Second, it emulates ZDef on Tmp behavior by emitting a Move32 to initialize
the high bits of a spill slot. But this is unsound because of the liveness semantics of spill
slots. They cannot have more than one def to initialize their value. I fixed that by making
allocateStack() be the thing that fixes ZDefs. That's a change to ZDef semantics: now, ZDef
on an anonymous stack slot means that the high bits are zero-filled. I wasn't able to
construct a test for this. It might be a hypothetical bug, but still, I like how this
simplifies the register allocator.

This is a ~0.7% speed-up on Octane.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3CheckSpecial.cpp:
(JSC::B3::CheckSpecial::hiddenBranch):
(JSC::B3::CheckSpecial::forEachArg):
(JSC::B3::CheckSpecial::commitHiddenBranch): Deleted.
* b3/B3CheckSpecial.h:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::fillStackmap):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3StackmapValue.h:
* b3/air/AirAllocateStack.cpp:
(JSC::B3::Air::allocateStack):
* b3/air/AirAllocateStack.h:
* b3/air/AirArg.h:
(JSC::B3::Air::Arg::callArg):
(JSC::B3::Air::Arg::stackAddr):
(JSC::B3::Air::Arg::isValidScale):
* b3/air/AirBasicBlock.cpp:
(JSC::B3::Air::BasicBlock::deepDump):
(JSC::B3::Air::BasicBlock::dumpHeader):
(JSC::B3::Air::BasicBlock::dumpFooter):
* b3/air/AirBasicBlock.h:
* b3/air/AirCCallSpecial.cpp:
(JSC::B3::Air::CCallSpecial::CCallSpecial):
(JSC::B3::Air::CCallSpecial::~CCallSpecial):
* b3/air/AirCode.h:
(JSC::B3::Air::Code::lastPhaseName):
(JSC::B3::Air::Code::setEnableRCRS):
(JSC::B3::Air::Code::enableRCRS):
* b3/air/AirCustom.cpp:
(JSC::B3::Air::PatchCustom::isValidForm):
(JSC::B3::Air::CCallCustom::isValidForm):
* b3/air/AirCustom.h:
(JSC::B3::Air::PatchCustom::isValidFormStatic):
(JSC::B3::Air::PatchCustom::admitsStack):
(JSC::B3::Air::PatchCustom::isValidForm): Deleted.
* b3/air/AirEmitShuffle.cpp:
(JSC::B3::Air::ShufflePair::dump):
(JSC::B3::Air::createShuffle):
(JSC::B3::Air::emitShuffle):
* b3/air/AirEmitShuffle.h:
* b3/air/AirFixObviousSpills.cpp: Added.
(JSC::B3::Air::fixObviousSpills):
* b3/air/AirFixObviousSpills.h: Added.
* b3/air/AirFixSpillSlotZDef.h: Removed.
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::prepareForGeneration):
(JSC::B3::Air::generate):
* b3/air/AirHandleCalleeSaves.cpp:
(JSC::B3::Air::handleCalleeSaves):
* b3/air/AirInst.h:
* b3/air/AirInstInlines.h:
(JSC::B3::Air::Inst::reportUsedRegisters):
(JSC::B3::Air::Inst::admitsStack):
(JSC::B3::Air::isShiftValid):
* b3/air/AirIteratedRegisterCoalescing.cpp:
* b3/air/AirLiveness.h:
(JSC::B3::Air::AbstractLiveness::AbstractLiveness):
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin):
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end):
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains):
(JSC::B3::Air::AbstractLiveness::LocalCalc::live):
(JSC::B3::Air::AbstractLiveness::LocalCalc::isLive):
(JSC::B3::Air::AbstractLiveness::LocalCalc::execute):
(JSC::B3::Air::AbstractLiveness::rawLiveAtHead):
(JSC::B3::Air::AbstractLiveness::Iterable::begin):
(JSC::B3::Air::AbstractLiveness::Iterable::end):
(JSC::B3::Air::AbstractLiveness::Iterable::contains):
(JSC::B3::Air::AbstractLiveness::liveAtTail):
(JSC::B3::Air::AbstractLiveness::workset):
* b3/air/AirLogRegisterPressure.cpp: Added.
(JSC::B3::Air::logRegisterPressure):
* b3/air/AirLogRegisterPressure.h: Added.
* b3/air/AirOptimizeBlockOrder.cpp:
(JSC::B3::Air::blocksInOptimizedOrder):
(JSC::B3::Air::optimizeBlockOrder):
* b3/air/AirOptimizeBlockOrder.h:
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* b3/air/AirReportUsedRegisters.h:
* b3/air/AirSpillEverything.cpp:
(JSC::B3::Air::spillEverything):
* b3/air/AirStackSlot.h:
(JSC::B3::Air::StackSlot::isLocked):
(JSC::B3::Air::StackSlot::index):
(JSC::B3::Air::StackSlot::ensureSize):
(JSC::B3::Air::StackSlot::alignment):
* b3/air/AirValidate.cpp:
* ftl/FTLB3Compile.cpp:
(JSC::FTL::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithDiv):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
* jit/RegisterSet.h:
(JSC::RegisterSet::get):
(JSC::RegisterSet::setAll):
(JSC::RegisterSet::merge):
(JSC::RegisterSet::filter):
* runtime/Options.h:

Source/WTF:

* wtf/IndexSparseSet.h:
(WTF::IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet):
(WTF::IndexSparseSet&lt;OverflowHandler&gt;::add):
(WTF::IndexSparseSet&lt;OverflowHandler&gt;::remove):
* wtf/StringPrintStream.h:
(WTF::StringPrintStream::length):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CheckSpecialcpp">trunk/Source/JavaScriptCore/b3/B3CheckSpecial.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CheckSpecialh">trunk/Source/JavaScriptCore/b3/B3CheckSpecial.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3StackmapValueh">trunk/Source/JavaScriptCore/b3/B3StackmapValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackh">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirArgh">trunk/Source/JavaScriptCore/b3/air/AirArg.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirBasicBlockcpp">trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirBasicBlockh">trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCCallSpecialcpp">trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCodeh">trunk/Source/JavaScriptCore/b3/air/AirCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCustomcpp">trunk/Source/JavaScriptCore/b3/air/AirCustom.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCustomh">trunk/Source/JavaScriptCore/b3/air/AirCustom.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirEmitShufflecpp">trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirEmitShuffleh">trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirHandleCalleeSavescpp">trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInsth">trunk/Source/JavaScriptCore/b3/air/AirInst.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInstInlinesh">trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirIteratedRegisterCoalescingcpp">trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLivenessh">trunk/Source/JavaScriptCore/b3/air/AirLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOptimizeBlockOrdercpp">trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOptimizeBlockOrderh">trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp">trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirReportUsedRegistersh">trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp">trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirStackSloth">trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirValidatecpp">trunk/Source/JavaScriptCore/b3/air/AirValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Compilecpp">trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfCheckedArithmetich">trunk/Source/WTF/wtf/CheckedArithmetic.h</a></li>
<li><a href="#trunkSourceWTFwtfIndexSparseSeth">trunk/Source/WTF/wtf/IndexSparseSet.h</a></li>
<li><a href="#trunkSourceWTFwtfStringPrintStreamh">trunk/Source/WTF/wtf/StringPrintStream.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp">trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixObviousSpillsh">trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLogRegisterPressurecpp">trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLogRegisterPressureh">trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixSpillSlotZDefh">trunk/Source/JavaScriptCore/b3/air/AirFixSpillSlotZDef.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -78,6 +78,7 @@
</span><span class="cx">     b3/air/AirCustom.cpp
</span><span class="cx">     b3/air/AirEliminateDeadCode.cpp
</span><span class="cx">     b3/air/AirEmitShuffle.cpp
</span><ins>+    b3/air/AirFixObviousSpills.cpp
</ins><span class="cx">     b3/air/AirFixPartialRegisterStalls.cpp
</span><span class="cx">     b3/air/AirGenerate.cpp
</span><span class="cx">     b3/air/AirGenerated.cpp
</span><span class="lines">@@ -85,6 +86,7 @@
</span><span class="cx">     b3/air/AirInsertionSet.cpp
</span><span class="cx">     b3/air/AirInst.cpp
</span><span class="cx">     b3/air/AirIteratedRegisterCoalescing.cpp
</span><ins>+    b3/air/AirLogRegisterPressure.cpp
</ins><span class="cx">     b3/air/AirLowerAfterRegAlloc.cpp
</span><span class="cx">     b3/air/AirLowerMacros.cpp
</span><span class="cx">     b3/air/AirOptimizeBlockOrder.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,3 +1,166 @@
</span><ins>+2016-01-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 should be just as fast as FTL LLVM on Octane/crypto
+        https://bugs.webkit.org/show_bug.cgi?id=153113
+
+        Reviewed by Saam Barati.
+
+        This is the result of a hacking rampage to close the gap between FTL B3 and FTL LLVM on
+        Octane/crypto. It was a very successful rampage.
+
+        The biggest change in this patch is the introduction of a phase called fixObviousSpills()
+        that fixes patterns like:
+
+        Store register to stack slot and then use stack slot:
+            Move %rcx, (stack42)
+            Foo use:(stack42) // replace (stack42) with %rcx here.
+
+        Load stack slot into register and then use stack slot:
+            Move (stack42), %rcx
+            Foo use:(stack42) // replace (stack42) with %rcx here.
+
+        Store constant into stack slot and then use stack slot:
+            Move $42, %rcx
+            Move %rcx, (stack42)
+            Bar def:%rcx // %rcx isn't available anymore, but we still know that (stack42) is $42
+            Foo use:(stack42) // replace (stack42) with $42 here.
+
+        This phases does these fixups by doing a global forward flow that propagates sets of
+        must-aliases.
+
+        Also added a phase to report register pressure. It pretty-prints code alongside the set of
+        in-use registers above each instruction. Using this phase, I found that our register
+        allocator is actually doing a pretty awesome job. I had previously feared that we'd have to
+        make substantial changes to register allocation. I don't have such a fear anymore, at least
+        for Octane/crypto. In the future, we can check how the regalloc is performing just by
+        enabling logAirRegisterPressure.
+
+        Also fixed some FTL codegen pathologies. We were using bitOr where we meant to use a
+        conditional or. LLVM likes to canonicalize boolean expressions this way. B3, on the other
+        hand, doesn't do this canonicalization and doesn't have logic to decompose it into sequences
+        of branches.
+
+        Also added strength reductions for checked arithmetic. It turns out that LLVM learned how to
+        reduce checked multiply to unchecked multiply in some obvious cases that our existing DFG
+        optimizations lacked. Ideally, our DFG integer range optimization phase would cover this. But
+        the cases of interest were dead simple - the incoming values to the CheckMul were obviously
+        too small to cause overflow. I added such reasoning to B3's strength reduction.
+
+        Finally, this fixes some bugs with how we were handling subwidth spill slots. The register
+        allocator was making two mistakes. First, it might cause a Width64 def or use of a 4-byte
+        spill slot. In that case, it would extend the size of the spill slot to ensure that the use
+        or def is safe. Second, it emulates ZDef on Tmp behavior by emitting a Move32 to initialize
+        the high bits of a spill slot. But this is unsound because of the liveness semantics of spill
+        slots. They cannot have more than one def to initialize their value. I fixed that by making
+        allocateStack() be the thing that fixes ZDefs. That's a change to ZDef semantics: now, ZDef
+        on an anonymous stack slot means that the high bits are zero-filled. I wasn't able to
+        construct a test for this. It might be a hypothetical bug, but still, I like how this
+        simplifies the register allocator.
+
+        This is a ~0.7% speed-up on Octane.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3CheckSpecial.cpp:
+        (JSC::B3::CheckSpecial::hiddenBranch):
+        (JSC::B3::CheckSpecial::forEachArg):
+        (JSC::B3::CheckSpecial::commitHiddenBranch): Deleted.
+        * b3/B3CheckSpecial.h:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::fillStackmap):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3StackmapValue.h:
+        * b3/air/AirAllocateStack.cpp:
+        (JSC::B3::Air::allocateStack):
+        * b3/air/AirAllocateStack.h:
+        * b3/air/AirArg.h:
+        (JSC::B3::Air::Arg::callArg):
+        (JSC::B3::Air::Arg::stackAddr):
+        (JSC::B3::Air::Arg::isValidScale):
+        * b3/air/AirBasicBlock.cpp:
+        (JSC::B3::Air::BasicBlock::deepDump):
+        (JSC::B3::Air::BasicBlock::dumpHeader):
+        (JSC::B3::Air::BasicBlock::dumpFooter):
+        * b3/air/AirBasicBlock.h:
+        * b3/air/AirCCallSpecial.cpp:
+        (JSC::B3::Air::CCallSpecial::CCallSpecial):
+        (JSC::B3::Air::CCallSpecial::~CCallSpecial):
+        * b3/air/AirCode.h:
+        (JSC::B3::Air::Code::lastPhaseName):
+        (JSC::B3::Air::Code::setEnableRCRS):
+        (JSC::B3::Air::Code::enableRCRS):
+        * b3/air/AirCustom.cpp:
+        (JSC::B3::Air::PatchCustom::isValidForm):
+        (JSC::B3::Air::CCallCustom::isValidForm):
+        * b3/air/AirCustom.h:
+        (JSC::B3::Air::PatchCustom::isValidFormStatic):
+        (JSC::B3::Air::PatchCustom::admitsStack):
+        (JSC::B3::Air::PatchCustom::isValidForm): Deleted.
+        * b3/air/AirEmitShuffle.cpp:
+        (JSC::B3::Air::ShufflePair::dump):
+        (JSC::B3::Air::createShuffle):
+        (JSC::B3::Air::emitShuffle):
+        * b3/air/AirEmitShuffle.h:
+        * b3/air/AirFixObviousSpills.cpp: Added.
+        (JSC::B3::Air::fixObviousSpills):
+        * b3/air/AirFixObviousSpills.h: Added.
+        * b3/air/AirFixSpillSlotZDef.h: Removed.
+        * b3/air/AirGenerate.cpp:
+        (JSC::B3::Air::prepareForGeneration):
+        (JSC::B3::Air::generate):
+        * b3/air/AirHandleCalleeSaves.cpp:
+        (JSC::B3::Air::handleCalleeSaves):
+        * b3/air/AirInst.h:
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::Inst::reportUsedRegisters):
+        (JSC::B3::Air::Inst::admitsStack):
+        (JSC::B3::Air::isShiftValid):
+        * b3/air/AirIteratedRegisterCoalescing.cpp:
+        * b3/air/AirLiveness.h:
+        (JSC::B3::Air::AbstractLiveness::AbstractLiveness):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::live):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::isLive):
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::execute):
+        (JSC::B3::Air::AbstractLiveness::rawLiveAtHead):
+        (JSC::B3::Air::AbstractLiveness::Iterable::begin):
+        (JSC::B3::Air::AbstractLiveness::Iterable::end):
+        (JSC::B3::Air::AbstractLiveness::Iterable::contains):
+        (JSC::B3::Air::AbstractLiveness::liveAtTail):
+        (JSC::B3::Air::AbstractLiveness::workset):
+        * b3/air/AirLogRegisterPressure.cpp: Added.
+        (JSC::B3::Air::logRegisterPressure):
+        * b3/air/AirLogRegisterPressure.h: Added.
+        * b3/air/AirOptimizeBlockOrder.cpp:
+        (JSC::B3::Air::blocksInOptimizedOrder):
+        (JSC::B3::Air::optimizeBlockOrder):
+        * b3/air/AirOptimizeBlockOrder.h:
+        * b3/air/AirReportUsedRegisters.cpp:
+        (JSC::B3::Air::reportUsedRegisters):
+        * b3/air/AirReportUsedRegisters.h:
+        * b3/air/AirSpillEverything.cpp:
+        (JSC::B3::Air::spillEverything):
+        * b3/air/AirStackSlot.h:
+        (JSC::B3::Air::StackSlot::isLocked):
+        (JSC::B3::Air::StackSlot::index):
+        (JSC::B3::Air::StackSlot::ensureSize):
+        (JSC::B3::Air::StackSlot::alignment):
+        * b3/air/AirValidate.cpp:
+        * ftl/FTLB3Compile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithDiv):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::get):
+        (JSC::RegisterSet::setAll):
+        (JSC::RegisterSet::merge):
+        (JSC::RegisterSet::filter):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2016-01-19  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, undo unintended commit.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -379,7 +379,8 @@
</span><span class="cx">                 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F493AF816D0CAD10084508B /* SourceProvider.cpp */; };
</span><span class="cx">                 0F4B94DC17B9F07500DD03A4 /* TypedArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4B94DB17B9F07500DD03A4 /* TypedArrayInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F4C91661C29F4F2004341A6 /* B3OriginDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4C91651C29F4F2004341A6 /* B3OriginDump.h */; };
</span><del>-                0F4C91681C2B3D68004341A6 /* AirFixSpillSlotZDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */; };
</del><ins>+                0F4DE1CE1C4C1B54004D6C11 /* AirFixObviousSpills.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4DE1CC1C4C1B54004D6C11 /* AirFixObviousSpills.cpp */; };
+                0F4DE1CF1C4C1B54004D6C11 /* AirFixObviousSpills.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4DE1CD1C4C1B54004D6C11 /* AirFixObviousSpills.h */; };
</ins><span class="cx">                 0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4F29DD18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp */; };
</span><span class="cx">                 0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */; };
</span><span class="cx">                 0F50AF3C193E8B3900674EE8 /* DFGStructureClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F50AF3B193E8B3900674EE8 /* DFGStructureClobberState.h */; };
</span><span class="lines">@@ -724,6 +725,8 @@
</span><span class="cx">                 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
</span><span class="cx">                 0FE254F61ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE254F41ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp */; };
</span><span class="cx">                 0FE254F71ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE254F51ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h */; };
</span><ins>+                0FE34C191C4B39AE0003A512 /* AirLogRegisterPressure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE34C171C4B39AE0003A512 /* AirLogRegisterPressure.cpp */; };
+                0FE34C1A1C4B39AE0003A512 /* AirLogRegisterPressure.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE34C181C4B39AE0003A512 /* AirLogRegisterPressure.h */; };
</ins><span class="cx">                 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */; };
</span><span class="cx">                 0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE7211C193B9C590031F6ED /* DFGTransition.h */; };
</span><span class="cx">                 0FE834171A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */; };
</span><span class="lines">@@ -2542,7 +2545,8 @@
</span><span class="cx">                 0F493AF816D0CAD10084508B /* SourceProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProvider.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4B94DB17B9F07500DD03A4 /* TypedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrayInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4C91651C29F4F2004341A6 /* B3OriginDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3OriginDump.h; path = b3/B3OriginDump.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirFixSpillSlotZDef.h; path = b3/air/AirFixSpillSlotZDef.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                0F4DE1CC1C4C1B54004D6C11 /* AirFixObviousSpills.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirFixObviousSpills.cpp; path = b3/air/AirFixObviousSpills.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F4DE1CD1C4C1B54004D6C11 /* AirFixObviousSpills.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirFixObviousSpills.h; path = b3/air/AirFixObviousSpills.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F4F29DD18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStaticExecutionCountEstimationPhase.cpp; path = dfg/DFGStaticExecutionCountEstimationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStaticExecutionCountEstimationPhase.h; path = dfg/DFGStaticExecutionCountEstimationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F50AF3B193E8B3900674EE8 /* DFGStructureClobberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureClobberState.h; path = dfg/DFGStructureClobberState.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2900,6 +2904,8 @@
</span><span class="cx">                 0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE254F41ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVarargsForwardingPhase.cpp; path = dfg/DFGVarargsForwardingPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE254F51ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVarargsForwardingPhase.h; path = dfg/DFGVarargsForwardingPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FE34C171C4B39AE0003A512 /* AirLogRegisterPressure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLogRegisterPressure.cpp; path = b3/air/AirLogRegisterPressure.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FE34C181C4B39AE0003A512 /* AirLogRegisterPressure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLogRegisterPressure.h; path = b3/air/AirLogRegisterPressure.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGTransition.cpp; path = dfg/DFGTransition.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE7211C193B9C590031F6ED /* DFGTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGTransition.h; path = dfg/DFGTransition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicCallStubRoutine.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4859,9 +4865,10 @@
</span><span class="cx">                                 0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */,
</span><span class="cx">                                 0F6183231C45BF070072450B /* AirEmitShuffle.cpp */,
</span><span class="cx">                                 0F6183241C45BF070072450B /* AirEmitShuffle.h */,
</span><ins>+                                0F4DE1CC1C4C1B54004D6C11 /* AirFixObviousSpills.cpp */,
+                                0F4DE1CD1C4C1B54004D6C11 /* AirFixObviousSpills.h */,
</ins><span class="cx">                                 262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */,
</span><span class="cx">                                 262D85B51C0D650F006ACB61 /* AirFixPartialRegisterStalls.h */,
</span><del>-                                0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */,
</del><span class="cx">                                 0FEC85521BDACDC70080FF74 /* AirFrequentedBlock.h */,
</span><span class="cx">                                 0FEC85531BDACDC70080FF74 /* AirGenerate.cpp */,
</span><span class="cx">                                 0FEC85541BDACDC70080FF74 /* AirGenerate.h */,
</span><span class="lines">@@ -4877,6 +4884,8 @@
</span><span class="cx">                                 26718BA21BE99F780052017B /* AirIteratedRegisterCoalescing.cpp */,
</span><span class="cx">                                 26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */,
</span><span class="cx">                                 2684D4371C00161C0081D663 /* AirLiveness.h */,
</span><ins>+                                0FE34C171C4B39AE0003A512 /* AirLogRegisterPressure.cpp */,
+                                0FE34C181C4B39AE0003A512 /* AirLogRegisterPressure.h */,
</ins><span class="cx">                                 0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */,
</span><span class="cx">                                 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */,
</span><span class="cx">                                 0F6183271C45BF070072450B /* AirLowerMacros.cpp */,
</span><span class="lines">@@ -7326,7 +7335,6 @@
</span><span class="cx">                                 DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */,
</span><span class="cx">                                 0FBE0F7516C1DB0B0082C5E8 /* DFGPredictionInjectionPhase.h in Headers */,
</span><span class="cx">                                 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */,
</span><del>-                                0F4C91681C2B3D68004341A6 /* AirFixSpillSlotZDef.h in Headers */,
</del><span class="cx">                                 0F3E01AB19D353A500F61B7F /* DFGPrePostNumbering.h in Headers */,
</span><span class="cx">                                 0F2B9CED19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h in Headers */,
</span><span class="cx">                                 0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
</span><span class="lines">@@ -7357,6 +7365,7 @@
</span><span class="cx">                                 70B791991C024A29002481E2 /* GeneratorPrototype.h in Headers */,
</span><span class="cx">                                 0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */,
</span><span class="cx">                                 0FD8A32817D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.h in Headers */,
</span><ins>+                                0FE34C1A1C4B39AE0003A512 /* AirLogRegisterPressure.h in Headers */,
</ins><span class="cx">                                 0FD8A32A17D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h in Headers */,
</span><span class="cx">                                 0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */,
</span><span class="cx">                                 FE3A06B41C10CB9300390FDD /* JITBitXorGenerator.h in Headers */,
</span><span class="lines">@@ -7402,6 +7411,7 @@
</span><span class="cx">                                 0F3AC754188E5EC80032029F /* ExitingJITType.h in Headers */,
</span><span class="cx">                                 0FB105861675481200F8AB6E /* ExitKind.h in Headers */,
</span><span class="cx">                                 0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
</span><ins>+                                0F4DE1CF1C4C1B54004D6C11 /* AirFixObviousSpills.h in Headers */,
</ins><span class="cx">                                 A7A8AF3817ADB5F3005AB174 /* Float32Array.h in Headers */,
</span><span class="cx">                                 A7A8AF3917ADB5F3005AB174 /* Float64Array.h in Headers */,
</span><span class="cx">                                 0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */,
</span><span class="lines">@@ -8676,6 +8686,7 @@
</span><span class="cx">                                 0FEC856D1BDACDC70080FF74 /* AirAllocateStack.cpp in Sources */,
</span><span class="cx">                                 43422A661C16267500E2EB98 /* B3ReduceDoubleToFloat.cpp in Sources */,
</span><span class="cx">                                 0FEC856F1BDACDC70080FF74 /* AirArg.cpp in Sources */,
</span><ins>+                                0F4DE1CE1C4C1B54004D6C11 /* AirFixObviousSpills.cpp in Sources */,
</ins><span class="cx">                                 0FEC85711BDACDC70080FF74 /* AirBasicBlock.cpp in Sources */,
</span><span class="cx">                                 0FEC85731BDACDC70080FF74 /* AirCCallSpecial.cpp in Sources */,
</span><span class="cx">                                 0FEC85751BDACDC70080FF74 /* AirCode.cpp in Sources */,
</span><span class="lines">@@ -9091,6 +9102,7 @@
</span><span class="cx">                                 A593CF821840377100BFCE27 /* InspectorValues.cpp in Sources */,
</span><span class="cx">                                 147F39CF107EC37600427A48 /* InternalFunction.cpp in Sources */,
</span><span class="cx">                                 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */,
</span><ins>+                                0FE34C191C4B39AE0003A512 /* AirLogRegisterPressure.cpp in Sources */,
</ins><span class="cx">                                 A1B9E2391B4E0D6700BC7FED /* IntlCollator.cpp in Sources */,
</span><span class="cx">                                 A1B9E23B1B4E0D6700BC7FED /* IntlCollatorConstructor.cpp in Sources */,
</span><span class="cx">                                 A1B9E23D1B4E0D6700BC7FED /* IntlCollatorPrototype.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CheckSpecialcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CheckSpecial.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CheckSpecial.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/B3CheckSpecial.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -105,19 +105,14 @@
</span><span class="cx">     return hiddenBranch;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CheckSpecial::commitHiddenBranch(Inst&amp; original, Inst&amp; hiddenBranch)
-{
-    ASSERT(hiddenBranch.args.size() == m_numCheckArgs);
-    ASSERT(hiddenBranch.opcode = m_checkOpcode);
-    for (unsigned i = 0; i &lt; m_numCheckArgs; ++i)
-        original.args[i + 1] = hiddenBranch.args[i];
-}
-
</del><span class="cx"> void CheckSpecial::forEachArg(Inst&amp; inst, const ScopedLambda&lt;Inst::EachArgCallback&gt;&amp; callback)
</span><span class="cx"> {
</span><span class="cx">     Inst hidden = hiddenBranch(inst);
</span><del>-    hidden.forEachArg(callback);
-    commitHiddenBranch(inst, hidden);
</del><ins>+    hidden.forEachArg(
+        [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type type, Arg::Width width) {
+            unsigned index = &amp;arg - &amp;hidden.args[0];
+            callback(inst.args[1 + index], role, type, width);
+        });
</ins><span class="cx">     forEachArgImpl(numB3Args(inst), m_numCheckArgs + 1, inst, m_stackmapRole, callback);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CheckSpecialh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CheckSpecial.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CheckSpecial.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/B3CheckSpecial.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -123,9 +123,6 @@
</span><span class="cx">     // Constructs and returns the Inst representing the branch that this will use.
</span><span class="cx">     Air::Inst hiddenBranch(const Air::Inst&amp;) const;
</span><span class="cx"> 
</span><del>-    // If we edited the hidden branch, this installs the edits into the given inst.
-    void commitHiddenBranch(Air::Inst&amp; original, Air::Inst&amp; hiddenBranch);
-
</del><span class="cx">     void forEachArg(Air::Inst&amp;, const ScopedLambda&lt;Air::Inst::EachArgCallback&gt;&amp;) override;
</span><span class="cx">     bool isValid(Air::Inst&amp;) override;
</span><span class="cx">     bool admitsStack(Air::Inst&amp;, unsigned argIndex) override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -871,6 +871,7 @@
</span><span class="cx">                 arg = tmp(value.value());
</span><span class="cx">                 break;
</span><span class="cx">             case ValueRep::Register:
</span><ins>+                stackmap-&gt;earlyClobbered().clear(value.rep().reg());
</ins><span class="cx">                 arg = Tmp(value.rep().reg());
</span><span class="cx">                 append(Move, immOrTmp(value.value()), arg);
</span><span class="cx">                 break;
</span><span class="lines">@@ -1973,6 +1974,9 @@
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             fillStackmap(inst, patchpointValue, 0);
</span><ins>+            
+            if (patchpointValue-&gt;resultConstraint.isReg())
+                patchpointValue-&gt;lateClobbered().clear(patchpointValue-&gt;resultConstraint.reg());
</ins><span class="cx"> 
</span><span class="cx">             for (unsigned i = patchpointValue-&gt;numGPScratchRegisters; i--;)
</span><span class="cx">                 inst.args.append(m_code.newTmp(Arg::GP));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -84,6 +84,175 @@
</span><span class="cx"> 
</span><span class="cx"> bool verbose = false;
</span><span class="cx"> 
</span><ins>+class IntRange {
+public:
+    IntRange()
+    {
+    }
+
+    IntRange(int64_t min, int64_t max)
+        : m_min(min)
+        , m_max(max)
+    {
+    }
+
+    template&lt;typename T&gt;
+    static IntRange top()
+    {
+        return IntRange(std::numeric_limits&lt;T&gt;::min(), std::numeric_limits&lt;T&gt;::max());
+    }
+
+    static IntRange top(Type type)
+    {
+        switch (type) {
+        case Int32:
+            return top&lt;int32_t&gt;();
+        case Int64:
+            return top&lt;int64_t&gt;();
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return IntRange();
+        }
+    }
+
+    template&lt;typename T&gt;
+    static IntRange rangeForMask(T mask)
+    {
+        if (!(mask + 1))
+            return top&lt;T&gt;();
+        return IntRange(0, mask);
+    }
+
+    static IntRange rangeForMask(int64_t mask, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return rangeForMask&lt;int32_t&gt;(static_cast&lt;int32_t&gt;(mask));
+        case Int64:
+            return rangeForMask&lt;int64_t&gt;(mask);
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return IntRange();
+        }
+    }
+
+    template&lt;typename T&gt;
+    static IntRange rangeForZShr(int32_t shiftAmount)
+    {
+        typename std::make_unsigned&lt;T&gt;::type mask = 0;
+        mask--;
+        mask &gt;&gt;= shiftAmount;
+        return rangeForMask&lt;T&gt;(static_cast&lt;T&gt;(mask));
+    }
+
+    static IntRange rangeForZShr(int32_t shiftAmount, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return rangeForZShr&lt;int32_t&gt;(shiftAmount);
+        case Int64:
+            return rangeForZShr&lt;int64_t&gt;(shiftAmount);
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return IntRange();
+        }
+    }
+
+    template&lt;typename T&gt;
+    static IntRange rangeForSShr(int32_t shiftAmount)
+    {
+        return IntRange(top&lt;T&gt;().min() &gt;&gt; shiftAmount, top&lt;T&gt;().max() &gt;&gt; shiftAmount);
+    }
+
+    static IntRange rangeForSShr(int32_t shiftAmount, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return rangeForSShr&lt;int32_t&gt;(shiftAmount);
+        case Int64:
+            return rangeForSShr&lt;int64_t&gt;(shiftAmount);
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return IntRange();
+        }
+    }
+
+    int64_t min() const { return m_min; }
+    int64_t max() const { return m_max; }
+
+    void dump(PrintStream&amp; out) const
+    {
+        out.print(&quot;[&quot;, m_min, &quot;,&quot;, m_max, &quot;]&quot;);
+    }
+
+    template&lt;typename T&gt;
+    bool couldOverflowAdd(const IntRange&amp; other)
+    {
+        return sumOverflows&lt;T&gt;(m_min, other.m_min)
+            || sumOverflows&lt;T&gt;(m_min, other.m_max)
+            || sumOverflows&lt;T&gt;(m_max, other.m_min)
+            || sumOverflows&lt;T&gt;(m_max, other.m_max);
+    }
+
+    bool couldOverflowAdd(const IntRange&amp; other, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return couldOverflowAdd&lt;int32_t&gt;(other);
+        case Int64:
+            return couldOverflowAdd&lt;int64_t&gt;(other);
+        default:
+            return true;
+        }
+    }
+
+    template&lt;typename T&gt;
+    bool couldOverflowSub(const IntRange&amp; other)
+    {
+        return differenceOverflows&lt;T&gt;(m_min, other.m_min)
+            || differenceOverflows&lt;T&gt;(m_min, other.m_max)
+            || differenceOverflows&lt;T&gt;(m_max, other.m_min)
+            || differenceOverflows&lt;T&gt;(m_max, other.m_max);
+    }
+
+    bool couldOverflowSub(const IntRange&amp; other, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return couldOverflowSub&lt;int32_t&gt;(other);
+        case Int64:
+            return couldOverflowSub&lt;int64_t&gt;(other);
+        default:
+            return true;
+        }
+    }
+
+    template&lt;typename T&gt;
+    bool couldOverflowMul(const IntRange&amp; other)
+    {
+        return productOverflows&lt;T&gt;(m_min, other.m_min)
+            || productOverflows&lt;T&gt;(m_min, other.m_max)
+            || productOverflows&lt;T&gt;(m_max, other.m_min)
+            || productOverflows&lt;T&gt;(m_max, other.m_max);
+    }
+
+    bool couldOverflowMul(const IntRange&amp; other, Type type)
+    {
+        switch (type) {
+        case Int32:
+            return couldOverflowMul&lt;int32_t&gt;(other);
+        case Int64:
+            return couldOverflowMul&lt;int64_t&gt;(other);
+        default:
+            return true;
+        }
+    }
+
+private:
+    int64_t m_min { 0 };
+    int64_t m_max { 0 };
+};
+
</ins><span class="cx"> class ReduceStrength {
</span><span class="cx"> public:
</span><span class="cx">     ReduceStrength(Procedure&amp; proc)
</span><span class="lines">@@ -1091,7 +1260,7 @@
</span><span class="cx">                     m_value-&gt;child(1)-&gt;equalOrUnorderedConstant(m_value-&gt;child(0))));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case CheckAdd:
</del><ins>+        case CheckAdd: {
</ins><span class="cx">             if (replaceWithNewValue(m_value-&gt;child(0)-&gt;checkAddConstant(m_proc, m_value-&gt;child(1))))
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -1102,9 +1271,18 @@
</span><span class="cx">                 m_changed = true;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+
+            IntRange leftRange = rangeFor(m_value-&gt;child(0));
+            IntRange rightRange = rangeFor(m_value-&gt;child(1));
+            if (!leftRange.couldOverflowAdd(rightRange, m_value-&gt;type())) {
+                replaceWithNewValue(
+                    m_proc.add&lt;Value&gt;(Add, m_value-&gt;origin(), m_value-&gt;child(0), m_value-&gt;child(1)));
+                break;
+            }
</ins><span class="cx">             break;
</span><ins>+        }
</ins><span class="cx"> 
</span><del>-        case CheckSub:
</del><ins>+        case CheckSub: {
</ins><span class="cx">             if (replaceWithNewValue(m_value-&gt;child(0)-&gt;checkSubConstant(m_proc, m_value-&gt;child(1))))
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -1121,9 +1299,18 @@
</span><span class="cx">                 m_changed = true;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+
+            IntRange leftRange = rangeFor(m_value-&gt;child(0));
+            IntRange rightRange = rangeFor(m_value-&gt;child(1));
+            if (!leftRange.couldOverflowSub(rightRange, m_value-&gt;type())) {
+                replaceWithNewValue(
+                    m_proc.add&lt;Value&gt;(Sub, m_value-&gt;origin(), m_value-&gt;child(0), m_value-&gt;child(1)));
+                break;
+            }
</ins><span class="cx">             break;
</span><ins>+        }
</ins><span class="cx"> 
</span><del>-        case CheckMul:
</del><ins>+        case CheckMul: {
</ins><span class="cx">             if (replaceWithNewValue(m_value-&gt;child(0)-&gt;checkMulConstant(m_proc, m_value-&gt;child(1))))
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -1151,7 +1338,16 @@
</span><span class="cx">                 if (modified)
</span><span class="cx">                     break;
</span><span class="cx">             }
</span><ins>+
+            IntRange leftRange = rangeFor(m_value-&gt;child(0));
+            IntRange rightRange = rangeFor(m_value-&gt;child(1));
+            if (!leftRange.couldOverflowMul(rightRange, m_value-&gt;type())) {
+                replaceWithNewValue(
+                    m_proc.add&lt;Value&gt;(Mul, m_value-&gt;origin(), m_value-&gt;child(0), m_value-&gt;child(1)));
+                break;
+            }
</ins><span class="cx">             break;
</span><ins>+        }
</ins><span class="cx"> 
</span><span class="cx">         case Check: {
</span><span class="cx">             CheckValue* checkValue = m_value-&gt;as&lt;CheckValue&gt;();
</span><span class="lines">@@ -1294,6 +1490,37 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    IntRange rangeFor(Value* value)
+    {
+        switch (value-&gt;opcode()) {
+        case Const32:
+        case Const64: {
+            int64_t intValue = value-&gt;asInt();
+            return IntRange(intValue, intValue);
+        }
+
+        case BitAnd:
+            if (value-&gt;child(1)-&gt;hasInt())
+                return IntRange::rangeForMask(value-&gt;child(1)-&gt;asInt(), value-&gt;type());
+            break;
+
+        case SShr:
+            if (value-&gt;child(1)-&gt;hasInt32())
+                return IntRange::rangeForSShr(value-&gt;child(1)-&gt;asInt32(), value-&gt;type());
+            break;
+
+        case ZShr:
+            if (value-&gt;child(1)-&gt;hasInt32())
+                return IntRange::rangeForZShr(value-&gt;child(1)-&gt;asInt32(), value-&gt;type());
+            break;
+
+        default:
+            break;
+        }
+
+        return IntRange::top(value-&gt;type());
+    }
+
</ins><span class="cx">     template&lt;typename ValueType, typename... Arguments&gt;
</span><span class="cx">     void replaceWithNew(Arguments... arguments)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3StackmapValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3StackmapValue.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3StackmapValue.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/B3StackmapValue.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -187,6 +187,8 @@
</span><span class="cx">         clobberLate(set);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RegisterSet&amp; earlyClobbered() { return m_earlyClobbered; }
+    RegisterSet&amp; lateClobbered() { return m_lateClobbered; }
</ins><span class="cx">     const RegisterSet&amp; earlyClobbered() const { return m_earlyClobbered; }
</span><span class="cx">     const RegisterSet&amp; lateClobbered() const { return m_lateClobbered; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><ins>+#include &quot;AirInsertionSet.h&quot;
</ins><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><span class="lines">@@ -166,10 +167,49 @@
</span><span class="cx">         for (unsigned instIndex = block-&gt;size(); instIndex--;) {
</span><span class="cx">             if (verbose)
</span><span class="cx">                 dataLog(&quot;Analyzing: &quot;, block-&gt;at(instIndex), &quot;\n&quot;);
</span><ins>+
+            // Kill dead stores. For simplicity we say that a store is killable if it has only late
+            // defs and those late defs are to things that are dead right now. We only do that
+            // because that's the only kind of dead stack store we will see here.
+            Inst&amp; inst = block-&gt;at(instIndex);
+            if (!inst.hasNonArgEffects()) {
+                bool ok = true;
+                inst.forEachArg(
+                    [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type, Arg::Width) {
+                        if (Arg::isEarlyDef(role)) {
+                            ok = false;
+                            return;
+                        }
+                        if (!Arg::isLateDef(role))
+                            return;
+                        if (!arg.isStack()) {
+                            ok = false;
+                            return;
+                        }
+                        StackSlot* slot = arg.stackSlot();
+                        if (slot-&gt;kind() != StackSlotKind::Anonymous) {
+                            ok = false;
+                            return;
+                        }
+
+                        if (localCalc.isLive(slot)) {
+                            ok = false;
+                            return;
+                        }
+                    });
+                if (ok)
+                    inst = Inst();
+            }
+            
</ins><span class="cx">             interfere(instIndex);
</span><span class="cx">             localCalc.execute(instIndex);
</span><span class="cx">         }
</span><span class="cx">         interfere(-1);
</span><ins>+        
+        block-&gt;insts().removeAllMatching(
+            [&amp;] (const Inst&amp; inst) -&gt; bool {
+                return !inst;
+            });
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (verbose) {
</span><span class="lines">@@ -232,33 +272,43 @@
</span><span class="cx">     // We would have to scavenge for temporaries if this happened. Fortunately, this case will be
</span><span class="cx">     // extremely rare so we can do crazy things when it arises.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=152530
</span><del>-    
</del><ins>+
+    InsertionSet insertionSet(code);
</ins><span class="cx">     for (BasicBlock* block : code) {
</span><del>-        for (Inst&amp; inst : *block) {
</del><ins>+        for (unsigned instIndex = 0; instIndex &lt; block-&gt;size(); ++instIndex) {
+            Inst&amp; inst = block-&gt;at(instIndex);
</ins><span class="cx">             inst.forEachArg(
</span><del>-                [&amp;] (Arg&amp; arg, Arg::Role, Arg::Type, Arg::Width width)
-                {
</del><ins>+                [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type, Arg::Width width) {
+                    auto stackAddr = [&amp;] (int32_t offset) -&gt; Arg {
+                        return Arg::stackAddr(offset, code.frameSize(), width);
+                    };
+                    
</ins><span class="cx">                     switch (arg.kind()) {
</span><span class="cx">                     case Arg::Stack: {
</span><del>-                        arg = Arg::addr(
-                            Tmp(GPRInfo::callFrameRegister),
-                            arg.offset() + arg.stackSlot()-&gt;offsetFromFP());
-                        if (!arg.isValidForm(width)) {
-                            arg = Arg::addr(
-                                Tmp(MacroAssembler::stackPointerRegister),
-                                arg.offset() + code.frameSize());
</del><ins>+                        StackSlot* slot = arg.stackSlot();
+                        if (Arg::isZDef(role)
+                            &amp;&amp; slot-&gt;kind() == StackSlotKind::Anonymous
+                            &amp;&amp; slot-&gt;byteSize() &gt; Arg::bytes(width)) {
+                            // Currently we only handle this simple case because it's the only one
+                            // that arises: ZDef's are only 32-bit right now. So, when we hit these
+                            // assertions it means that we need to implement those other kinds of
+                            // zero fills.
+                            RELEASE_ASSERT(slot-&gt;byteSize() == 8);
+                            RELEASE_ASSERT(width == Arg::Width32);
+
+                            // We rely on the fact that there must be some way to move zero to a
+                            // memory location without first burning a register. On ARM, we would do
+                            // this using zr.
+                            RELEASE_ASSERT(isValidForm(Move32, Arg::Imm, Arg::Addr));
+                            insertionSet.insert(
+                                instIndex + 1, Move32, inst.origin, Arg::imm(0),
+                                stackAddr(arg.offset() + 4 + slot-&gt;offsetFromFP()));
</ins><span class="cx">                         }
</span><ins>+                        arg = stackAddr(arg.offset() + slot-&gt;offsetFromFP());
</ins><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                     case Arg::CallArg:
</span><del>-                        arg = Arg::addr(
-                            Tmp(GPRInfo::callFrameRegister),
-                            arg.offset() - code.frameSize());
-                        if (!arg.isValidForm(width)) {
-                            arg = Arg::addr(
-                                Tmp(MacroAssembler::stackPointerRegister),
-                                arg.offset() + code.frameSize());
-                        }
</del><ins>+                        arg = stackAddr(arg.offset() - code.frameSize());
</ins><span class="cx">                         break;
</span><span class="cx">                     default:
</span><span class="cx">                         break;
</span><span class="lines">@@ -266,6 +316,7 @@
</span><span class="cx">                 }
</span><span class="cx">             );
</span><span class="cx">         }
</span><ins>+        insertionSet.execute(block);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,7 +33,9 @@
</span><span class="cx"> class Code;
</span><span class="cx"> 
</span><span class="cx"> // This allocates StackSlots to places on the stack. It first allocates the pinned ones in index
</span><del>-// order and then it allocates the rest using first fit.
</del><ins>+// order and then it allocates the rest using first fit. Takes the opportunity to kill dead
+// assignments to stack slots, since it knows which ones are live. Also fixes ZDefs to anonymous
+// stack slots.
</ins><span class="cx"> 
</span><span class="cx"> void allocateStack(Code&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirArgh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirArg.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirArg.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirArg.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -126,6 +126,7 @@
</span><span class="cx">         // depending on the kind of the argument:
</span><span class="cx">         //
</span><span class="cx">         // For register: the upper bits are zero-filled.
</span><ins>+        // For anonymous stack slot: the upper bits are zero-filled.
</ins><span class="cx">         // For address: the upper bits are not touched (i.e. we do a 32-bit store in our example).
</span><span class="cx">         // For tmp: either the upper bits are not touched or they are zero-filled, and we won't know
</span><span class="cx">         // which until we lower the tmp to either a StackSlot or a Reg.
</span><span class="lines">@@ -513,6 +514,17 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static Arg stackAddr(int32_t offsetFromFP, unsigned frameSize, Width width)
+    {
+        Arg result = Arg::addr(Air::Tmp(GPRInfo::callFrameRegister), offsetFromFP);
+        if (!result.isValidForm(width)) {
+            result = Arg::addr(
+                Air::Tmp(MacroAssembler::stackPointerRegister),
+                offsetFromFP + frameSize);
+        }
+        return result;
+    }
+
</ins><span class="cx">     // If you don't pass a Width, this optimistically assumes that you're using the right width.
</span><span class="cx">     static bool isValidScale(unsigned scale, Optional&lt;Width&gt; width = Nullopt)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirBasicBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -57,11 +57,21 @@
</span><span class="cx"> 
</span><span class="cx"> void BasicBlock::deepDump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><ins>+    dumpHeader(out);
+    for (const Inst&amp; inst : *this)
+        out.print(&quot;    &quot;, inst, &quot;\n&quot;);
+    dumpFooter(out);
+}
+
+void BasicBlock::dumpHeader(PrintStream&amp; out) const
+{
</ins><span class="cx">     out.print(&quot;BB&quot;, *this, &quot;: ; frequency = &quot;, m_frequency, &quot;\n&quot;);
</span><span class="cx">     if (predecessors().size())
</span><span class="cx">         out.print(&quot;  Predecessors: &quot;, pointerListDump(predecessors()), &quot;\n&quot;);
</span><del>-    for (const Inst&amp; inst : *this)
-        out.print(&quot;    &quot;, inst, &quot;\n&quot;);
</del><ins>+}
+
+void BasicBlock::dumpFooter(PrintStream&amp; out) const
+{
</ins><span class="cx">     if (successors().size())
</span><span class="cx">         out.print(&quot;  Successors: &quot;, listDump(successors()), &quot;\n&quot;);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+class BlockInsertionSet;
</ins><span class="cx"> class Code;
</span><span class="cx"> class InsertionSet;
</span><span class="cx"> 
</span><span class="lines">@@ -126,7 +127,11 @@
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void deepDump(PrintStream&amp;) const;
</span><span class="cx"> 
</span><ins>+    void dumpHeader(PrintStream&amp;) const;
+    void dumpFooter(PrintStream&amp;) const;
+
</ins><span class="cx"> private:
</span><ins>+    friend class BlockInsertionSet;
</ins><span class="cx">     friend class Code;
</span><span class="cx">     friend class InsertionSet;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCCallSpecialcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -36,6 +36,9 @@
</span><span class="cx">     m_clobberedRegs.exclude(RegisterSet::stackRegisters());
</span><span class="cx">     m_clobberedRegs.exclude(RegisterSet::reservedHardwareRegisters());
</span><span class="cx">     m_clobberedRegs.exclude(RegisterSet::calleeSaveRegisters());
</span><ins>+    m_clobberedRegs.clear(GPRInfo::returnValueGPR);
+    m_clobberedRegs.clear(GPRInfo::returnValueGPR2);
+    m_clobberedRegs.clear(FPRInfo::returnValueFPR);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CCallSpecial::~CCallSpecial()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCode.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCode.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirCode.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Air {
</span><span class="cx"> 
</span><ins>+class BlockInsertionSet;
</ins><span class="cx"> class CCallSpecial;
</span><span class="cx"> 
</span><span class="cx"> // This is an IR that is very close to the bare metal. It requires about 40x more bytes than the
</span><span class="lines">@@ -324,6 +325,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ::JSC::B3::Procedure;
</span><ins>+    friend class BlockInsertionSet;
</ins><span class="cx">     
</span><span class="cx">     Code(Procedure&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCustom.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCustom.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirCustom.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -28,11 +28,35 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirInstInlines.h&quot;
</ins><span class="cx"> #include &quot;B3CCallValue.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+bool PatchCustom::isValidForm(Inst&amp; inst)
+{
+    if (inst.args.size() &lt; 1)
+        return false;
+    if (!inst.args[0].isSpecial())
+        return false;
+    if (!inst.args[0].special()-&gt;isValid(inst))
+        return false;
+    RegisterSet clobberedEarly = inst.extraEarlyClobberedRegs();
+    RegisterSet clobberedLate = inst.extraClobberedRegs();
+    bool ok = true;
+    inst.forEachTmp(
+        [&amp;] (Tmp&amp; tmp, Arg::Role role, Arg::Type, Arg::Width) {
+            if (!tmp.isReg())
+                return;
+            if (Arg::isLateDef(role) || Arg::isLateUse(role))
+                ok &amp;= !clobberedLate.get(tmp.reg());
+            else
+                ok &amp;= !clobberedEarly.get(tmp.reg());
+        });
+    return ok;
+}
+
</ins><span class="cx"> bool CCallCustom::isValidForm(Inst&amp; inst)
</span><span class="cx"> {
</span><span class="cx">     CCallValue* value = inst.origin-&gt;as&lt;CCallValue&gt;();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCustomh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCustom.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCustom.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirCustom.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -71,14 +71,7 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static bool isValidForm(Inst&amp; inst)
-    {
-        if (inst.args.size() &lt; 1)
-            return false;
-        if (!inst.args[0].isSpecial())
-            return false;
-        return inst.args[0].special()-&gt;isValid(inst);
-    }
</del><ins>+    static bool isValidForm(Inst&amp; inst);
</ins><span class="cx"> 
</span><span class="cx">     static bool admitsStack(Inst&amp; inst, unsigned argIndex)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirEmitShufflecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -70,6 +70,14 @@
</span><span class="cx">     out.print(width(), &quot;:&quot;, src(), &quot;=&gt;&quot;, dst());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Inst createShuffle(Value* origin, const Vector&lt;ShufflePair&gt;&amp; pairs)
+{
+    Inst result(Shuffle, origin);
+    for (const ShufflePair&amp; pair : pairs)
+        result.append(pair.src(), pair.dst(), Arg::widthArg(pair.width()));
+    return result;
+}
+
</ins><span class="cx"> Vector&lt;Inst&gt; emitShuffle(
</span><span class="cx">     Vector&lt;ShufflePair&gt; pairs, std::array&lt;Arg, 2&gt; scratches, Arg::Type type, Value* origin)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirEmitShuffleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -66,6 +66,9 @@
</span><span class="cx">     Arg::Width m_width { Arg::Width8 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// Create a Shuffle instruction.
+Inst createShuffle(Value* origin, const Vector&lt;ShufflePair&gt;&amp;);
+
</ins><span class="cx"> // Perform a shuffle of a given type. The scratch argument is mandatory. You should pass it as
</span><span class="cx"> // follows: If you know that you have scratch registers or temporaries available - that is, they're
</span><span class="cx"> // registers that are not mentioned in the shuffle, have the same type as the shuffle, and are not
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp (0 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -0,0 +1,515 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;AirFixObviousSpills.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirCode.h&quot;
+#include &quot;AirInstInlines.h&quot;
+#include &quot;AirPhaseScope.h&quot;
+#include &quot;B3IndexMap.h&quot;
+#include &lt;wtf/ListDump.h&gt;
+
+namespace JSC { namespace B3 { namespace Air {
+
+namespace {
+
+bool verbose = false;
+
+class FixObviousSpills {
+public:
+    FixObviousSpills(Code&amp; code)
+        : m_code(code)
+        , m_atHead(code.size())
+    {
+    }
+
+    void run()
+    {
+        if (verbose)
+            dataLog(&quot;Code before fixObviousSpills:\n&quot;, m_code);
+        
+        computeAliases();
+        fixCode();
+    }
+
+private:
+    void computeAliases()
+    {
+        m_atHead[m_code[0]].wasVisited = true;
+        
+        bool changed = true;
+        while (changed) {
+            changed = false;
+            
+            for (BasicBlock* block : m_code) {
+                m_block = block;
+                m_state = m_atHead[block];
+                if (!m_state.wasVisited)
+                    continue;
+
+                if (verbose)
+                    dataLog(&quot;Executing block &quot;, *m_block, &quot;: &quot;, m_state, &quot;\n&quot;);
+                
+                for (m_instIndex = 0; m_instIndex &lt; block-&gt;size(); ++m_instIndex)
+                    executeInst();
+
+                for (BasicBlock* successor : block-&gt;successorBlocks()) {
+                    State&amp; toState = m_atHead[successor];
+                    if (toState.wasVisited)
+                        changed |= toState.merge(m_state);
+                    else {
+                        toState = m_state;
+                        changed = true;
+                    }
+                }
+            }
+        }
+    }
+
+    void fixCode()
+    {
+        for (BasicBlock* block : m_code) {
+            m_block = block;
+            m_state = m_atHead[block];
+            RELEASE_ASSERT(m_state.wasVisited);
+
+            for (m_instIndex = 0; m_instIndex &lt; block-&gt;size(); ++m_instIndex) {
+                fixInst();
+                executeInst();
+            }
+        }
+    }
+
+    void executeInst()
+    {
+        Inst&amp; inst = m_block-&gt;at(m_instIndex);
+
+        if (verbose)
+            dataLog(&quot;    Executing &quot;, inst, &quot;: &quot;, m_state, &quot;\n&quot;);
+
+        Inst::forEachDefWithExtraClobberedRegs&lt;Arg&gt;(
+            &amp;inst, &amp;inst,
+            [&amp;] (const Arg&amp; arg, Arg::Role, Arg::Type, Arg::Width) {
+                if (verbose)
+                    dataLog(&quot;        Clobbering &quot;, arg, &quot;\n&quot;);
+                m_state.clobber(arg);
+            });
+
+        // FIXME: This needs a story for floats and doubles.
+        // https://bugs.webkit.org/show_bug.cgi?id=153197
+
+        switch (inst.opcode) {
+        case Move:
+            if (inst.args[0].isSomeImm()) {
+                if (inst.args[1].isReg())
+                    m_state.addAlias(RegConst(inst.args[1].reg(), inst.args[0].value()));
+                else if (isSpillSlot(inst.args[1]))
+                    m_state.addAlias(SlotConst(inst.args[1].stackSlot(), inst.args[0].value()));
+            } else if (isSpillSlot(inst.args[0]) &amp;&amp; inst.args[1].isReg()) {
+                if (Optional&lt;int64_t&gt; constant = m_state.constantFor(inst.args[0]))
+                    m_state.addAlias(RegConst(inst.args[1].reg(), *constant));
+                m_state.addAlias(
+                    RegSlot(inst.args[1].reg(), inst.args[0].stackSlot(), RegSlot::AllBits));
+            } else if (inst.args[0].isReg() &amp;&amp; isSpillSlot(inst.args[1])) {
+                if (Optional&lt;int64_t&gt; constant = m_state.constantFor(inst.args[0]))
+                    m_state.addAlias(SlotConst(inst.args[1].stackSlot(), *constant));
+                m_state.addAlias(
+                    RegSlot(inst.args[0].reg(), inst.args[1].stackSlot(), RegSlot::AllBits));
+            }
+            break;
+
+        case Move32:
+            if (inst.args[0].isSomeImm()) {
+                if (inst.args[1].isReg())
+                    m_state.addAlias(RegConst(inst.args[1].reg(), static_cast&lt;uint32_t&gt;(inst.args[0].value())));
+                else if (isSpillSlot(inst.args[1]))
+                    m_state.addAlias(SlotConst(inst.args[1].stackSlot(), static_cast&lt;uint32_t&gt;(inst.args[0].value())));
+            } else if (isSpillSlot(inst.args[0]) &amp;&amp; inst.args[1].isReg()) {
+                if (Optional&lt;int64_t&gt; constant = m_state.constantFor(inst.args[0]))
+                    m_state.addAlias(RegConst(inst.args[1].reg(), static_cast&lt;uint32_t&gt;(*constant)));
+                m_state.addAlias(
+                    RegSlot(inst.args[1].reg(), inst.args[0].stackSlot(), RegSlot::ZExt32));
+            } else if (inst.args[0].isReg() &amp;&amp; isSpillSlot(inst.args[1])) {
+                if (Optional&lt;int64_t&gt; constant = m_state.constantFor(inst.args[0]))
+                    m_state.addAlias(SlotConst(inst.args[1].stackSlot(), static_cast&lt;int32_t&gt;(*constant)));
+                m_state.addAlias(
+                    RegSlot(inst.args[0].reg(), inst.args[1].stackSlot(), RegSlot::Match32));
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    void fixInst()
+    {
+        Inst&amp; inst = m_block-&gt;at(m_instIndex);
+
+        if (verbose)
+            dataLog(&quot;Fixing inst &quot;, inst, &quot;: &quot;, m_state, &quot;\n&quot;);
+
+        // Create a copy in case we invalidate the instruction. That doesn't happen often.
+        Inst instCopy = inst;
+
+        // The goal is to replace references to stack slots. We only care about early uses. We can't
+        // handle UseDefs. We could teach this to handle UseDefs if we inserted a store instruction
+        // after and we proved that the register aliased to the stack slot dies here. We can get that
+        // information from the liveness analysis. We also can't handle late uses, because we don't
+        // look at late clobbers when doing this.
+        bool didThings = false;
+        auto handleArg = [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type, Arg::Width width) {
+            if (!isSpillSlot(arg))
+                return;
+            if (!Arg::isEarlyUse(role))
+                return;
+            if (Arg::isAnyDef(role))
+                return;
+            
+            // Try to get a register if at all possible.
+            if (const RegSlot* alias = m_state.getRegSlot(arg.stackSlot())) {
+                switch (width) {
+                case Arg::Width64:
+                    if (alias-&gt;mode != RegSlot::AllBits)
+                        return;
+                    if (verbose)
+                        dataLog(&quot;    Replacing &quot;, arg, &quot; with &quot;, alias-&gt;reg, &quot;\n&quot;);
+                    arg = Tmp(alias-&gt;reg);
+                    didThings = true;
+                    return;
+                case Arg::Width32:
+                    if (verbose)
+                        dataLog(&quot;    Replacing &quot;, arg, &quot; with &quot;, alias-&gt;reg, &quot; (subwidth case)\n&quot;);
+                    arg = Tmp(alias-&gt;reg);
+                    didThings = true;
+                    return;
+                default:
+                    return;
+                }
+            }
+
+            // Revert to immediate if that didn't work.
+            if (const SlotConst* alias = m_state.getSlotConst(arg.stackSlot())) {
+                if (verbose)
+                    dataLog(&quot;    Replacing &quot;, arg, &quot; with constant &quot;, alias-&gt;constant, &quot;\n&quot;);
+                if (Arg::isValidImmForm(alias-&gt;constant))
+                    arg = Arg::imm(alias-&gt;constant);
+                else
+                    arg = Arg::imm64(alias-&gt;constant);
+                didThings = true;
+                return;
+            }
+        };
+        
+        inst.forEachArg(handleArg);
+        if (!didThings || inst.isValidForm())
+            return;
+        
+        // We introduced something invalid along the way. Back up and carefully handle each argument.
+        inst = instCopy;
+        ASSERT(inst.isValidForm());
+        inst.forEachArg(
+            [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type type, Arg::Width width) {
+                Arg argCopy = arg;
+                handleArg(arg, role, type, width);
+                if (!inst.isValidForm())
+                    arg = argCopy;
+            });
+    }
+    
+    static bool isSpillSlot(const Arg&amp; arg)
+    {
+        return arg.isStack() &amp;&amp; !arg.stackSlot()-&gt;isLocked();
+    }
+    
+    struct RegConst {
+        RegConst()
+        {
+        }
+        
+        RegConst(Reg reg, int64_t constant)
+            : reg(reg)
+            , constant(constant)
+        {
+        }
+
+        explicit operator bool() const
+        {
+            return !!reg;
+        }
+
+        void dump(PrintStream&amp; out) const
+        {
+            out.print(reg, &quot;-&gt;&quot;, constant);
+        }
+        
+        Reg reg;
+        int64_t constant { 0 };
+    };
+
+    struct RegSlot {
+        enum Mode : int8_t {
+            AllBits,
+            ZExt32, // Register contains zero-extended contents of stack slot.
+            Match32 // Low 32 bits of register match low 32 bits of stack slot.
+        };
+        
+        RegSlot()
+        {
+        }
+
+        RegSlot(Reg reg, StackSlot* slot, Mode mode)
+            : slot(slot)
+            , reg(reg)
+            , mode(mode)
+        {
+        }
+
+        explicit operator bool() const
+        {
+            return slot &amp;&amp; reg;
+        }
+
+        void dump(PrintStream&amp; out) const
+        {
+            out.print(pointerDump(slot), &quot;-&gt;&quot;, reg);
+            switch (mode) {
+            case AllBits:
+                out.print(&quot;(AllBits)&quot;);
+                break;
+            case ZExt32:
+                out.print(&quot;(ZExt32)&quot;);
+                break;
+            case Match32:
+                out.print(&quot;(Match32)&quot;);
+                break;
+            }
+        }
+        
+        StackSlot* slot { nullptr };
+        Reg reg;
+        Mode mode { AllBits };
+    };
+
+    struct SlotConst {
+        SlotConst()
+        {
+        }
+
+        SlotConst(StackSlot* slot, int64_t constant)
+            : slot(slot)
+            , constant(constant)
+        {
+        }
+
+        explicit operator bool() const
+        {
+            return slot;
+        }
+
+        void dump(PrintStream&amp; out) const
+        {
+            out.print(pointerDump(slot), &quot;-&gt;&quot;, constant);
+        }
+        
+        StackSlot* slot { nullptr };
+        int64_t constant { 0 };
+    };
+
+    struct State {
+        void addAlias(const RegConst&amp; newAlias)
+        {
+            regConst.append(newAlias);
+        }
+        void addAlias(const RegSlot&amp; newAlias)
+        {
+            regSlot.append(newAlias);
+        }
+        void addAlias(const SlotConst&amp; newAlias)
+        {
+            slotConst.append(newAlias);
+        }
+
+        const RegConst* getRegConst(Reg reg) const
+        {
+            for (const RegConst&amp; alias : regConst) {
+                if (alias.reg == reg)
+                    return &amp;alias;
+            }
+            return nullptr;
+        }
+
+        const RegSlot* getRegSlot(Reg reg) const
+        {
+            for (const RegSlot&amp; alias : regSlot) {
+                if (alias.reg == reg)
+                    return &amp;alias;
+            }
+            return nullptr;
+        }
+
+        const RegSlot* getRegSlot(StackSlot* slot) const
+        {
+            for (const RegSlot&amp; alias : regSlot) {
+                if (alias.slot == slot)
+                    return &amp;alias;
+            }
+            return nullptr;
+        }
+
+        const RegSlot* getRegSlot(Reg reg, StackSlot* slot) const
+        {
+            for (const RegSlot&amp; alias : regSlot) {
+                if (alias.reg == reg &amp;&amp; alias.slot == slot)
+                    return &amp;alias;
+            }
+            return nullptr;
+        }
+
+        const SlotConst* getSlotConst(StackSlot* slot) const
+        {
+            for (const SlotConst&amp; alias : slotConst) {
+                if (alias.slot == slot)
+                    return &amp;alias;
+            }
+            return nullptr;
+        }
+
+        Optional&lt;int64_t&gt; constantFor(const Arg&amp; arg)
+        {
+            if (arg.isReg()) {
+                if (const RegConst* alias = getRegConst(arg.reg()))
+                    return alias-&gt;constant;
+                return Nullopt;
+            }
+            if (arg.isStack()) {
+                if (const SlotConst* alias = getSlotConst(arg.stackSlot()))
+                    return alias-&gt;constant;
+                return Nullopt;
+            }
+            return Nullopt;
+        }
+
+        void clobber(const Arg&amp; arg)
+        {
+            if (arg.isReg()) {
+                regConst.removeAllMatching(
+                    [&amp;] (const RegConst&amp; alias) -&gt; bool {
+                        return alias.reg == arg.reg();
+                    });
+                regSlot.removeAllMatching(
+                    [&amp;] (const RegSlot&amp; alias) -&gt; bool {
+                        return alias.reg == arg.reg();
+                    });
+                return;
+            }
+            if (arg.isStack()) {
+                slotConst.removeAllMatching(
+                    [&amp;] (const SlotConst&amp; alias) -&gt; bool {
+                        return alias.slot == arg.stackSlot();
+                    });
+                regSlot.removeAllMatching(
+                    [&amp;] (const RegSlot&amp; alias) -&gt; bool {
+                        return alias.slot == arg.stackSlot();
+                    });
+            }
+        }
+
+        bool merge(const State&amp; other)
+        {
+            bool changed = false;
+            
+            changed |= !!regConst.removeAllMatching(
+                [&amp;] (RegConst&amp; alias) -&gt; bool {
+                    const RegConst* otherAlias = other.getRegConst(alias.reg);
+                    if (!otherAlias)
+                        return true;
+                    if (alias.constant != otherAlias-&gt;constant)
+                        return true;
+                    return false;
+                });
+
+            changed |= !!slotConst.removeAllMatching(
+                [&amp;] (SlotConst&amp; alias) -&gt; bool {
+                    const SlotConst* otherAlias = other.getSlotConst(alias.slot);
+                    if (!otherAlias)
+                        return true;
+                    if (alias.constant != otherAlias-&gt;constant)
+                        return true;
+                    return false;
+                });
+
+            changed |= !!regSlot.removeAllMatching(
+                [&amp;] (RegSlot&amp; alias) -&gt; bool {
+                    const RegSlot* otherAlias = other.getRegSlot(alias.reg, alias.slot);
+                    if (!otherAlias)
+                        return true;
+                    if (alias.mode != RegSlot::Match32 &amp;&amp; alias.mode != otherAlias-&gt;mode) {
+                        alias.mode = RegSlot::Match32;
+                        changed = true;
+                    }
+                    return false;
+                });
+
+            return changed;
+        }
+
+        void dump(PrintStream&amp; out) const
+        {
+            out.print(
+                &quot;{regConst = [&quot;, listDump(regConst), &quot;], slotConst = [&quot;, listDump(slotConst),
+                &quot;], regSlot = [&quot;, listDump(regSlot), &quot;], wasVisited = &quot;, wasVisited, &quot;}&quot;);
+        }
+
+        Vector&lt;RegConst&gt; regConst;
+        Vector&lt;SlotConst&gt; slotConst;
+        Vector&lt;RegSlot&gt; regSlot;
+        bool wasVisited { false };
+    };
+
+    Code&amp; m_code;
+    IndexMap&lt;BasicBlock, State&gt; m_atHead;
+    State m_state;
+    BasicBlock* m_block { nullptr };
+    unsigned m_instIndex { 0 };
+};
+
+} // anonymous namespace
+
+void fixObviousSpills(Code&amp; code)
+{
+    PhaseScope phaseScope(code, &quot;fixObviousSpills&quot;);
+
+    FixObviousSpills fixObviousSpills(code);
+    fixObviousSpills.run();
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixObviousSpillsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.h (0 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AirFixObviousSpills_h
+#define AirFixObviousSpills_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// This is a forward flow phase that tracks equivalence between spills slots and registers. It
+// removes loads from spill slots in cases when the contents of the spill slot can be found in (or
+// computed from) a register.
+void fixObviousSpills(Code&amp;);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+#endif // AirFixObviousSpills_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixSpillSlotZDefh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/air/AirFixSpillSlotZDef.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixSpillSlotZDef.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixSpillSlotZDef.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,78 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef AirFixSpillSlotZDef_h
-#define AirFixSpillSlotZDef_h
-
-#include &quot;AirCode.h&quot;
-#include &quot;AirInsertionSet.h&quot;
-#include &quot;AirInstInlines.h&quot;
-
-namespace JSC { namespace B3 { namespace Air {
-
-template&lt;typename IsSpillSlot&gt;
-void fixSpillSlotZDef(Code&amp; code, const IsSpillSlot&amp; isSpillSlot)
-{
-    // We could have introduced ZDef's to StackSlots that are wider than the def. In that case, we
-    // need to emit code to zero-fill the top bits of the StackSlot.
-    InsertionSet insertionSet(code);
-    for (BasicBlock* block : code) {
-        for (unsigned instIndex = 0; instIndex &lt; block-&gt;size(); ++instIndex) {
-            Inst&amp; inst = block-&gt;at(instIndex);
-
-            inst.forEachArg(
-                [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type, Arg::Width width) {
-                    if (!Arg::isZDef(role))
-                        return;
-                    if (!arg.isStack())
-                        return;
-                    if (!isSpillSlot(arg.stackSlot()))
-                        return;
-                    if (arg.stackSlot()-&gt;byteSize() == Arg::bytes(width))
-                        return;
-
-                    // Currently we only handle this simple case because it's the only one that
-                    // arises: ZDef's are only 32-bit right now. So, when we hit these
-                    // assertions it means that we need to implement those other kinds of zero
-                    // fills.
-                    RELEASE_ASSERT(arg.stackSlot()-&gt;byteSize() == 8);
-                    RELEASE_ASSERT(width == Arg::Width32);
-
-                    // We rely on the fact that there must be some way to move zero to a memory
-                    // location without first burning a register. On ARM, we would do this using
-                    // zr.
-                    RELEASE_ASSERT(isValidForm(Move32, Arg::Imm, Arg::Stack));
-                    insertionSet.insert(
-                        instIndex + 1, Move32, inst.origin, Arg::imm(0), arg.withOffset(4));
-                });
-        }
-        insertionSet.execute(block);
-    }
-}
-
-} } } // namespace JSC::B3::Air
-
-#endif // AirFixSpillSlotZDef_h
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -31,10 +31,12 @@
</span><span class="cx"> #include &quot;AirAllocateStack.h&quot;
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirEliminateDeadCode.h&quot;
</span><ins>+#include &quot;AirFixObviousSpills.h&quot;
</ins><span class="cx"> #include &quot;AirFixPartialRegisterStalls.h&quot;
</span><span class="cx"> #include &quot;AirGenerationContext.h&quot;
</span><span class="cx"> #include &quot;AirHandleCalleeSaves.h&quot;
</span><span class="cx"> #include &quot;AirIteratedRegisterCoalescing.h&quot;
</span><ins>+#include &quot;AirLogRegisterPressure.h&quot;
</ins><span class="cx"> #include &quot;AirLowerAfterRegAlloc.h&quot;
</span><span class="cx"> #include &quot;AirLowerMacros.h&quot;
</span><span class="cx"> #include &quot;AirOpcodeUtils.h&quot;
</span><span class="lines">@@ -84,6 +86,16 @@
</span><span class="cx">     else
</span><span class="cx">         iteratedRegisterCoalescing(code);
</span><span class="cx"> 
</span><ins>+    if (Options::logAirRegisterPressure()) {
+        dataLog(&quot;Register pressure after register allocation:\n&quot;);
+        logRegisterPressure(code);
+    }
+
+    // This replaces uses of spill slots with registers or constants if possible. It does this by
+    // minimizing the amount that we perturb the already-chosen register allocation. It may extend
+    // the live ranges of registers though.
+    fixObviousSpills(code);
+
</ins><span class="cx">     lowerAfterRegAlloc(code);
</span><span class="cx"> 
</span><span class="cx">     // Prior to this point the prologue and epilogue is implicit. This makes it explicit. It also
</span><span class="lines">@@ -103,13 +115,15 @@
</span><span class="cx">     // frequency successor is also the fall-through target.
</span><span class="cx">     optimizeBlockOrder(code);
</span><span class="cx"> 
</span><ins>+    // This is needed to satisfy a requirement of B3::StackmapValue.
+    reportUsedRegisters(code);
+
</ins><span class="cx">     // Attempt to remove false dependencies between instructions created by partial register changes.
</span><del>-    // This must be executed as late as possible as it depends on the instructions order and register use.
</del><ins>+    // This must be executed as late as possible as it depends on the instructions order and register
+    // use. We _must_ run this after reportUsedRegisters(), since that kills variable assignments
+    // that seem dead. Luckily, this phase does not change register liveness, so that's OK.
</ins><span class="cx">     fixPartialRegisterStalls(code);
</span><span class="cx"> 
</span><del>-    // This is needed to satisfy a requirement of B3::StackmapValue.
-    reportUsedRegisters(code);
-
</del><span class="cx">     if (shouldValidateIR())
</span><span class="cx">         validate(code);
</span><span class="cx"> 
</span><span class="lines">@@ -132,6 +146,17 @@
</span><span class="cx">     if (code.frameSize())
</span><span class="cx">         jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), MacroAssembler::stackPointerRegister);
</span><span class="cx"> 
</span><ins>+    auto argFor = [&amp;] (const RegisterAtOffset&amp; entry) -&gt; CCallHelpers::Address {
+        return CCallHelpers::Address(GPRInfo::callFrameRegister, entry.offset());
+    };
+    
+    for (const RegisterAtOffset&amp; entry : code.calleeSaveRegisters()) {
+        if (entry.reg().isGPR())
+            jit.storePtr(entry.reg().gpr(), argFor(entry));
+        else
+            jit.storeDouble(entry.reg().fpr(), argFor(entry));
+    }
+
</ins><span class="cx">     GenerationContext context;
</span><span class="cx">     context.code = &amp;code;
</span><span class="cx">     IndexMap&lt;BasicBlock, CCallHelpers::Label&gt; blockLabels(code.size());
</span><span class="lines">@@ -162,9 +187,15 @@
</span><span class="cx">         if (isReturn(block-&gt;last().opcode)) {
</span><span class="cx">             // We currently don't represent the full prologue/epilogue in Air, so we need to
</span><span class="cx">             // have this override.
</span><del>-            if (code.frameSize())
</del><ins>+            if (code.frameSize()) {
+                for (const RegisterAtOffset&amp; entry : code.calleeSaveRegisters()) {
+                    if (entry.reg().isGPR())
+                        jit.loadPtr(argFor(entry), entry.reg().gpr());
+                    else
+                        jit.loadDouble(argFor(entry), entry.reg().fpr());
+                }
</ins><span class="cx">                 jit.emitFunctionEpilogue();
</span><del>-            else
</del><ins>+            } else
</ins><span class="cx">                 jit.emitFunctionEpilogueWithEmptyFrame();
</span><span class="cx">             jit.ret();
</span><span class="cx">             continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirHandleCalleeSavescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><del>-#include &quot;AirInsertionSet.h&quot;
</del><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -71,34 +70,6 @@
</span><span class="cx">     // This is a bit weird since we could have already pinned a different stack slot to this
</span><span class="cx">     // area. Also, our runtime does not require us to pin the saves area. Maybe we shouldn't pin it?
</span><span class="cx">     savesArea-&gt;setOffsetFromFP(-byteSize);
</span><del>-
-    auto argFor = [&amp;] (const RegisterAtOffset&amp; entry) -&gt; Arg {
-        return Arg::stack(savesArea, entry.offset() + byteSize);
-    };
-
-    InsertionSet insertionSet(code);
-    
-    // First insert saving code in the prologue.
-    for (const RegisterAtOffset&amp; entry : code.calleeSaveRegisters()) {
-        insertionSet.insert(
-            0, entry.reg().isGPR() ? Move : MoveDouble, code[0]-&gt;at(0).origin,
-            Tmp(entry.reg()), argFor(entry));
-    }
-    insertionSet.execute(code[0]);
-
-    // Now insert restore code at epilogues.
-    for (BasicBlock* block : code) {
-        Inst&amp; last = block-&gt;last();
-        if (!isReturn(last.opcode))
-            continue;
-
-        for (const RegisterAtOffset&amp; entry : code.calleeSaveRegisters()) {
-            insertionSet.insert(
-                block-&gt;size() - 1, entry.reg().isGPR() ? Move : MoveDouble, last.origin,
-                argFor(entry), Tmp(entry.reg()));
-        }
-        insertionSet.execute(block);
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInsth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInst.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInst.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirInst.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -162,6 +162,7 @@
</span><span class="cx">     //
</span><span class="cx">     // This function is auto-generated by opcode_generator.rb.
</span><span class="cx">     bool admitsStack(unsigned argIndex);
</span><ins>+    bool admitsStack(Arg&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Returns true if this instruction can have any effects other than control flow or arguments.
</span><span class="cx">     bool hasNonArgNonControlEffects();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInstInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -158,6 +158,11 @@
</span><span class="cx">     args[0].special()-&gt;reportUsedRegisters(*this, usedRegisters);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool Inst::admitsStack(Arg&amp; arg)
+{
+    return admitsStack(&amp;arg - &amp;args[0]);
+}
+
</ins><span class="cx"> inline bool isShiftValid(const Inst&amp; inst)
</span><span class="cx"> {
</span><span class="cx"> #if CPU(X86) || CPU(X86_64)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirIteratedRegisterCoalescingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><del>-#include &quot;AirFixSpillSlotZDef.h&quot;
</del><span class="cx"> #include &quot;AirInsertionSet.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="lines">@@ -1124,11 +1123,11 @@
</span><span class="cx">                 // complete register allocation. So, we record this before starting.
</span><span class="cx">                 bool mayBeCoalescable = allocator.mayBeCoalescable(inst);
</span><span class="cx"> 
</span><del>-                // On X86_64, Move32 is cheaper if we know that it's equivalent to a Move. It's
</del><ins>+                // Move32 is cheaper if we know that it's equivalent to a Move. It's
</ins><span class="cx">                 // equivalent if the destination's high bits are not observable or if the source's high
</span><span class="cx">                 // bits are all zero. Note that we don't have the opposite optimization for other
</span><span class="cx">                 // architectures, which may prefer Move over Move32, because Move is canonical already.
</span><del>-                if (type == Arg::GP &amp;&amp; optimizeForX86_64() &amp;&amp; inst.opcode == Move
</del><ins>+                if (type == Arg::GP &amp;&amp; inst.opcode == Move
</ins><span class="cx">                     &amp;&amp; inst.args[0].isTmp() &amp;&amp; inst.args[1].isTmp()) {
</span><span class="cx">                     if (m_tmpWidth.useWidth(inst.args[1].tmp()) &lt;= Arg::Width32
</span><span class="cx">                         || m_tmpWidth.defWidth(inst.args[0].tmp()) &lt;= Arg::Width32)
</span><span class="lines">@@ -1168,7 +1167,6 @@
</span><span class="cx">     void addSpillAndFill(const ColoringAllocator&lt;type&gt;&amp; allocator, HashSet&lt;unsigned&gt;&amp; unspillableTmps)
</span><span class="cx">     {
</span><span class="cx">         HashMap&lt;Tmp, StackSlot*&gt; stackSlots;
</span><del>-        unsigned newStackSlotThreshold = m_code.stackSlots().size();
</del><span class="cx">         for (Tmp tmp : allocator.spilledTmps()) {
</span><span class="cx">             // All the spilled values become unspillable.
</span><span class="cx">             unspillableTmps.add(AbsoluteTmpMapper&lt;type&gt;::absoluteIndex(tmp));
</span><span class="lines">@@ -1202,16 +1200,19 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 // Try to replace the register use by memory use when possible.
</span><del>-                for (unsigned i = 0; i &lt; inst.args.size(); ++i) {
-                    Arg&amp; arg = inst.args[i];
-                    if (arg.isTmp() &amp;&amp; arg.type() == type &amp;&amp; !arg.isReg()) {
-                        auto stackSlotEntry = stackSlots.find(arg.tmp());
-                        if (stackSlotEntry != stackSlots.end() &amp;&amp; inst.admitsStack(i)) {
-                            arg = Arg::stack(stackSlotEntry-&gt;value);
-                            didSpill = true;
</del><ins>+                inst.forEachArg(
+                    [&amp;] (Arg&amp; arg, Arg::Role, Arg::Type argType, Arg::Width width) {
+                        if (arg.isTmp() &amp;&amp; argType == type &amp;&amp; !arg.isReg()) {
+                            auto stackSlotEntry = stackSlots.find(arg.tmp());
+                            if (stackSlotEntry != stackSlots.end()
+                                &amp;&amp; inst.admitsStack(arg)) {
+                                stackSlotEntry-&gt;value-&gt;ensureSize(
+                                    forceMove32IfDidSpill ? 4 : Arg::bytes(width));
+                                arg = Arg::stack(stackSlotEntry-&gt;value);
+                                didSpill = true;
+                            }
</ins><span class="cx">                         }
</span><del>-                    }
-                }
</del><ins>+                    });
</ins><span class="cx"> 
</span><span class="cx">                 if (didSpill &amp;&amp; forceMove32IfDidSpill)
</span><span class="cx">                     inst.opcode = Move32;
</span><span class="lines">@@ -1262,12 +1263,6 @@
</span><span class="cx">                 });
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-
-        fixSpillSlotZDef(
-            m_code,
-            [&amp;] (StackSlot* stackSlot) -&gt; bool {
-                return stackSlot-&gt;index() &gt;= newStackSlotThreshold;
-            });
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Code&amp; m_code;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirBasicBlock.h&quot;
</span><ins>+#include &quot;AirCode.h&quot;
</ins><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirTmpInlines.h&quot;
</span><span class="cx"> #include &quot;B3IndexMap.h&quot;
</span><span class="lines">@@ -93,9 +94,11 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Adapter&gt;
</span><del>-class AbstractLiveness : private Adapter {
</del><ins>+class AbstractLiveness : public Adapter {
</ins><span class="cx">     struct Workset;
</span><span class="cx"> public:
</span><ins>+    typedef typename Adapter::Thing Thing;
+    
</ins><span class="cx">     AbstractLiveness(Code&amp; code)
</span><span class="cx">         : Adapter(code)
</span><span class="cx">         , m_workset(Adapter::maxIndex(code))
</span><span class="lines">@@ -222,6 +225,11 @@
</span><span class="cx"> 
</span><span class="cx">             Iterator begin() const { return Iterator(m_liveness, m_liveness.m_workset.begin()); }
</span><span class="cx">             Iterator end() const { return Iterator(m_liveness, m_liveness.m_workset.end()); }
</span><ins>+            
+            bool contains(const typename Adapter::Thing&amp; thing) const
+            {
+                return m_liveness.m_workset.contains(Adapter::valueToIndex(thing));
+            }
</ins><span class="cx"> 
</span><span class="cx">         private:
</span><span class="cx">             AbstractLiveness&amp; m_liveness;
</span><span class="lines">@@ -232,6 +240,11 @@
</span><span class="cx">             return Iterable(m_liveness);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        bool isLive(const typename Adapter::Thing&amp; thing) const
+        {
+            return live().contains(thing);
+        }
+
</ins><span class="cx">         void execute(unsigned instIndex)
</span><span class="cx">         {
</span><span class="cx">             Inst&amp; inst = m_block-&gt;at(instIndex);
</span><span class="lines">@@ -277,6 +290,11 @@
</span><span class="cx">         BasicBlock* m_block;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    const Vector&lt;unsigned&gt;&amp; rawLiveAtHead(BasicBlock* block)
+    {
+        return m_liveAtHead[block];
+    }
+
</ins><span class="cx">     template&lt;typename UnderlyingIterable&gt;
</span><span class="cx">     class Iterable {
</span><span class="cx">     public:
</span><span class="lines">@@ -330,6 +348,11 @@
</span><span class="cx">         iterator begin() const { return iterator(m_liveness, m_iterable.begin()); }
</span><span class="cx">         iterator end() const { return iterator(m_liveness, m_iterable.end()); }
</span><span class="cx"> 
</span><ins>+        bool contains(const typename Adapter::Thing&amp; thing) const
+        {
+            return m_liveness.m_workset.contains(Adapter::valueToIndex(thing));
+        }
+
</ins><span class="cx">     private:
</span><span class="cx">         AbstractLiveness&amp; m_liveness;
</span><span class="cx">         const UnderlyingIterable&amp; m_iterable;
</span><span class="lines">@@ -345,6 +368,8 @@
</span><span class="cx">         return Iterable&lt;typename Adapter::IndexSet&gt;(*this, m_liveAtTail[block]);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    IndexSparseSet&lt;UnsafeVectorOverflow&gt;&amp; workset() { return m_workset; }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class LocalCalc;
</span><span class="cx">     friend struct LocalCalc::Iterable;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLogRegisterPressurecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp (0 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -0,0 +1,102 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;AirLogRegisterPressure.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirCode.h&quot;
+#include &quot;AirInstInlines.h&quot;
+#include &quot;AirLiveness.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+void logRegisterPressure(Code&amp; code)
+{
+    const unsigned totalColumns = 200;
+    const unsigned registerColumns = 100;
+    
+    RegLiveness liveness(code);
+
+    for (BasicBlock* block : code) {
+        RegLiveness::LocalCalc localCalc(liveness, block);
+
+        block-&gt;dumpHeader(WTF::dataFile());
+
+        Vector&lt;CString&gt; instDumps;
+        for (unsigned instIndex = block-&gt;size(); instIndex--;) {
+            Inst&amp; inst = block-&gt;at(instIndex);
+            Inst* prevInst = block-&gt;get(instIndex - 1);
+
+            localCalc.execute(instIndex);
+
+            RegisterSet set;
+            set.setAll(localCalc.live());
+            Inst::forEachDefWithExtraClobberedRegs&lt;Reg&gt;(
+                prevInst, &amp;inst,
+                [&amp;] (Reg reg, Arg::Role, Arg::Type, Arg::Width) {
+                    set.set(reg);
+                });
+
+            StringPrintStream instOut;
+            StringPrintStream lineOut;
+            lineOut.print(&quot;   &quot;);
+            if (set.numberOfSetRegisters()) {
+                set.forEach(
+                    [&amp;] (Reg reg) {
+                        CString text = toCString(&quot; &quot;, reg);
+                        if (text.length() + lineOut.length() &gt; totalColumns) {
+                            instOut.print(lineOut.toCString(), &quot;\n&quot;);
+                            lineOut.reset();
+                            lineOut.print(&quot;       &quot;);
+                        }
+                        lineOut.print(text);
+                    });
+                lineOut.print(&quot;:&quot;);
+            }
+            if (lineOut.length() &gt; registerColumns) {
+                instOut.print(lineOut.toCString(), &quot;\n&quot;);
+                lineOut.reset();
+            }
+            while (lineOut.length() &lt; registerColumns)
+                lineOut.print(&quot; &quot;);
+            lineOut.print(&quot; &quot;);
+            lineOut.print(inst);
+            instOut.print(lineOut.toCString(), &quot;\n&quot;);
+            instDumps.append(instOut.toCString());
+        }
+
+        for (unsigned i = instDumps.size(); i--;)
+            dataLog(instDumps[i]);
+        
+        block-&gt;dumpFooter(WTF::dataFile());
+    }
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLogRegisterPressureh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.h (0 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AirLogRegisterPressure_h
+#define AirLogRegisterPressure_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// Dumps the registers that are used at each instruction.
+void logRegisterPressure(Code&amp;);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+#endif // AirLogRegisterPressure_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOptimizeBlockOrdercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -73,10 +73,8 @@
</span><span class="cx"> 
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><del>-void optimizeBlockOrder(Code&amp; code)
</del><ins>+Vector&lt;BasicBlock*&gt; blocksInOptimizedOrder(Code&amp; code)
</ins><span class="cx"> {
</span><del>-    PhaseScope phaseScope(code, &quot;optimizeBlockOrder&quot;);
-
</del><span class="cx">     Vector&lt;BasicBlock*&gt; blocksInOrder;
</span><span class="cx"> 
</span><span class="cx">     BlockWorklist fastWorklist;
</span><span class="lines">@@ -113,6 +111,15 @@
</span><span class="cx">     ASSERT(fastWorklist.isEmpty());
</span><span class="cx">     ASSERT(slowWorklist.isEmpty());
</span><span class="cx"> 
</span><ins>+    return blocksInOrder;
+}
+
+void optimizeBlockOrder(Code&amp; code)
+{
+    PhaseScope phaseScope(code, &quot;optimizeBlockOrder&quot;);
+
+    Vector&lt;BasicBlock*&gt; blocksInOrder = blocksInOptimizedOrder(code);
+    
</ins><span class="cx">     // Place blocks into Code's block list according to the ordering in blocksInOrder. We do this by leaking
</span><span class="cx">     // all of the blocks and then readopting them.
</span><span class="cx">     for (auto&amp; entry : code.blockList())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOptimizeBlockOrderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,10 +28,18 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/Vector.h&gt;
+
</ins><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+class BasicBlock;
</ins><span class="cx"> class Code;
</span><span class="cx"> 
</span><ins>+// Returns a list of blocks sorted according to what would be the current optimal order. This shares
+// some properties with a pre-order traversal. In particular, each block will appear after at least
+// one of its predecessors.
+Vector&lt;BasicBlock*&gt; blocksInOptimizedOrder(Code&amp;);
+
</ins><span class="cx"> // Reorders the basic blocks to keep hot blocks at the top, and maximize the likelihood that a frequently
</span><span class="cx"> // taken edge is just a fall-through.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -46,6 +46,32 @@
</span><span class="cx"> 
</span><span class="cx">         for (unsigned instIndex = block-&gt;size(); instIndex--;) {
</span><span class="cx">             Inst&amp; inst = block-&gt;at(instIndex);
</span><ins>+
+            // Kill dead assignments to registers. For simplicity we say that a store is killable if
+            // it has only late defs and those late defs are to registers that are dead right now.
+            if (!inst.hasNonArgEffects()) {
+                bool canDelete = true;
+                inst.forEachArg(
+                    [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type, Arg::Width) {
+                        if (Arg::isEarlyDef(role)) {
+                            canDelete = false;
+                            return;
+                        }
+                        if (!Arg::isLateDef(role))
+                            return;
+                        if (!arg.isReg()) {
+                            canDelete = false;
+                            return;
+                        }
+                        if (localCalc.isLive(arg.reg())) {
+                            canDelete = false;
+                            return;
+                        }
+                    });
+                if (canDelete)
+                    inst = Inst();
+            }
+            
</ins><span class="cx">             if (inst.opcode == Patch) {
</span><span class="cx">                 RegisterSet registerSet;
</span><span class="cx">                 for (Reg reg : localCalc.live())
</span><span class="lines">@@ -54,6 +80,11 @@
</span><span class="cx">             }
</span><span class="cx">             localCalc.execute(instIndex);
</span><span class="cx">         }
</span><ins>+        
+        block-&gt;insts().removeAllMatching(
+            [&amp;] (const Inst&amp; inst) -&gt; bool {
+                return !inst;
+            });
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirReportUsedRegistersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,7 +32,8 @@
</span><span class="cx"> 
</span><span class="cx"> class Code;
</span><span class="cx"> 
</span><del>-// Performs a liveness analysis over registers and reports the live registers to every Special.
</del><ins>+// Performs a liveness analysis over registers and reports the live registers to every Special. Takes
+// the opportunity to kill dead assignments to registers, since it has access to register liveness.
</ins><span class="cx"> 
</span><span class="cx"> void reportUsedRegisters(Code&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><del>-#include &quot;AirFixSpillSlotZDef.h&quot;
</del><span class="cx"> #include &quot;AirInsertionSet.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="lines">@@ -84,7 +83,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Allocate a stack slot for each tmp.
</span><span class="cx">     Vector&lt;StackSlot*&gt; allStackSlots[Arg::numTypes];
</span><del>-    unsigned newStackSlotThreshold = code.stackSlots().size();
</del><span class="cx">     for (unsigned typeIndex = 0; typeIndex &lt; Arg::numTypes; ++typeIndex) {
</span><span class="cx">         Vector&lt;StackSlot*&gt;&amp; stackSlots = allStackSlots[typeIndex];
</span><span class="cx">         Arg::Type type = static_cast&lt;Arg::Type&gt;(typeIndex);
</span><span class="lines">@@ -130,7 +128,6 @@
</span><span class="cx">                     switch (role) {
</span><span class="cx">                     case Arg::Use:
</span><span class="cx">                     case Arg::ColdUse:
</span><del>-                    case Arg::EarlyDef:
</del><span class="cx">                         for (Reg reg : regsInPriorityOrder(type)) {
</span><span class="cx">                             if (!setBefore.get(reg)) {
</span><span class="cx">                                 setBefore.set(reg);
</span><span class="lines">@@ -154,6 +151,7 @@
</span><span class="cx">                     case Arg::LateUse:
</span><span class="cx">                     case Arg::LateColdUse:
</span><span class="cx">                     case Arg::Scratch:
</span><ins>+                    case Arg::EarlyDef:
</ins><span class="cx">                         for (Reg reg : regsInPriorityOrder(type)) {
</span><span class="cx">                             if (!setBefore.get(reg) &amp;&amp; !setAfter.get(reg)) {
</span><span class="cx">                                 setAfter.set(reg);
</span><span class="lines">@@ -182,12 +180,6 @@
</span><span class="cx">         }
</span><span class="cx">         insertionSet.execute(block);
</span><span class="cx">     }
</span><del>-
-    fixSpillSlotZDef(
-        code,
-        [&amp;] (StackSlot* stackSlot) -&gt; bool {
-            return stackSlot-&gt;index() &gt;= newStackSlotThreshold;
-        });
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirStackSloth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -48,6 +48,12 @@
</span><span class="cx">     bool isLocked() const { return m_kind == StackSlotKind::Locked; }
</span><span class="cx">     unsigned index() const { return m_index; }
</span><span class="cx"> 
</span><ins>+    void ensureSize(unsigned requestedSize)
+    {
+        ASSERT(!m_offsetFromFP);
+        m_byteSize = std::max(m_byteSize, requestedSize);
+    }
+
</ins><span class="cx">     unsigned alignment() const
</span><span class="cx">     {
</span><span class="cx">         if (byteSize() &lt;= 1)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirValidate.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirValidate.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/b3/air/AirValidate.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -82,6 +82,13 @@
</span><span class="cx">                     VALIDATE(isTerminal(inst.opcode), (&quot;At &quot;, inst, &quot; in &quot;, *block));
</span><span class="cx">                 else
</span><span class="cx">                     VALIDATE(!isTerminal(inst.opcode), (&quot;At &quot;, inst, &quot; in &quot;, *block));
</span><ins>+
+                // forEachArg must return Arg&amp;'s that point into the args array.
+                inst.forEachArg(
+                    [&amp;] (Arg&amp; arg, Arg::Role, Arg::Type, Arg::Width) {
+                        VALIDATE(&amp;arg &gt;= &amp;inst.args[0], (&quot;At &quot;, arg, &quot; in &quot;, inst, &quot; in &quot;, *block));
+                        VALIDATE(&amp;arg &lt;= &amp;inst.args.last(), (&quot;At &quot;, arg, &quot; in &quot;, inst, &quot; in &quot;, *block));
+                    });
</ins><span class="cx">             }
</span><span class="cx">             for (BasicBlock* successor : block-&gt;successorBlocks())
</span><span class="cx">                 VALIDATE(validBlocks.contains(successor), (&quot;In &quot;, *block));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Compilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
</span><span class="cx"> 
</span><ins>+#include &quot;AirCode.h&quot;
</ins><span class="cx"> #include &quot;B3Generate.h&quot;
</span><span class="cx"> #include &quot;B3ProcedureInlines.h&quot;
</span><span class="cx"> #include &quot;B3StackSlotValue.h&quot;
</span><span class="lines">@@ -57,7 +58,7 @@
</span><span class="cx">     Graph&amp; graph = state.graph;
</span><span class="cx">     CodeBlock* codeBlock = graph.m_codeBlock;
</span><span class="cx">     VM&amp; vm = graph.m_vm;
</span><del>-    
</del><ins>+
</ins><span class="cx">     {
</span><span class="cx">         GraphSafepoint safepoint(state.graph, safepointResult);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1858,8 +1858,8 @@
</span><span class="cx">                     m_out.notZero32(result), usually(continuation), rarely(slowCase));
</span><span class="cx">                 
</span><span class="cx">                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
</span><del>-                LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int32Zero), m_out.lessThan(right, m_out.int32Zero));
-                speculate(NegativeZero, noValue(), 0, cond);
</del><ins>+                speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(left, m_out.int32Zero));
+                speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(right, m_out.int32Zero));
</ins><span class="cx">                 m_out.jump(continuation);
</span><span class="cx">                 m_out.appendTo(continuation, lastNext);
</span><span class="cx">             }
</span><span class="lines">@@ -1890,8 +1890,8 @@
</span><span class="cx">                     m_out.notZero64(result), usually(continuation), rarely(slowCase));
</span><span class="cx">                 
</span><span class="cx">                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
</span><del>-                LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int64Zero), m_out.lessThan(right, m_out.int64Zero));
-                speculate(NegativeZero, noValue(), 0, cond);
</del><ins>+                speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(left, m_out.int64Zero));
+                speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(right, m_out.int64Zero));
</ins><span class="cx">                 m_out.jump(continuation);
</span><span class="cx">                 m_out.appendTo(continuation, lastNext);
</span><span class="cx">             }
</span><span class="lines">@@ -1957,8 +1957,8 @@
</span><span class="cx"> 
</span><span class="cx">                 LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
</span><span class="cx">                 LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
</span><del>-                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
-                speculate(Overflow, noValue(), 0, cond);
</del><ins>+                speculate(Overflow, noValue(), nullptr, m_out.isZero32(denominator));
+                speculate(Overflow, noValue(), nullptr, m_out.equal(numerator, neg2ToThe31));
</ins><span class="cx">                 m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">                 m_out.appendTo(continuation, lastNext);
</span><span class="lines">@@ -2013,8 +2013,8 @@
</span><span class="cx"> 
</span><span class="cx">                 LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
</span><span class="cx">                 LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
</span><del>-                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
-                speculate(Overflow, noValue(), 0, cond);
</del><ins>+                speculate(Overflow, noValue(), nullptr, m_out.isZero32(denominator));
+                speculate(Overflow, noValue(), nullptr, m_out.equal(numerator, neg2ToThe31));
</ins><span class="cx">                 m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">                 m_out.appendTo(continuation, lastNext);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -91,6 +91,13 @@
</span><span class="cx">         ASSERT(!!reg);
</span><span class="cx">         return m_vector.get(reg.index());
</span><span class="cx">     }
</span><ins>+
+    template&lt;typename Iterable&gt;
+    void setAll(const Iterable&amp; iterable)
+    {
+        for (Reg reg : iterable)
+            set(reg);
+    }
</ins><span class="cx">     
</span><span class="cx">     void merge(const RegisterSet&amp; other) { m_vector.merge(other.m_vector); }
</span><span class="cx">     void filter(const RegisterSet&amp; other) { m_vector.filter(other.m_vector); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -343,6 +343,7 @@
</span><span class="cx">     v(bool, logB3PhaseTimes, false, nullptr) \
</span><span class="cx">     v(double, rareBlockPenalty, 0.001, nullptr) \
</span><span class="cx">     v(bool, airSpillsEverything, false, nullptr) \
</span><ins>+    v(bool, logAirRegisterPressure, false, nullptr) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, useDollarVM, false, &quot;installs the $vm debugging tool in global objects&quot;) \
</span><span class="cx">     v(optionString, functionOverrides, nullptr, &quot;file with debugging overrides for function bodies&quot;) \
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/WTF/ChangeLog        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-01-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 should be just as fast as FTL LLVM on Octane/crypto
+        https://bugs.webkit.org/show_bug.cgi?id=153113
+
+        Reviewed by Saam Barati.
+
+        * wtf/IndexSparseSet.h:
+        (WTF::IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet):
+        (WTF::IndexSparseSet&lt;OverflowHandler&gt;::add):
+        (WTF::IndexSparseSet&lt;OverflowHandler&gt;::remove):
+        * wtf/StringPrintStream.h:
+        (WTF::StringPrintStream::length):
+
</ins><span class="cx"> 2016-01-17  Michael Catanzaro  &lt;mcatanzaro@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CMake] Do not build bmalloc when USE_SYSTEM_MALLOC is ON
</span></span></pre></div>
<a id="trunkSourceWTFwtfCheckedArithmetich"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CheckedArithmetic.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CheckedArithmetic.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/WTF/wtf/CheckedArithmetic.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -806,8 +806,32 @@
</span><span class="cx">     return checkedSum&lt;T&gt;(args...).hasOverflowed();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T, typename U&gt; bool differenceOverflows(U left, U right)
+{
+    return (Checked&lt;T, RecordOverflow&gt;(left) - Checked&lt;T, RecordOverflow&gt;(right)).hasOverflowed();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T, typename U&gt;
+Checked&lt;T, RecordOverflow&gt; checkedProduct(U value)
+{
+    return Checked&lt;T, RecordOverflow&gt;(value);
+}
+template&lt;typename T, typename U, typename... Args&gt;
+Checked&lt;T, RecordOverflow&gt; checkedProduct(U value, Args... args)
+{
+    return Checked&lt;T, RecordOverflow&gt;(value) * checkedProduct&lt;T&gt;(args...);
+}
+
+// Sometimes, you just want to check if some math would overflow - the code to do the math is
+// already in place, and you want to guard it.
+
+template&lt;typename T, typename... Args&gt; bool productOverflows(Args... args)
+{
+    return checkedProduct&lt;T&gt;(args...).hasOverflowed();
+}
+
+}
+
</ins><span class="cx"> using WTF::Checked;
</span><span class="cx"> using WTF::CheckedState;
</span><span class="cx"> using WTF::RecordOverflow;
</span><span class="lines">@@ -821,6 +845,8 @@
</span><span class="cx"> using WTF::CheckedUint64;
</span><span class="cx"> using WTF::CheckedSize;
</span><span class="cx"> using WTF::checkedSum;
</span><ins>+using WTF::differenceOverflows;
+using WTF::productOverflows;
</ins><span class="cx"> using WTF::sumOverflows;
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWTFwtfIndexSparseSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/IndexSparseSet.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/IndexSparseSet.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/WTF/wtf/IndexSparseSet.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -47,8 +47,8 @@
</span><span class="cx"> public:
</span><span class="cx">     explicit IndexSparseSet(unsigned maxValue);
</span><span class="cx"> 
</span><del>-    void add(unsigned);
-    void remove(unsigned);
</del><ins>+    bool add(unsigned);
+    bool remove(unsigned);
</ins><span class="cx">     void clear();
</span><span class="cx"> 
</span><span class="cx">     unsigned size() const;
</span><span class="lines">@@ -71,29 +71,33 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename OverflowHandler&gt;
</span><del>-inline void IndexSparseSet&lt;OverflowHandler&gt;::add(unsigned value)
</del><ins>+inline bool IndexSparseSet&lt;OverflowHandler&gt;::add(unsigned value)
</ins><span class="cx"> {
</span><span class="cx">     if (contains(value))
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx"> 
</span><span class="cx">     unsigned newPosition = m_values.size();
</span><span class="cx">     m_values.append(value);
</span><span class="cx">     m_map[value] = newPosition;
</span><ins>+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename OverflowHandler&gt;
</span><del>-inline void IndexSparseSet&lt;OverflowHandler&gt;::remove(unsigned value)
</del><ins>+inline bool IndexSparseSet&lt;OverflowHandler&gt;::remove(unsigned value)
</ins><span class="cx"> {
</span><span class="cx">     unsigned position = m_map[value];
</span><span class="cx">     if (position &gt;= m_values.size())
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx"> 
</span><span class="cx">     if (m_values[position] == value) {
</span><span class="cx">         unsigned lastValue = m_values.last();
</span><span class="cx">         m_values[position] = lastValue;
</span><span class="cx">         m_map[lastValue] = position;
</span><span class="cx">         m_values.removeLast();
</span><ins>+        return true;
</ins><span class="cx">     }
</span><ins>+
+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename OverflowHandler&gt;
</span></span></pre></div>
<a id="trunkSourceWTFwtfStringPrintStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/StringPrintStream.h (195297 => 195298)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/StringPrintStream.h        2016-01-19 18:35:33 UTC (rev 195297)
+++ trunk/Source/WTF/wtf/StringPrintStream.h        2016-01-19 19:20:35 UTC (rev 195298)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -38,6 +38,8 @@
</span><span class="cx">     WTF_EXPORT_PRIVATE virtual ~StringPrintStream();
</span><span class="cx">     
</span><span class="cx">     WTF_EXPORT_PRIVATE virtual void vprintf(const char* format, va_list) override WTF_ATTRIBUTE_PRINTF(2, 0);
</span><ins>+
+    size_t length() const { return m_next; }
</ins><span class="cx">     
</span><span class="cx">     WTF_EXPORT_PRIVATE CString toCString();
</span><span class="cx">     WTF_EXPORT_PRIVATE String toString();
</span></span></pre>
</div>
</div>

</body>
</html>