<!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>[214636] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>Air should support linear scan for optLevel&lt;2
https://bugs.webkit.org/show_bug.cgi?id=170161

Reviewed by Saam Barati.
        
Source/JavaScriptCore:

This changes the default opt level of B3 to 2. It makes the other opt levels useful by adding a
new register allocator. This new linear scan allocator will produce significantly worse code.
But it will produce that code a lot faster than IRC or Briggs.
        
The opt levels are:
    0: no optimizations, linear scan
    1: some optimizations, linear scan
    2: full optimizations, graph coloring (IRC or Briggs based on CPU)
        
What we used to call optLevel=1 is not called optLevel=2, or better yet,
optLevel=B3::defaultOptLevel(). We no longer have anything like the old optLevel=0 (which did no
optimizations but ran graph coloring).
        
allocateRegistersByLinearScan() faithfully implements Massimiliano Poletto and Vivek Sarkar's
famous algorithm. It uses the variant that handles clobbered registers by avoiding assigning
ranges to those registers if the range overlaps a clobber. It's engineered to allocate registers
very quickly and generate inefficient code without falling off a cliff.
        
The new optLevel=1 speeds up B3 by a factor of 2, and results in a 80% throughput regression.
Linear scan runs 4.7x faster than graph coloring on average.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3BasicBlockUtils.h:
(JSC::B3::blocksInPreOrder):
(JSC::B3::blocksInPostOrder):
* b3/B3BlockWorklist.h:
* b3/B3CFG.h:
(JSC::B3::CFG::newMap):
* b3/B3Common.h:
(JSC::B3::defaultOptLevel):
* b3/B3Compile.h:
* b3/B3DuplicateTails.cpp:
* b3/B3EliminateCommonSubexpressions.cpp:
* b3/B3FixSSA.cpp:
(JSC::B3::demoteValues):
(JSC::B3::fixSSA):
* b3/B3FixSSA.h:
* b3/B3Generate.cpp:
(JSC::B3::prepareForGeneration):
(JSC::B3::generateToAir):
* b3/B3Generate.h:
* b3/B3HeapRange.cpp: Removed.
* b3/B3HeapRange.h:
(JSC::B3::HeapRange::HeapRange): Deleted.
(JSC::B3::HeapRange::top): Deleted.
(JSC::B3::HeapRange::operator==): Deleted.
(JSC::B3::HeapRange::operator!=): Deleted.
(JSC::B3::HeapRange::operator|): Deleted.
(JSC::B3::HeapRange::operator bool): Deleted.
(JSC::B3::HeapRange::begin): Deleted.
(JSC::B3::HeapRange::end): Deleted.
(JSC::B3::HeapRange::overlaps): Deleted.
* b3/B3LowerToAir.cpp:
* b3/B3MoveConstants.cpp:
* b3/B3PhiChildren.h:
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::dump):
(JSC::B3::Procedure::deleteOrphans):
(JSC::B3::Procedure::setBlockOrderImpl):
* b3/B3ReduceDoubleToFloat.cpp:
* b3/B3ReduceStrength.cpp:
* b3/B3SSACalculator.h:
* b3/B3UseCounts.h:
* b3/air/AirAllocateRegistersByGraphColoring.cpp:
* b3/air/AirAllocateRegistersByLinearScan.cpp: Added.
(JSC::B3::Air::allocateRegistersByLinearScan):
* b3/air/AirAllocateRegistersByLinearScan.h: Added.
* b3/air/AirAllocateStack.cpp:
(JSC::B3::Air::allocateStack):
* b3/air/AirArg.cpp:
(WTF::printInternal):
* b3/air/AirArg.h:
(JSC::B3::Air::Arg::activeAt):
(JSC::B3::Air::Arg::timing):
(JSC::B3::Air::Arg::forEachPhase):
* b3/air/AirBasicBlock.h:
* b3/air/AirBlockWorklist.h:
* b3/air/AirCFG.h:
(JSC::B3::Air::CFG::newMap):
* b3/air/AirEliminateDeadCode.cpp:
(JSC::B3::Air::eliminateDeadCode):
* b3/air/AirFixObviousSpills.cpp:
* b3/air/AirFixPartialRegisterStalls.cpp:
(JSC::B3::Air::fixPartialRegisterStalls):
* b3/air/AirFixSpillsAfterTerminals.cpp: Added.
(JSC::B3::Air::fixSpillsAfterTerminals):
* b3/air/AirFixSpillsAfterTerminals.h: Added.
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::prepareForGeneration):
(JSC::B3::Air::generate):
* b3/air/AirGenerate.h:
* b3/air/AirGenerationContext.h:
* b3/air/AirInsertionSet.h:
* b3/air/AirInst.cpp:
(JSC::B3::Air::Inst::needsPadding):
* b3/air/AirLowerAfterRegAlloc.cpp:
(JSC::B3::Air::lowerAfterRegAlloc):
* b3/air/AirLowerEntrySwitch.cpp:
(JSC::B3::Air::lowerEntrySwitch):
* b3/air/AirOpcode.opcodes:
* b3/air/AirPhaseInsertionSet.cpp: Added.
(JSC::B3::Air::PhaseInsertionSet::execute):
* b3/air/AirPhaseInsertionSet.h: Added.
(JSC::B3::Air::PhaseInsertion::PhaseInsertion):
(JSC::B3::Air::PhaseInsertion::phase):
(JSC::B3::Air::PhaseInsertion::operator&lt;):
(JSC::B3::Air::PhaseInsertionSet::PhaseInsertionSet):
(JSC::B3::Air::PhaseInsertionSet::appendInsertion):
(JSC::B3::Air::PhaseInsertionSet::insertInst):
(JSC::B3::Air::PhaseInsertionSet::insert):
* b3/air/AirRegLiveness.h:
(JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
* b3/air/AirSpillEverything.cpp:
(JSC::B3::Air::spillEverything):
* b3/air/AirTmp.cpp:
* b3/air/AirTmp.h:
(JSC::B3::Air::Tmp::tmpForIndex):
* b3/air/AirTmpInlines.h:
(JSC::B3::Air::Tmp::Indexed::Indexed):
(JSC::B3::Air::Tmp::Indexed::index):
(JSC::B3::Air::Tmp::AbsolutelyIndexed::AbsolutelyIndexed):
(JSC::B3::Air::Tmp::AbsolutelyIndexed::index):
(JSC::B3::Air::Tmp::indexed):
(JSC::B3::Air::Tmp::absolutelyIndexed):
(JSC::B3::Air::Tmp::tmpForAbsoluteIndex):
* b3/testb3.cpp:
(JSC::B3::compile):
(JSC::B3::testMulLoadTwice):
* jit/RegisterSet.h:
(JSC::RegisterSet::add):
(JSC::RegisterSet::remove):
* runtime/Options.h:
* wasm/WasmB3IRGenerator.h:

Source/WTF:

This change introduces a new low-latency register allocator. It can allocate registers very
quickly by doing a relatively poor job. Implementing this algorithm required beefing up some of
our core algorithms.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Deque.h: Make it possible to do some basic priority queueing with this data structure.
(WTF::inlineCapacity&gt;::removeAllMatching):
(WTF::inlineCapacity&gt;::appendAndBubble):
(WTF::inlineCapacity&gt;::takeLast):
* wtf/IndexKeyType.h: Added. This makes it possible to use IndexMap and IndexSet with value or pointer types. Previously they just worked with pointer types.
(WTF::IndexKeyType::index):
* wtf/IndexMap.h: Adopt IndexKeyType.
(WTF::IndexMap::operator[]):
(WTF::IndexMap::append):
* wtf/IndexSet.h: Adopt IndexKeyType.
(WTF::IndexSet::add):
(WTF::IndexSet::addAll):
(WTF::IndexSet::remove):
(WTF::IndexSet::contains):
(WTF::IndexSet::Iterable::iterator::operator*):
* wtf/Range.h: Added. This used to be B3::HeapRange. This generalizes that data structure to any kind of range stuff.
(WTF::Range::Range):
(WTF::Range::top):
(WTF::Range::operator==):
(WTF::Range::operator!=):
(WTF::Range::operator bool):
(WTF::Range::operator|):
(WTF::Range::operator|=):
(WTF::Range::begin):
(WTF::Range::end):
(WTF::Range::overlaps):
(WTF::Range::dump):
* wtf/RangeSet.h:
(WTF::RangeSet::add):

Tools:

This makes us run a bunch of JS tests at optLevel=1 to force testing of this new compiler
pipeline.

* Scripts/run-jsc-stress-tests:</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="#trunkSourceJavaScriptCoreb3B3BasicBlockUtilsh">trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BlockWorklisth">trunk/Source/JavaScriptCore/b3/B3BlockWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CFGh">trunk/Source/JavaScriptCore/b3/B3CFG.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Commonh">trunk/Source/JavaScriptCore/b3/B3Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Compileh">trunk/Source/JavaScriptCore/b3/B3Compile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3DuplicateTailscpp">trunk/Source/JavaScriptCore/b3/B3DuplicateTails.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3EliminateCommonSubexpressionscpp">trunk/Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3FixSSAcpp">trunk/Source/JavaScriptCore/b3/B3FixSSA.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3FixSSAh">trunk/Source/JavaScriptCore/b3/B3FixSSA.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Generatecpp">trunk/Source/JavaScriptCore/b3/B3Generate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Generateh">trunk/Source/JavaScriptCore/b3/B3Generate.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3HeapRangeh">trunk/Source/JavaScriptCore/b3/B3HeapRange.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MoveConstantscpp">trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3PhiChildrenh">trunk/Source/JavaScriptCore/b3/B3PhiChildren.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp">trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3SSACalculatorh">trunk/Source/JavaScriptCore/b3/B3SSACalculator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3UseCountsh">trunk/Source/JavaScriptCore/b3/B3UseCounts.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateRegistersByGraphColoringcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirArgcpp">trunk/Source/JavaScriptCore/b3/air/AirArg.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirArgh">trunk/Source/JavaScriptCore/b3/air/AirArg.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirBasicBlockh">trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirBlockWorklisth">trunk/Source/JavaScriptCore/b3/air/AirBlockWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCFGh">trunk/Source/JavaScriptCore/b3/air/AirCFG.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirEliminateDeadCodecpp">trunk/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp">trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixPartialRegisterStallscpp">trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGenerateh">trunk/Source/JavaScriptCore/b3/air/AirGenerate.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGenerationContexth">trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInsertionSeth">trunk/Source/JavaScriptCore/b3/air/AirInsertionSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInstcpp">trunk/Source/JavaScriptCore/b3/air/AirInst.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp">trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLowerEntrySwitchcpp">trunk/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirRegLivenessh">trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp">trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirTmpcpp">trunk/Source/JavaScriptCore/b3/air/AirTmp.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirTmph">trunk/Source/JavaScriptCore/b3/air/AirTmp.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirTmpInlinesh">trunk/Source/JavaScriptCore/b3/air/AirTmpInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.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="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCMakeListstxt">trunk/Source/WTF/wtf/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWTFwtfDequeh">trunk/Source/WTF/wtf/Deque.h</a></li>
<li><a href="#trunkSourceWTFwtfIndexMaph">trunk/Source/WTF/wtf/IndexMap.h</a></li>
<li><a href="#trunkSourceWTFwtfIndexSeth">trunk/Source/WTF/wtf/IndexSet.h</a></li>
<li><a href="#trunkSourceWTFwtfRangeSeth">trunk/Source/WTF/wtf/RangeSet.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateRegistersByLinearScancpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateRegistersByLinearScanh">trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixSpillsAfterTerminalscpp">trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixSpillsAfterTerminalsh">trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirPhaseInsertionSetcpp">trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirPhaseInsertionSeth">trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.h</a></li>
<li><a href="#trunkSourceWTFwtfIndexKeyTypeh">trunk/Source/WTF/wtf/IndexKeyType.h</a></li>
<li><a href="#trunkSourceWTFwtfRangeh">trunk/Source/WTF/wtf/Range.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3B3HeapRangecpp">trunk/Source/JavaScriptCore/b3/B3HeapRange.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx">     assembler/MacroAssemblerX86Common.cpp
</span><span class="cx"> 
</span><span class="cx">     b3/air/AirAllocateRegistersByGraphColoring.cpp
</span><ins>+    b3/air/AirAllocateRegistersByLinearScan.cpp
</ins><span class="cx">     b3/air/AirAllocateStack.cpp
</span><span class="cx">     b3/air/AirArg.cpp
</span><span class="cx">     b3/air/AirBasicBlock.cpp
</span><span class="lines">@@ -88,6 +89,7 @@
</span><span class="cx">     b3/air/AirEmitShuffle.cpp
</span><span class="cx">     b3/air/AirFixObviousSpills.cpp
</span><span class="cx">     b3/air/AirFixPartialRegisterStalls.cpp
</span><ins>+    b3/air/AirFixSpillsAfterTerminals.cpp
</ins><span class="cx">     b3/air/AirGenerate.cpp
</span><span class="cx">     b3/air/AirGenerated.cpp
</span><span class="cx">     b3/air/AirHandleCalleeSaves.cpp
</span><span class="lines">@@ -100,6 +102,7 @@
</span><span class="cx">     b3/air/AirLowerMacros.cpp
</span><span class="cx">     b3/air/AirOptimizeBlockOrder.cpp
</span><span class="cx">     b3/air/AirPadInterference.cpp
</span><ins>+    b3/air/AirPhaseInsertionSet.cpp
</ins><span class="cx">     b3/air/AirPhaseScope.cpp
</span><span class="cx">     b3/air/AirRegLiveness.cpp
</span><span class="cx">     b3/air/AirReportUsedRegisters.cpp
</span><span class="lines">@@ -140,7 +143,6 @@
</span><span class="cx">     b3/B3FoldPathConstants.cpp
</span><span class="cx">     b3/B3FrequencyClass.cpp
</span><span class="cx">     b3/B3Generate.cpp
</span><del>-    b3/B3HeapRange.cpp
</del><span class="cx">     b3/B3InferSwitches.cpp
</span><span class="cx">     b3/B3InsertionSet.cpp
</span><span class="cx">     b3/B3Kind.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,3 +1,145 @@
</span><ins>+2017-03-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should support linear scan for optLevel&lt;2
+        https://bugs.webkit.org/show_bug.cgi?id=170161
+
+        Reviewed by Saam Barati.
+        
+        This changes the default opt level of B3 to 2. It makes the other opt levels useful by adding a
+        new register allocator. This new linear scan allocator will produce significantly worse code.
+        But it will produce that code a lot faster than IRC or Briggs.
+        
+        The opt levels are:
+            0: no optimizations, linear scan
+            1: some optimizations, linear scan
+            2: full optimizations, graph coloring (IRC or Briggs based on CPU)
+        
+        What we used to call optLevel=1 is not called optLevel=2, or better yet,
+        optLevel=B3::defaultOptLevel(). We no longer have anything like the old optLevel=0 (which did no
+        optimizations but ran graph coloring).
+        
+        allocateRegistersByLinearScan() faithfully implements Massimiliano Poletto and Vivek Sarkar's
+        famous algorithm. It uses the variant that handles clobbered registers by avoiding assigning
+        ranges to those registers if the range overlaps a clobber. It's engineered to allocate registers
+        very quickly and generate inefficient code without falling off a cliff.
+        
+        The new optLevel=1 speeds up B3 by a factor of 2, and results in a 80% throughput regression.
+        Linear scan runs 4.7x faster than graph coloring on average.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3BasicBlockUtils.h:
+        (JSC::B3::blocksInPreOrder):
+        (JSC::B3::blocksInPostOrder):
+        * b3/B3BlockWorklist.h:
+        * b3/B3CFG.h:
+        (JSC::B3::CFG::newMap):
+        * b3/B3Common.h:
+        (JSC::B3::defaultOptLevel):
+        * b3/B3Compile.h:
+        * b3/B3DuplicateTails.cpp:
+        * b3/B3EliminateCommonSubexpressions.cpp:
+        * b3/B3FixSSA.cpp:
+        (JSC::B3::demoteValues):
+        (JSC::B3::fixSSA):
+        * b3/B3FixSSA.h:
+        * b3/B3Generate.cpp:
+        (JSC::B3::prepareForGeneration):
+        (JSC::B3::generateToAir):
+        * b3/B3Generate.h:
+        * b3/B3HeapRange.cpp: Removed.
+        * b3/B3HeapRange.h:
+        (JSC::B3::HeapRange::HeapRange): Deleted.
+        (JSC::B3::HeapRange::top): Deleted.
+        (JSC::B3::HeapRange::operator==): Deleted.
+        (JSC::B3::HeapRange::operator!=): Deleted.
+        (JSC::B3::HeapRange::operator|): Deleted.
+        (JSC::B3::HeapRange::operator bool): Deleted.
+        (JSC::B3::HeapRange::begin): Deleted.
+        (JSC::B3::HeapRange::end): Deleted.
+        (JSC::B3::HeapRange::overlaps): Deleted.
+        * b3/B3LowerToAir.cpp:
+        * b3/B3MoveConstants.cpp:
+        * b3/B3PhiChildren.h:
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::dump):
+        (JSC::B3::Procedure::deleteOrphans):
+        (JSC::B3::Procedure::setBlockOrderImpl):
+        * b3/B3ReduceDoubleToFloat.cpp:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3SSACalculator.h:
+        * b3/B3UseCounts.h:
+        * b3/air/AirAllocateRegistersByGraphColoring.cpp:
+        * b3/air/AirAllocateRegistersByLinearScan.cpp: Added.
+        (JSC::B3::Air::allocateRegistersByLinearScan):
+        * b3/air/AirAllocateRegistersByLinearScan.h: Added.
+        * b3/air/AirAllocateStack.cpp:
+        (JSC::B3::Air::allocateStack):
+        * b3/air/AirArg.cpp:
+        (WTF::printInternal):
+        * b3/air/AirArg.h:
+        (JSC::B3::Air::Arg::activeAt):
+        (JSC::B3::Air::Arg::timing):
+        (JSC::B3::Air::Arg::forEachPhase):
+        * b3/air/AirBasicBlock.h:
+        * b3/air/AirBlockWorklist.h:
+        * b3/air/AirCFG.h:
+        (JSC::B3::Air::CFG::newMap):
+        * b3/air/AirEliminateDeadCode.cpp:
+        (JSC::B3::Air::eliminateDeadCode):
+        * b3/air/AirFixObviousSpills.cpp:
+        * b3/air/AirFixPartialRegisterStalls.cpp:
+        (JSC::B3::Air::fixPartialRegisterStalls):
+        * b3/air/AirFixSpillsAfterTerminals.cpp: Added.
+        (JSC::B3::Air::fixSpillsAfterTerminals):
+        * b3/air/AirFixSpillsAfterTerminals.h: Added.
+        * b3/air/AirGenerate.cpp:
+        (JSC::B3::Air::prepareForGeneration):
+        (JSC::B3::Air::generate):
+        * b3/air/AirGenerate.h:
+        * b3/air/AirGenerationContext.h:
+        * b3/air/AirInsertionSet.h:
+        * b3/air/AirInst.cpp:
+        (JSC::B3::Air::Inst::needsPadding):
+        * b3/air/AirLowerAfterRegAlloc.cpp:
+        (JSC::B3::Air::lowerAfterRegAlloc):
+        * b3/air/AirLowerEntrySwitch.cpp:
+        (JSC::B3::Air::lowerEntrySwitch):
+        * b3/air/AirOpcode.opcodes:
+        * b3/air/AirPhaseInsertionSet.cpp: Added.
+        (JSC::B3::Air::PhaseInsertionSet::execute):
+        * b3/air/AirPhaseInsertionSet.h: Added.
+        (JSC::B3::Air::PhaseInsertion::PhaseInsertion):
+        (JSC::B3::Air::PhaseInsertion::phase):
+        (JSC::B3::Air::PhaseInsertion::operator&lt;):
+        (JSC::B3::Air::PhaseInsertionSet::PhaseInsertionSet):
+        (JSC::B3::Air::PhaseInsertionSet::appendInsertion):
+        (JSC::B3::Air::PhaseInsertionSet::insertInst):
+        (JSC::B3::Air::PhaseInsertionSet::insert):
+        * b3/air/AirRegLiveness.h:
+        (JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
+        * b3/air/AirSpillEverything.cpp:
+        (JSC::B3::Air::spillEverything):
+        * b3/air/AirTmp.cpp:
+        * b3/air/AirTmp.h:
+        (JSC::B3::Air::Tmp::tmpForIndex):
+        * b3/air/AirTmpInlines.h:
+        (JSC::B3::Air::Tmp::Indexed::Indexed):
+        (JSC::B3::Air::Tmp::Indexed::index):
+        (JSC::B3::Air::Tmp::AbsolutelyIndexed::AbsolutelyIndexed):
+        (JSC::B3::Air::Tmp::AbsolutelyIndexed::index):
+        (JSC::B3::Air::Tmp::indexed):
+        (JSC::B3::Air::Tmp::absolutelyIndexed):
+        (JSC::B3::Air::Tmp::tmpForAbsoluteIndex):
+        * b3/testb3.cpp:
+        (JSC::B3::compile):
+        (JSC::B3::testMulLoadTwice):
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::add):
+        (JSC::RegisterSet::remove):
+        * runtime/Options.h:
+        * wasm/WasmB3IRGenerator.h:
+
</ins><span class="cx"> 2017-03-30  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clean up RTCDataChannel
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -183,6 +183,12 @@
</span><span class="cx">                 0F25F1B2181635F300522F39 /* FTLSlowPathCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F25F1AB181635F300522F39 /* FTLSlowPathCall.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F25F1B3181635F300522F39 /* FTLSlowPathCallKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F25F1AC181635F300522F39 /* FTLSlowPathCallKey.cpp */; };
</span><span class="cx">                 0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F25F1AD181635F300522F39 /* FTLSlowPathCallKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F2AC5661E8A0B770001EE3F /* AirFixSpillsAfterTerminals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2AC5641E8A0B760001EE3F /* AirFixSpillsAfterTerminals.cpp */; };
+                0F2AC5671E8A0B790001EE3F /* AirFixSpillsAfterTerminals.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5651E8A0B760001EE3F /* AirFixSpillsAfterTerminals.h */; };
+                0F2AC56A1E8A0BD30001EE3F /* AirAllocateRegistersByLinearScan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2AC5681E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.cpp */; };
+                0F2AC56B1E8A0BD50001EE3F /* AirAllocateRegistersByLinearScan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5691E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.h */; };
+                0F2AC56E1E8D7B000001EE3F /* AirPhaseInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2AC56C1E8D7AFF0001EE3F /* AirPhaseInsertionSet.cpp */; };
+                0F2AC56F1E8D7B030001EE3F /* AirPhaseInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC56D1E8D7AFF0001EE3F /* AirPhaseInsertionSet.h */; };
</ins><span class="cx">                 0F2B66AC17B6B53F00A7AE3F /* GCIncomingRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F2B66AD17B6B54500A7AE3F /* GCIncomingRefCountedInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F2B66AE17B6B54500A7AE3F /* GCIncomingRefCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66AA17B6B53D00A7AE3F /* GCIncomingRefCountedSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -969,7 +975,6 @@
</span><span class="cx">                 0FEC85BC1BE1462F0080FF74 /* B3ReduceStrength.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85B71BE1462F0080FF74 /* B3ReduceStrength.cpp */; };
</span><span class="cx">                 0FEC85BD1BE1462F0080FF74 /* B3ReduceStrength.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85B81BE1462F0080FF74 /* B3ReduceStrength.h */; };
</span><span class="cx">                 0FEC85C11BE167A00080FF74 /* B3Effects.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85BE1BE167A00080FF74 /* B3Effects.h */; };
</span><del>-                0FEC85C21BE167A00080FF74 /* B3HeapRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85BF1BE167A00080FF74 /* B3HeapRange.cpp */; };
</del><span class="cx">                 0FEC85C31BE167A00080FF74 /* B3HeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85C01BE167A00080FF74 /* B3HeapRange.h */; };
</span><span class="cx">                 0FEC85C51BE16F5A0080FF74 /* B3Effects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */; };
</span><span class="cx">                 0FED67B91B26256D0066CE15 /* DFGConstantHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FED67B71B26256D0066CE15 /* DFGConstantHoistingPhase.cpp */; };
</span><span class="lines">@@ -2710,6 +2715,12 @@
</span><span class="cx">                 0F25F1AB181635F300522F39 /* FTLSlowPathCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSlowPathCall.h; path = ftl/FTLSlowPathCall.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F25F1AC181635F300522F39 /* FTLSlowPathCallKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSlowPathCallKey.cpp; path = ftl/FTLSlowPathCallKey.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F25F1AD181635F300522F39 /* FTLSlowPathCallKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSlowPathCallKey.h; path = ftl/FTLSlowPathCallKey.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F2AC5641E8A0B760001EE3F /* AirFixSpillsAfterTerminals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirFixSpillsAfterTerminals.cpp; path = b3/air/AirFixSpillsAfterTerminals.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC5651E8A0B760001EE3F /* AirFixSpillsAfterTerminals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirFixSpillsAfterTerminals.h; path = b3/air/AirFixSpillsAfterTerminals.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC5681E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateRegistersByLinearScan.cpp; path = b3/air/AirAllocateRegistersByLinearScan.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC5691E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirAllocateRegistersByLinearScan.h; path = b3/air/AirAllocateRegistersByLinearScan.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC56C1E8D7AFF0001EE3F /* AirPhaseInsertionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirPhaseInsertionSet.cpp; path = b3/air/AirPhaseInsertionSet.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC56D1E8D7AFF0001EE3F /* AirPhaseInsertionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirPhaseInsertionSet.h; path = b3/air/AirPhaseInsertionSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCounted.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCountedInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2B66AA17B6B53D00A7AE3F /* GCIncomingRefCountedSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCountedSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3503,7 +3514,6 @@
</span><span class="cx">                 0FEC85B71BE1462F0080FF74 /* B3ReduceStrength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ReduceStrength.cpp; path = b3/B3ReduceStrength.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC85B81BE1462F0080FF74 /* B3ReduceStrength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ReduceStrength.h; path = b3/B3ReduceStrength.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC85BE1BE167A00080FF74 /* B3Effects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Effects.h; path = b3/B3Effects.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0FEC85BF1BE167A00080FF74 /* B3HeapRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3HeapRange.cpp; path = b3/B3HeapRange.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0FEC85C01BE167A00080FF74 /* B3HeapRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3HeapRange.h; path = b3/B3HeapRange.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Effects.cpp; path = b3/B3Effects.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FED67B71B26256D0066CE15 /* DFGConstantHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGConstantHoistingPhase.cpp; path = dfg/DFGConstantHoistingPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5433,7 +5443,6 @@
</span><span class="cx">                                 0FEC84CF1BDACDAC0080FF74 /* B3Generate.h */,
</span><span class="cx">                                 0F2C63B51E6343E800C13839 /* B3GenericBlockInsertionSet.h */,
</span><span class="cx">                                 0FEC84D01BDACDAC0080FF74 /* B3GenericFrequentedBlock.h */,
</span><del>-                                0FEC85BF1BE167A00080FF74 /* B3HeapRange.cpp */,
</del><span class="cx">                                 0FEC85C01BE167A00080FF74 /* B3HeapRange.h */,
</span><span class="cx">                                 DC69B99A1D15F90F002E3C00 /* B3InferSwitches.cpp */,
</span><span class="cx">                                 DC69B99B1D15F90F002E3C00 /* B3InferSwitches.h */,
</span><span class="lines">@@ -5544,6 +5553,8 @@
</span><span class="cx">                         children = (
</span><span class="cx">                                 7965C2141E5D799600B7591D /* AirAllocateRegistersByGraphColoring.cpp */,
</span><span class="cx">                                 7965C2151E5D799600B7591D /* AirAllocateRegistersByGraphColoring.h */,
</span><ins>+                                0F2AC5681E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.cpp */,
+                                0F2AC5691E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.h */,
</ins><span class="cx">                                 0FEC85481BDACDC70080FF74 /* AirAllocateStack.cpp */,
</span><span class="cx">                                 0FEC85491BDACDC70080FF74 /* AirAllocateStack.h */,
</span><span class="cx">                                 0FEC854A1BDACDC70080FF74 /* AirArg.cpp */,
</span><span class="lines">@@ -5575,6 +5586,8 @@
</span><span class="cx">                                 0F4DE1CD1C4C1B54004D6C11 /* AirFixObviousSpills.h */,
</span><span class="cx">                                 262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */,
</span><span class="cx">                                 262D85B51C0D650F006ACB61 /* AirFixPartialRegisterStalls.h */,
</span><ins>+                                0F2AC5641E8A0B760001EE3F /* AirFixSpillsAfterTerminals.cpp */,
+                                0F2AC5651E8A0B760001EE3F /* AirFixSpillsAfterTerminals.h */,
</ins><span class="cx">                                 0FEC85521BDACDC70080FF74 /* AirFrequentedBlock.h */,
</span><span class="cx">                                 0FEC85531BDACDC70080FF74 /* AirGenerate.cpp */,
</span><span class="cx">                                 0FEC85541BDACDC70080FF74 /* AirGenerate.h */,
</span><span class="lines">@@ -5603,6 +5616,8 @@
</span><span class="cx">                                 0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */,
</span><span class="cx">                                 0F9CABC61DB54A760008E83B /* AirPadInterference.cpp */,
</span><span class="cx">                                 0F9CABC71DB54A760008E83B /* AirPadInterference.h */,
</span><ins>+                                0F2AC56C1E8D7AFF0001EE3F /* AirPhaseInsertionSet.cpp */,
+                                0F2AC56D1E8D7AFF0001EE3F /* AirPhaseInsertionSet.h */,
</ins><span class="cx">                                 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */,
</span><span class="cx">                                 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */,
</span><span class="cx">                                 0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */,
</span><span class="lines">@@ -8160,6 +8175,7 @@
</span><span class="cx">                                 0FEC85101BDACDAC0080FF74 /* B3Const64Value.h in Headers */,
</span><span class="cx">                                 0FEC85121BDACDAC0080FF74 /* B3ConstDoubleValue.h in Headers */,
</span><span class="cx">                                 43422A631C158E6D00E2EB98 /* B3ConstFloatValue.h in Headers */,
</span><ins>+                                0F2AC56B1E8A0BD50001EE3F /* AirAllocateRegistersByLinearScan.h in Headers */,
</ins><span class="cx">                                 0FEC85B31BDED9570080FF74 /* B3ConstPtrValue.h in Headers */,
</span><span class="cx">                                 0F338DF61BE93D550013C88F /* B3ConstrainedValue.h in Headers */,
</span><span class="cx">                                 0F2C63B81E6343F700C13839 /* B3GenericBlockInsertionSet.h in Headers */,
</span><span class="lines">@@ -8393,6 +8409,7 @@
</span><span class="cx">                                 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */,
</span><span class="cx">                                 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */,
</span><span class="cx">                                 0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */,
</span><ins>+                                0F2AC56F1E8D7B030001EE3F /* AirPhaseInsertionSet.h in Headers */,
</ins><span class="cx">                                 A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
</span><span class="cx">                                 A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
</span><span class="cx">                                 0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
</span><span class="lines">@@ -9387,6 +9404,7 @@
</span><span class="cx">                                 709FB86A1AE335C60039D069 /* WeakSetConstructor.h in Headers */,
</span><span class="cx">                                 14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */,
</span><span class="cx">                                 709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
</span><ins>+                                0F2AC5671E8A0B790001EE3F /* AirFixSpillsAfterTerminals.h in Headers */,
</ins><span class="cx">                                 AD2FCBED1DB58DAD00B3E736 /* WebAssemblyCompileErrorConstructor.h in Headers */,
</span><span class="cx">                                 AD2FCC161DB59CB200B3E736 /* WebAssemblyCompileErrorConstructor.lut.h in Headers */,
</span><span class="cx">                                 AD2FCBEF1DB58DAD00B3E736 /* WebAssemblyCompileErrorPrototype.h in Headers */,
</span><span class="lines">@@ -10015,7 +10033,6 @@
</span><span class="cx">                                 0F725CAF1C506D3B00AD943A /* B3FoldPathConstants.cpp in Sources */,
</span><span class="cx">                                 0FEC85151BDACDAC0080FF74 /* B3FrequencyClass.cpp in Sources */,
</span><span class="cx">                                 0FEC85181BDACDAC0080FF74 /* B3Generate.cpp in Sources */,
</span><del>-                                0FEC85C21BE167A00080FF74 /* B3HeapRange.cpp in Sources */,
</del><span class="cx">                                 DC69B99C1D15F912002E3C00 /* B3InferSwitches.cpp in Sources */,
</span><span class="cx">                                 0FEC85B91BE1462F0080FF74 /* B3InsertionSet.cpp in Sources */,
</span><span class="cx">                                 0FDF67D31D9C6D2A001B9825 /* B3Kind.cpp in Sources */,
</span><span class="lines">@@ -10181,6 +10198,7 @@
</span><span class="cx">                                 A78A9776179738B8009DF744 /* DFGFinalizer.cpp in Sources */,
</span><span class="cx">                                 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */,
</span><span class="cx">                                 0F20177F1DCADC3300EA5950 /* DFGFlowIndexing.cpp in Sources */,
</span><ins>+                                0F2AC56A1E8A0BD30001EE3F /* AirAllocateRegistersByLinearScan.cpp in Sources */,
</ins><span class="cx">                                 0F9D339617FFC4E60073C2BC /* DFGFlushedAt.cpp in Sources */,
</span><span class="cx">                                 A7D89CF717A0B8CC00773AD8 /* DFGFlushFormat.cpp in Sources */,
</span><span class="cx">                                 0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */,
</span><span class="lines">@@ -10290,6 +10308,7 @@
</span><span class="cx">                                 2A83638518D7D0EE0000EBCC /* EdenGCActivityCallback.cpp in Sources */,
</span><span class="cx">                                 99E45A2518A1B2590026D88F /* EncodedValue.cpp in Sources */,
</span><span class="cx">                                 147F39C7107EC37600427A48 /* Error.cpp in Sources */,
</span><ins>+                                0F2AC5661E8A0B770001EE3F /* AirFixSpillsAfterTerminals.cpp in Sources */,
</ins><span class="cx">                                 147F39C8107EC37600427A48 /* ErrorConstructor.cpp in Sources */,
</span><span class="cx">                                 FEB58C14187B8B160098EF0B /* ErrorHandlingScope.cpp in Sources */,
</span><span class="cx">                                 147F39C9107EC37600427A48 /* ErrorInstance.cpp in Sources */,
</span><span class="lines">@@ -10407,6 +10426,7 @@
</span><span class="cx">                                 E35E035F1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp in Sources */,
</span><span class="cx">                                 A532438B18568335002ED692 /* InspectorProtocolObjects.cpp in Sources */,
</span><span class="cx">                                 A50E4B6118809DD50068A46D /* InspectorRuntimeAgent.cpp in Sources */,
</span><ins>+                                0F2AC56E1E8D7B000001EE3F /* AirPhaseInsertionSet.cpp in Sources */,
</ins><span class="cx">                                 0F2C63BB1E63440A00C13839 /* AirBlockInsertionSet.cpp in Sources */,
</span><span class="cx">                                 A55165D21BDF0B98003B75C1 /* InspectorScriptProfilerAgent.cpp in Sources */,
</span><span class="cx">                                 A593CF821840377100BFCE27 /* InspectorValues.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockUtilsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx"> Vector&lt;BasicBlock*&gt; blocksInPreOrder(BasicBlock* root)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;BasicBlock*&gt; result;
</span><del>-    GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; worklist;
</del><ins>+    GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; worklist;
</ins><span class="cx">     worklist.push(root);
</span><span class="cx">     while (BasicBlock* block = worklist.pop()) {
</span><span class="cx">         result.append(block);
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx"> Vector&lt;BasicBlock*&gt; blocksInPostOrder(BasicBlock* root)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;BasicBlock*&gt; result;
</span><del>-    PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; worklist;
</del><ins>+    PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; worklist;
</ins><span class="cx">     worklist.push(root);
</span><span class="cx">     while (GraphNodeWithOrder&lt;BasicBlock*&gt; item = worklist.pop()) {
</span><span class="cx">         switch (item.order) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BlockWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BlockWorklist.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BlockWorklist.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3BlockWorklist.h        2017-03-30 22:55:44 UTC (rev 214636)
</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-2017 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">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> class BasicBlock;
</span><span class="cx"> 
</span><del>-typedef GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; BlockWorklist;
</del><ins>+typedef GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; BlockWorklist;
</ins><span class="cx"> 
</span><span class="cx"> // When you say BlockWith&lt;int&gt; you should read it as &quot;block with an int&quot;.
</span><span class="cx"> template&lt;typename T&gt; using BlockWith = GraphNodeWith&lt;BasicBlock*, T&gt;;
</span><span class="lines">@@ -44,13 +44,13 @@
</span><span class="cx"> // permits forcibly enqueueing things even if the block has already been seen. It's useful for
</span><span class="cx"> // things like building a spanning tree, in which case T (the auxiliary payload) would be the
</span><span class="cx"> // successor index.
</span><del>-template&lt;typename T&gt; using ExtendedBlockWorklist = ExtendedGraphNodeWorklist&lt;BasicBlock*, T, IndexSet&lt;BasicBlock&gt;&gt;;
</del><ins>+template&lt;typename T&gt; using ExtendedBlockWorklist = ExtendedGraphNodeWorklist&lt;BasicBlock*, T, IndexSet&lt;BasicBlock*&gt;&gt;;
</ins><span class="cx"> 
</span><span class="cx"> typedef GraphVisitOrder VisitOrder;
</span><span class="cx"> 
</span><span class="cx"> typedef GraphNodeWithOrder&lt;BasicBlock*&gt; BlockWithOrder;
</span><span class="cx"> 
</span><del>-typedef PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; PostOrderBlockWorklist;
</del><ins>+typedef PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; PostOrderBlockWorklist;
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CFGh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CFG.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CFG.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3CFG.h        2017-03-30 22:55:44 UTC (rev 214636)
</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-2017 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">@@ -39,8 +39,8 @@
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     typedef BasicBlock* Node;
</span><del>-    typedef IndexSet&lt;BasicBlock&gt; Set;
-    template&lt;typename T&gt; using Map = IndexMap&lt;BasicBlock, T&gt;;
</del><ins>+    typedef IndexSet&lt;BasicBlock*&gt; Set;
+    template&lt;typename T&gt; using Map = IndexMap&lt;BasicBlock*, T&gt;;
</ins><span class="cx">     typedef Vector&lt;BasicBlock*, 4&gt; List;
</span><span class="cx"> 
</span><span class="cx">     CFG(Procedure&amp; proc)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">     Node root() { return m_proc[0]; }
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename T&gt;
</span><del>-    Map&lt;T&gt; newMap() { return IndexMap&lt;JSC::B3::BasicBlock, T&gt;(m_proc.size()); }
</del><ins>+    Map&lt;T&gt; newMap() { return IndexMap&lt;JSC::B3::BasicBlock*, T&gt;(m_proc.size()); }
</ins><span class="cx"> 
</span><span class="cx">     SuccessorCollection&lt;BasicBlock, BasicBlock::SuccessorList&gt; successors(Node node) { return node-&gt;successorBlocks(); }
</span><span class="cx">     BasicBlock::PredecessorList&amp; predecessors(Node node) { return node-&gt;predecessors(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Common.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Common.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3Common.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSExportMacros.h&quot;
</span><ins>+#include &quot;Options.h&quot;
</ins><span class="cx"> #include &lt;wtf/Optional.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="lines">@@ -170,6 +171,13 @@
</span><span class="cx">     return (uValue &lt;&lt; shift) | (uValue &gt;&gt; ((bits - shift) &amp; mask));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline unsigned defaultOptLevel()
+{
+    // This should almost always return 2, but we allow this default to be lowered for testing. Some
+    // components will deliberately set the optLevel.
+    return Options::defaultB3OptLevel();
+}
+
</ins><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Compileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Compile.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Compile.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3Compile.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3Common.h&quot;
</ins><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -45,7 +46,7 @@
</span><span class="cx"> // Then you keep the Compilation object alive for as long as you want to be able to run the code.
</span><span class="cx"> // If this API feels too high-level, you can use B3::generate() directly.
</span><span class="cx"> 
</span><del>-JS_EXPORT_PRIVATE Compilation compile(Procedure&amp;, unsigned optLevel = 1);
</del><ins>+JS_EXPORT_PRIVATE Compilation compile(Procedure&amp;, unsigned optLevel = defaultOptLevel());
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3DuplicateTailscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3DuplicateTails.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3DuplicateTails.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3DuplicateTails.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> 
</span><span class="cx">         m_proc.resetValueOwners();
</span><span class="cx"> 
</span><del>-        IndexSet&lt;BasicBlock&gt; candidates;
</del><ins>+        IndexSet&lt;BasicBlock*&gt; candidates;
</ins><span class="cx"> 
</span><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="cx">             if (block-&gt;size() &gt; m_maxSize)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Collect the set of values that must be de-SSA'd.
</span><del>-        IndexSet&lt;Value&gt; valuesToDemote;
</del><ins>+        IndexSet&lt;Value*&gt; valuesToDemote;
</ins><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="cx">             for (Value* value : *block) {
</span><span class="cx">                 if (value-&gt;opcode() == Phi &amp;&amp; candidates.contains(block))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3EliminateCommonSubexpressionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -682,7 +682,7 @@
</span><span class="cx">     Dominators&amp; m_dominators;
</span><span class="cx">     PureCSE m_pureCSE;
</span><span class="cx">     
</span><del>-    IndexMap&lt;BasicBlock, ImpureBlockData&gt; m_impureBlockData;
</del><ins>+    IndexMap&lt;BasicBlock*, ImpureBlockData&gt; m_impureBlockData;
</ins><span class="cx"> 
</span><span class="cx">     ImpureBlockData m_data;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3FixSSAcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3FixSSA.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3FixSSA.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3FixSSA.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> const bool verbose = false;
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><del>-void demoteValues(Procedure&amp; proc, const IndexSet&lt;Value&gt;&amp; values)
</del><ins>+void demoteValues(Procedure&amp; proc, const IndexSet&lt;Value*&gt;&amp; values)
</ins><span class="cx"> {
</span><span class="cx">     HashMap&lt;Value*, Variable*&gt; map;
</span><span class="cx">     HashMap&lt;Value*, Variable*&gt; phiMap;
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx">     // Just for sanity, remove any unused variables first. It's unlikely that this code has any
</span><span class="cx">     // bugs having to do with dead variables, but it would be silly to have to fix such a bug if
</span><span class="cx">     // it did arise.
</span><del>-    IndexSet&lt;Variable&gt; liveVariables;
</del><ins>+    IndexSet&lt;Variable*&gt; liveVariables;
</ins><span class="cx">     for (Value* value : proc.values()) {
</span><span class="cx">         if (VariableValue* variableValue = value-&gt;as&lt;VariableValue&gt;())
</span><span class="cx">             liveVariables.add(variableValue-&gt;variable());
</span><span class="lines">@@ -145,7 +145,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Create a SSACalculator::Variable (&quot;calcVar&quot;) for every variable.
</span><span class="cx">     Vector&lt;Variable*&gt; calcVarToVariable;
</span><del>-    IndexMap&lt;Variable, SSACalculator::Variable*&gt; variableToCalcVar(proc.variables().size());
</del><ins>+    IndexMap&lt;Variable*, SSACalculator::Variable*&gt; variableToCalcVar(proc.variables().size());
</ins><span class="cx"> 
</span><span class="cx">     for (Variable* variable : proc.variables()) {
</span><span class="cx">         SSACalculator::Variable* calcVar = ssa.newVariable();
</span><span class="lines">@@ -185,7 +185,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Now perform the conversion.
</span><span class="cx">     InsertionSet insertionSet(proc);
</span><del>-    IndexMap&lt;Variable, Value*&gt; mapping(proc.variables().size());
</del><ins>+    IndexMap&lt;Variable*, Value*&gt; mapping(proc.variables().size());
</ins><span class="cx">     for (BasicBlock* block : proc.blocksInPreOrder()) {
</span><span class="cx">         mapping.clear();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3FixSSAh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3FixSSA.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3FixSSA.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3FixSSA.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -37,7 +37,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Turns all mentions of the given values into accesses to variables. This is meant to be used
</span><span class="cx"> // from phases that don't like SSA for whatever reason.
</span><del>-void demoteValues(Procedure&amp;, const IndexSet&lt;Value&gt;&amp;);
</del><ins>+void demoteValues(Procedure&amp;, const IndexSet&lt;Value*&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx"> // This fixes SSA for you. Use this after you have done demoteValues() and you have performed
</span><span class="cx"> // whatever evil transformation you needed.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">     TimingScope timingScope(&quot;prepareForGeneration&quot;);
</span><span class="cx"> 
</span><span class="cx">     generateToAir(procedure, optLevel);
</span><del>-    Air::prepareForGeneration(procedure.code());
</del><ins>+    Air::prepareForGeneration(procedure.code(), optLevel);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void generate(Procedure&amp; procedure, CCallHelpers&amp; jit)
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">     if (shouldValidateIR())
</span><span class="cx">         validate(procedure);
</span><span class="cx"> 
</span><del>-    if (optLevel &gt;= 1) {
</del><ins>+    if (optLevel &gt;= 2) {
</ins><span class="cx">         reduceDoubleToFloat(procedure);
</span><span class="cx">         reduceStrength(procedure);
</span><span class="cx">         eliminateCommonSubexpressions(procedure);
</span><span class="lines">@@ -91,12 +91,15 @@
</span><span class="cx">         
</span><span class="cx">         // FIXME: Add more optimizations here.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=150507
</span><ins>+    } else if (optLevel &gt;= 1) {
+        // FIXME: Explore better &quot;quick mode&quot; optimizations.
+        reduceStrength(procedure);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // This puts the IR in quirks mode.
</span><span class="cx">     lowerMacros(procedure);
</span><span class="cx"> 
</span><del>-    if (optLevel &gt;= 1) {
</del><ins>+    if (optLevel &gt;= 2) {
</ins><span class="cx">         reduceStrength(procedure);
</span><span class="cx"> 
</span><span class="cx">         // FIXME: Add more optimizations here.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -27,6 +27,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3Common.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CCallHelpers;
</span><span class="lines">@@ -38,7 +40,7 @@
</span><span class="cx"> 
</span><span class="cx"> // This takes a B3::Procedure, optimizes it in-place, lowers it to Air, and prepares the Air for
</span><span class="cx"> // generation.
</span><del>-JS_EXPORT_PRIVATE void prepareForGeneration(Procedure&amp;, unsigned optLevel = 1);
</del><ins>+JS_EXPORT_PRIVATE void prepareForGeneration(Procedure&amp;, unsigned optLevel = defaultOptLevel());
</ins><span class="cx"> 
</span><span class="cx"> // This takes a B3::Procedure that has been prepared for generation (i.e. it has been lowered to Air and
</span><span class="cx"> // the Air has been prepared for generation) and generates it. This is the equivalent of calling
</span><span class="lines">@@ -48,7 +50,7 @@
</span><span class="cx"> // This takes a B3::Procedure, optimizes it in-place, and lowers it to Air. You can then generate
</span><span class="cx"> // the Air to machine code using Air::prepareForGeneration() and Air::generate() on the Procedure's
</span><span class="cx"> // code().
</span><del>-void generateToAir(Procedure&amp;, unsigned optLevel = 1);
</del><ins>+void generateToAir(Procedure&amp;, unsigned optLevel = defaultOptLevel());
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3HeapRangecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/B3HeapRange.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3HeapRange.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3HeapRange.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,49 +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. 
- */
-
-#include &quot;config.h&quot;
-#include &quot;B3HeapRange.h&quot;
-
-#if ENABLE(B3_JIT)
-
-namespace JSC { namespace B3 {
-
-void HeapRange::dump(PrintStream&amp; out) const
-{
-    if (*this == HeapRange()) {
-        out.print(&quot;Bottom&quot;);
-        return;
-    }
-    if (*this == top()) {
-        out.print(&quot;Top&quot;);
-        return;
-    }
-    out.print(m_begin, &quot;...&quot;, m_end);
-}
-
-} } // namespace JSC::B3
-
-#endif // ENABLE(B3_JIT)
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3HeapRangeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3HeapRange.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3HeapRange.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3HeapRange.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -27,9 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><del>-#include &lt;limits.h&gt;
-#include &lt;wtf/MathExtras.h&gt;
-#include &lt;wtf/PrintStream.h&gt;
</del><ins>+#include &lt;wtf/Range.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><span class="lines">@@ -36,82 +34,9 @@
</span><span class="cx"> // Alias analysis in B3 is done by checking if two integer ranges overlap. This is powerful enough
</span><span class="cx"> // to be used for TBAA-style alias analysis used by the DFG, FTL, and LLVM: you just turn each node
</span><span class="cx"> // in the tree of abstract heaps into a pre/post range.
</span><del>-//
-// Note that the 'begin' is inclusive, while the 'end' is exclusive. These two ranges are non-
-// overlapping:
-//
-//     rangeA = 0...8
-//     rangeB = 8...16
</del><span class="cx"> 
</span><del>-class HeapRange {
-public:
-    typedef unsigned Type;
-    
-    HeapRange()
-        : m_begin(0)
-        , m_end(0)
-    {
-    }
</del><ins>+typedef Range&lt;unsigned&gt; HeapRange;
</ins><span class="cx"> 
</span><del>-    explicit HeapRange(unsigned value)
-        : m_begin(value)
-        , m_end(value + 1)
-    {
-        ASSERT(m_end &gt;= m_begin);
-    }
-
-    HeapRange(unsigned begin, unsigned end)
-        : m_begin(begin)
-        , m_end(end)
-    {
-        ASSERT(m_end &gt;= m_begin);
-        if (m_begin == m_end) {
-            // Canonicalize empty ranges.
-            m_begin = 0;
-            m_end = 0;
-        }
-    }
-
-    static HeapRange top()
-    {
-        return HeapRange(0, UINT_MAX);
-    }
-
-    bool operator==(const HeapRange&amp; other) const
-    {
-        return m_begin == other.m_begin
-            &amp;&amp; m_end == other.m_end;
-    }
-
-    bool operator!=(const HeapRange&amp; other) const
-    {
-        return !(*this == other);
-    }
-    
-    HeapRange operator|(const HeapRange&amp; other) const
-    {
-        return HeapRange(
-            std::min(m_begin, other.m_begin),
-            std::max(m_end, other.m_end));
-    }
-    
-    explicit operator bool() const { return m_begin != m_end; }
-
-    unsigned begin() const { return m_begin; }
-    unsigned end() const { return m_end; }
-
-    bool overlaps(const HeapRange&amp; other) const
-    {
-        return WTF::rangesOverlap(m_begin, m_end, other.m_begin, other.m_end);
-    }
-
-    JS_EXPORT_PRIVATE void dump(PrintStream&amp; out) const;
-
-private:
-    unsigned m_begin;
-    unsigned m_end;
-};
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -3379,10 +3379,10 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    IndexSet&lt;Value&gt; m_locked; // These are values that will have no Tmp in Air.
-    IndexMap&lt;Value, Tmp&gt; m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is &quot;pinned&quot;.
-    IndexMap&lt;Value, Tmp&gt; m_phiToTmp; // Each Phi gets its own Tmp.
-    IndexMap&lt;B3::BasicBlock, Air::BasicBlock*&gt; m_blockToBlock;
</del><ins>+    IndexSet&lt;Value*&gt; m_locked; // These are values that will have no Tmp in Air.
+    IndexMap&lt;Value*, Tmp&gt; m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is &quot;pinned&quot;.
+    IndexMap&lt;Value*, Tmp&gt; m_phiToTmp; // Each Phi gets its own Tmp.
+    IndexMap&lt;B3::BasicBlock*, Air::BasicBlock*&gt; m_blockToBlock;
</ins><span class="cx">     HashMap&lt;B3::StackSlot*, Air::StackSlot*&gt; m_stackToStack;
</span><span class="cx">     HashMap&lt;Variable*, Tmp&gt; m_variableToTmp;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MoveConstantscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     {
</span><span class="cx">         Dominators&amp; dominators = m_proc.dominators();
</span><span class="cx">         HashMap&lt;ValueKey, Value*&gt; valueForConstant;
</span><del>-        IndexMap&lt;BasicBlock, Vector&lt;Value*&gt;&gt; materializations(m_proc.size());
</del><ins>+        IndexMap&lt;BasicBlock*, Vector&lt;Value*&gt;&gt; materializations(m_proc.size());
</ins><span class="cx"> 
</span><span class="cx">         // We determine where things get materialized based on where they are used.
</span><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="lines">@@ -274,7 +274,7 @@
</span><span class="cx">         for (auto&amp; entry : m_constTable)
</span><span class="cx">             m_dataSection[entry.value] = entry.key.value();
</span><span class="cx"> 
</span><del>-        IndexSet&lt;Value&gt; offLimits;
</del><ins>+        IndexSet&lt;Value*&gt; offLimits;
</ins><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="cx">             for (unsigned valueIndex = 0; valueIndex &lt; block-&gt;size(); ++valueIndex) {
</span><span class="cx">                 StackmapValue* value = block-&gt;at(valueIndex)-&gt;as&lt;StackmapValue&gt;();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PhiChildrenh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3PhiChildren.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PhiChildren.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3PhiChildren.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -168,7 +168,7 @@
</span><span class="cx">     const Vector&lt;Value*, 8&gt;&amp; phis() const { return m_phis; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    IndexMap&lt;Value, Vector&lt;UpsilonValue*&gt;&gt; m_upsilons;
</del><ins>+    IndexMap&lt;Value*, Vector&lt;UpsilonValue*&gt;&gt; m_upsilons;
</ins><span class="cx">     Vector&lt;Value*, 8&gt; m_phis;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -204,7 +204,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Procedure::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><del>-    IndexSet&lt;Value&gt; valuesInBlocks;
</del><ins>+    IndexSet&lt;Value*&gt; valuesInBlocks;
</ins><span class="cx">     for (BasicBlock* block : *this) {
</span><span class="cx">         out.print(deepDump(*this, block));
</span><span class="cx">         valuesInBlocks.addAll(*block);
</span><span class="lines">@@ -263,7 +263,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Procedure::deleteOrphans()
</span><span class="cx"> {
</span><del>-    IndexSet&lt;Value&gt; valuesInBlocks;
</del><ins>+    IndexSet&lt;Value*&gt; valuesInBlocks;
</ins><span class="cx">     for (BasicBlock* block : *this)
</span><span class="cx">         valuesInBlocks.addAll(*block);
</span><span class="cx"> 
</span><span class="lines">@@ -351,7 +351,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Procedure::setBlockOrderImpl(Vector&lt;BasicBlock*&gt;&amp; blocks)
</span><span class="cx"> {
</span><del>-    IndexSet&lt;BasicBlock&gt; blocksSet;
</del><ins>+    IndexSet&lt;BasicBlock*&gt; blocksSet;
</ins><span class="cx">     blocksSet.addAll(blocks);
</span><span class="cx"> 
</span><span class="cx">     for (BasicBlock* block : *this) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -424,18 +424,18 @@
</span><span class="cx"> 
</span><span class="cx">     // Set of all the Double values that are actually used as Double.
</span><span class="cx">     // Converting any of them to Float would lose precision.
</span><del>-    IndexSet&lt;Value&gt; m_valuesUsedAsDouble;
</del><ins>+    IndexSet&lt;Value*&gt; m_valuesUsedAsDouble;
</ins><span class="cx"> 
</span><span class="cx">     // Set of all the Phi of type Double that really contains a Double.
</span><span class="cx">     // Any Double Phi not in the set can be converted to Float without losing precision.
</span><del>-    IndexSet&lt;Value&gt; m_phisContainingDouble;
</del><ins>+    IndexSet&lt;Value*&gt; m_phisContainingDouble;
</ins><span class="cx"> 
</span><span class="cx">     // Any value that was converted from producing a Double to producing a Float.
</span><span class="cx">     // This set does not include Phi-Upsilons.
</span><del>-    IndexSet&lt;Value&gt; m_convertedValue;
</del><ins>+    IndexSet&lt;Value*&gt; m_convertedValue;
</ins><span class="cx"> 
</span><span class="cx">     // Any value that previously produced Double and now produce Float.
</span><del>-    IndexSet&lt;Value&gt; m_convertedPhis;
</del><ins>+    IndexSet&lt;Value*&gt; m_convertedPhis;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void printGraphIfConverting(Procedure&amp; procedure)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -2392,7 +2392,7 @@
</span><span class="cx"> 
</span><span class="cx">     void killDeadCode()
</span><span class="cx">     {
</span><del>-        GraphNodeWorklist&lt;Value*, IndexSet&lt;Value&gt;&gt; worklist;
</del><ins>+        GraphNodeWorklist&lt;Value*, IndexSet&lt;Value*&gt;&gt; worklist;
</ins><span class="cx">         Vector&lt;UpsilonValue*, 64&gt; upsilons;
</span><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="cx">             for (Value* value : *block) {
</span><span class="lines">@@ -2429,7 +2429,7 @@
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        IndexSet&lt;Variable&gt; liveVariables;
</del><ins>+        IndexSet&lt;Variable*&gt; liveVariables;
</ins><span class="cx">         
</span><span class="cx">         for (BasicBlock* block : m_proc) {
</span><span class="cx">             size_t sourceIndex = 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3SSACalculatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3SSACalculator.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3SSACalculator.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3SSACalculator.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -156,7 +156,7 @@
</span><span class="cx">         Vector&lt;Def*&gt; m_phis;
</span><span class="cx">     };
</span><span class="cx">     
</span><del>-    IndexMap&lt;BasicBlock, BlockData&gt; m_data;
</del><ins>+    IndexMap&lt;BasicBlock*, BlockData&gt; m_data;
</ins><span class="cx"> 
</span><span class="cx">     Dominators* m_dominators { nullptr };
</span><span class="cx">     Procedure&amp; m_proc;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3UseCountsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3UseCounts.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3UseCounts.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/B3UseCounts.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 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">@@ -48,7 +48,7 @@
</span><span class="cx">         unsigned numUsingInstructions { 0 };
</span><span class="cx">     };
</span><span class="cx">     
</span><del>-    IndexMap&lt;Value, Counts&gt; m_counts;
</del><ins>+    IndexMap&lt;Value*, Counts&gt; m_counts;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateRegistersByGraphColoringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</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;AirFixSpillsAfterTerminals.h&quot;
</ins><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">@@ -1585,6 +1586,9 @@
</span><span class="cx">         m_coalescingCandidates.clear();
</span><span class="cx">         m_worklistMoves.clear();
</span><span class="cx"> 
</span><ins>+        // FIXME: It seems like we don't need to recompute liveness. We just need to update its data
+        // structures so that it knows that the newly introduced temporaries are not live at any basic
+        // block boundary. This should trivially be true for now.
</ins><span class="cx">         TmpLiveness&lt;bank&gt; liveness(m_code);
</span><span class="cx">         for (BasicBlock* block : m_code) {
</span><span class="cx">             typename TmpLiveness&lt;bank&gt;::LocalCalc localCalc(liveness, block);
</span><span class="lines">@@ -1798,7 +1802,7 @@
</span><span class="cx">         m_numIterations = 0;
</span><span class="cx">         allocateOnBank&lt;FP&gt;();
</span><span class="cx"> 
</span><del>-        fixSpillsAfterTerminals();
</del><ins>+        fixSpillsAfterTerminals(m_code);
</ins><span class="cx"> 
</span><span class="cx">         if (reportStats)
</span><span class="cx">             dataLog(&quot;Num iterations = &quot;, m_numIterations, &quot;\n&quot;);
</span><span class="lines">@@ -1954,7 +1958,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 inst.forEachTmpFast([&amp;] (Tmp&amp; tmp) {
</span><del>-                    if (tmp.isReg() || tmp.isGP() == (bank != GP))
</del><ins>+                    if (tmp.isReg() || tmp.bank() != bank)
</ins><span class="cx">                         return;
</span><span class="cx"> 
</span><span class="cx">                     Tmp aliasTmp = allocator.getAlias(tmp);
</span><span class="lines">@@ -2132,7 +2136,7 @@
</span><span class="cx">                     // other. As well, we need this if the previous instruction had any late effects,
</span><span class="cx">                     // since otherwise the scratch would appear to interfere with those. On the other
</span><span class="cx">                     // hand, the late use added at the end of this spill move (previously it was just a
</span><del>-                    // late def) doesn't change the padding situation: the late def would have already
</del><ins>+                    // late def) doesn't change the padding situation.: the late def would have already
</ins><span class="cx">                     // caused it to report hasLateUseOrDef in Inst::needsPadding.
</span><span class="cx">                     insertionSet.insert(instIndex, Nop, inst.origin);
</span><span class="cx">                     continue;
</span><span class="lines">@@ -2169,9 +2173,12 @@
</span><span class="cx"> 
</span><span class="cx">                     tmp = m_code.newTmp(bank);
</span><span class="cx">                     unspillableTmps.add(AbsoluteTmpMapper&lt;bank&gt;::absoluteIndex(tmp));
</span><ins>+                    
+                    if (role == Arg::Scratch)
+                        return;
</ins><span class="cx"> 
</span><span class="cx">                     Arg arg = Arg::stack(stackSlotEntry-&gt;value);
</span><del>-                    if (Arg::isAnyUse(role) &amp;&amp; role != Arg::Scratch)
</del><ins>+                    if (Arg::isAnyUse(role))
</ins><span class="cx">                         insertionSet.insert(instIndex, move, inst.origin, arg, tmp);
</span><span class="cx">                     if (Arg::isAnyDef(role))
</span><span class="cx">                         insertionSet.insert(instIndex + 1, move, inst.origin, tmp, arg);
</span><span class="lines">@@ -2187,66 +2194,6 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void fixSpillsAfterTerminals()
-    {
-        // Because there may be terminals that produce values, IRC may
-        // want to spill those terminals. It'll happen to spill it after
-        // the terminal. If we left the graph in this state, it'd be invalid
-        // because a terminal must be the last instruction in a block.
-        // We fix that here.
-
-        InsertionSet insertionSet(m_code);
-
-        bool addedBlocks = false;
-
-        for (BasicBlock* block : m_code) {
-            unsigned terminalIndex = block-&gt;size();
-            bool foundTerminal = false;
-            while (terminalIndex--) {
-                if (block-&gt;at(terminalIndex).isTerminal()) {
-                    foundTerminal = true;
-                    break;
-                }
-            }
-            ASSERT_UNUSED(foundTerminal, foundTerminal);
-
-            if (terminalIndex == block-&gt;size() - 1)
-                continue;
-
-            // There must be instructions after the terminal because it's not the last instruction.
-            ASSERT(terminalIndex &lt; block-&gt;size() - 1);
-            Vector&lt;Inst, 1&gt; instsToMove;
-            for (unsigned i = terminalIndex + 1; i &lt; block-&gt;size(); i++)
-                instsToMove.append(block-&gt;at(i));
-            RELEASE_ASSERT(instsToMove.size());
-
-            for (FrequentedBlock&amp; frequentedSuccessor : block-&gt;successors()) {
-                BasicBlock* successor = frequentedSuccessor.block();
-                // If successor's only predecessor is block, we can plant the spill inside
-                // the successor. Otherwise, we must split the critical edge and create
-                // a new block for the spill.
-                if (successor-&gt;numPredecessors() == 1) {
-                    insertionSet.insertInsts(0, instsToMove);
-                    insertionSet.execute(successor);
-                } else {
-                    addedBlocks = true;
-                    // FIXME: We probably want better block ordering here.
-                    BasicBlock* newBlock = m_code.addBlock();
-                    for (const Inst&amp; inst : instsToMove)
-                        newBlock-&gt;appendInst(inst);
-                    newBlock-&gt;appendInst(Inst(Jump, instsToMove.last().origin));
-                    newBlock-&gt;successors().append(successor);
-                    frequentedSuccessor.block() = newBlock;
-                }
-            }
-
-            block-&gt;resize(terminalIndex + 1);
-        }
-
-        if (addedBlocks)
-            m_code.resetReachability();
-    }
-
</del><span class="cx">     Code&amp; m_code;
</span><span class="cx">     TmpWidth m_tmpWidth;
</span><span class="cx">     UseCounts&lt;Tmp&gt;&amp; m_useCounts;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateRegistersByLinearScancpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.cpp (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,594 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;AirAllocateRegistersByLinearScan.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirArgInlines.h&quot;
+#include &quot;AirCode.h&quot;
+#include &quot;AirFixSpillsAfterTerminals.h&quot;
+#include &quot;AirPhaseInsertionSet.h&quot;
+#include &quot;AirInstInlines.h&quot;
+#include &quot;AirLiveness.h&quot;
+#include &quot;AirPadInterference.h&quot;
+#include &quot;AirPhaseScope.h&quot;
+#include &quot;AirRegLiveness.h&quot;
+#include &quot;AirTmpInlines.h&quot;
+#include &lt;wtf/ListDump.h&gt;
+#include &lt;wtf/Range.h&gt;
+
+namespace JSC { namespace B3 { namespace Air {
+
+namespace {
+
+NO_RETURN_DUE_TO_CRASH NEVER_INLINE void crash()
+{
+    CRASH();
+}
+
+#undef RELEASE_ASSERT
+#define RELEASE_ASSERT(assertion) do { \
+    if (!(assertion)) { \
+        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
+        crash(); \
+    } \
+} while (0)
+
+bool verbose() { return Options::airLinearScanVerbose(); }
+
+// Phase constants we use for the PhaseInsertionSet.
+const unsigned firstPhase = 0;
+const unsigned secondPhase = 1;
+
+typedef Range&lt;size_t&gt; Interval;
+
+struct TmpData {
+    void dump(PrintStream&amp; out) const
+    {
+        out.print(&quot;{interval = &quot;, interval, &quot;, spilled = &quot;, pointerDump(spilled), &quot;, assigned = &quot;, assigned, &quot;, isUnspillable = &quot;, isUnspillable, &quot;, possibleRegs = &quot;, possibleRegs, &quot;, didBuildPossibleRegs = &quot;, didBuildPossibleRegs, &quot;}&quot;);
+    }
+    
+    void validate()
+    {
+        RELEASE_ASSERT(!(spilled &amp;&amp; assigned));
+    }
+    
+    Interval interval;
+    StackSlot* spilled { nullptr };
+    RegisterSet possibleRegs;
+    Reg assigned;
+    bool isUnspillable { false };
+    bool didBuildPossibleRegs { false };
+};
+
+struct Clobber {
+    Clobber()
+    {
+    }
+    
+    Clobber(size_t index, RegisterSet regs)
+        : index(index)
+        , regs(regs)
+    {
+    }
+    
+    void dump(PrintStream&amp; out) const
+    {
+        out.print(index, &quot;:&quot;, regs);
+    }
+    
+    size_t index { 0 };
+    RegisterSet regs;
+};
+
+template&lt;Bank bank&gt;
+class LinearScan {
+public:
+    LinearScan(Code&amp; code)
+        : m_code(code)
+        , m_startIndex(code.size())
+        , m_map(code.numTmps(bank))
+        , m_insertionSets(code.size())
+    {
+    }
+    
+    void run()
+    {
+        buildRegisterSet();
+        buildIndices();
+        buildIntervals();
+        if (shouldSpillEverything()) {
+            spillEverything();
+            emitSpillCode();
+        }
+        for (;;) {
+            prepareIntervals();
+            attemptScan();
+            if (!m_didSpill)
+                break;
+            emitSpillCode();
+        }
+        insertSpillCode();
+        assignRegisters();
+    }
+    
+private:
+    void buildRegisterSet()
+    {
+        m_registers = m_code.regsInPriorityOrder(bank);
+        m_registerSet.setAll(m_registers);
+    }
+
+    void buildIndices()
+    {
+        size_t index = 0;
+        for (BasicBlock* block : m_code) {
+            m_startIndex[block] = index;
+            index += block-&gt;size() * 2;
+        }
+    }
+    
+    size_t indexOfHead(BasicBlock* block)
+    {
+        return m_startIndex[block];
+    }
+    
+    size_t indexOfTail(BasicBlock* block)
+    {
+        return indexOfHead(block) + block-&gt;size() * 2;
+    }
+    
+    Interval interval(size_t indexOfEarly, Arg::Timing timing)
+    {
+        switch (timing) {
+        case Arg::OnlyEarly:
+            return Interval(indexOfEarly);
+        case Arg::OnlyLate:
+            return Interval(indexOfEarly + 1);
+        case Arg::EarlyAndLate:
+            return Interval(indexOfEarly, indexOfEarly + 2);
+        }
+        ASSERT_NOT_REACHED();
+        return Interval();
+    }
+    
+    void buildIntervals()
+    {
+        TmpLiveness&lt;bank&gt; liveness(m_code);
+        
+        for (BasicBlock* block : m_code) {
+            size_t indexOfHead = this-&gt;indexOfHead(block);
+            size_t indexOfTail = this-&gt;indexOfTail(block);
+            if (verbose()) {
+                dataLog(&quot;At block &quot;, pointerDump(block), &quot;\n&quot;);
+                dataLog(&quot;  indexOfHead = &quot;, indexOfHead, &quot;\n&quot;);
+                dataLog(&quot;  idnexOfTail = &quot;, indexOfTail, &quot;\n&quot;);
+            }
+            for (Tmp tmp : liveness.liveAtHead(block)) {
+                if (!tmp.isReg())
+                    m_map[tmp].interval |= Interval(indexOfHead);
+            }
+            for (Tmp tmp : liveness.liveAtTail(block)) {
+                if (!tmp.isReg())
+                    m_map[tmp].interval |= Interval(indexOfTail);
+            }
+            
+            for (unsigned instIndex = 0; instIndex &lt; block-&gt;size(); ++instIndex) {
+                Inst&amp; inst = block-&gt;at(instIndex);
+                size_t indexOfEarly = indexOfHead + instIndex * 2;
+                inst.forEachTmp(
+                    [&amp;] (Tmp&amp; tmp, Arg::Role role, Bank tmpBank, Width) {
+                        if (tmp.isReg())
+                            return;
+                        if (tmpBank != bank)
+                            return;
+                        m_map[tmp].interval |= interval(indexOfEarly, Arg::timing(role));
+                    });
+            }
+
+            RegLiveness::LocalCalc localCalc(liveness, block);
+            
+            auto record = [&amp;] (unsigned instIndex) {
+                RegisterSet regs = localCalc.live();
+                if (Inst* prev = block-&gt;get(instIndex - 1)) {
+                    RegisterSet prevRegs = regs;
+                    prev-&gt;forEach&lt;Reg&gt;(
+                        [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                            if (Arg::isLateDef(role))
+                                prevRegs.add(reg);
+                        });
+                    if (prev-&gt;kind.opcode == Patch)
+                        prevRegs.merge(prev-&gt;extraClobberedRegs());
+                    prevRegs.filter(m_registerSet);
+                    if (!prevRegs.isEmpty())
+                        m_clobbers.append(Clobber(indexOfHead + instIndex * 2 - 1, prevRegs));
+                }
+                if (Inst* next = block-&gt;get(instIndex)) {
+                    RegisterSet nextRegs = regs;
+                    next-&gt;forEach&lt;Reg&gt;(
+                        [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                            if (Arg::isEarlyDef(role))
+                                nextRegs.add(reg);
+                        });
+                    if (next-&gt;kind.opcode == Patch)
+                        nextRegs.merge(next-&gt;extraEarlyClobberedRegs());
+                    if (!nextRegs.isEmpty())
+                        m_clobbers.append(Clobber(indexOfHead + instIndex * 2, nextRegs));
+                }
+            };
+            
+            record(block-&gt;size());
+            for (unsigned instIndex = block-&gt;size(); instIndex--;) {
+                localCalc.execute(instIndex);
+                record(instIndex);
+            }
+        }
+        
+        std::sort(
+            m_clobbers.begin(), m_clobbers.end(),
+            [] (Clobber&amp; a, Clobber&amp; b) -&gt; bool {
+                return a.index &lt; b.index;
+            });
+        
+        if (verbose()) {
+            dataLog(&quot;Intervals:\n&quot;);
+            for (unsigned tmpIndex = 0; tmpIndex &lt; m_code.numTmps(bank); ++tmpIndex) {
+                Tmp tmp = Tmp::tmpForIndex(bank, tmpIndex);
+                dataLog(&quot;    &quot;, tmp, &quot;: &quot;, m_map[tmp], &quot;\n&quot;);
+            }
+        }
+    }
+    
+    bool shouldSpillEverything()
+    {
+        if (!Options::airLinearScanSpillsEverything())
+            return false;
+        
+        // You're meant to hack this so that you selectively spill everything depending on reasons.
+        // That's super useful for debugging.
+
+        return true;
+    }
+    
+    void spillEverything()
+    {
+        for (unsigned tmpIndex = 0; tmpIndex &lt; m_code.numTmps(bank); ++tmpIndex)
+            spill(Tmp::tmpForIndex(bank, tmpIndex));
+    }
+    
+    void prepareIntervals()
+    {
+        m_tmps.resize(0);
+        
+        for (unsigned tmpIndex = 0; tmpIndex &lt; m_code.numTmps(bank); ++tmpIndex) {
+            Tmp tmp = Tmp::tmpForIndex(bank, tmpIndex);
+            TmpData&amp; data = m_map[tmp];
+            if (data.spilled)
+                continue;
+            
+            data.assigned = Reg();
+            m_tmps.append(tmp);
+        }
+        
+        std::sort(
+            m_tmps.begin(), m_tmps.end(),
+            [&amp;] (Tmp&amp; a, Tmp&amp; b) {
+                return m_map[a].interval.begin() &lt; m_map[b].interval.begin();
+            });
+        
+        if (verbose()) {
+            dataLog(&quot;Tmps: &quot;, listDump(m_tmps), &quot;\n&quot;);
+            dataLog(&quot;Clobbers: &quot;, listDump(m_clobbers), &quot;\n&quot;);
+        }
+    }
+    
+    Tmp addSpillTmpWithInterval(Interval interval)
+    {
+        TmpData data;
+        data.interval = interval;
+        data.isUnspillable = true;
+        
+        Tmp tmp = m_code.newTmp(bank);
+        m_map.append(tmp, data);
+        return tmp;
+    }
+    
+    void attemptScan()
+    {
+        // This is modeled after LinearScanRegisterAllocation in Fig. 1 in
+        // http://dl.acm.org/citation.cfm?id=330250.
+
+        m_didSpill = false;
+        m_active.clear();
+        m_activeRegs = RegisterSet();
+        
+        size_t clobberIndex = 0;
+        for (Tmp&amp; tmp : m_tmps) {
+            TmpData&amp; entry = m_map[tmp];
+            size_t index = entry.interval.begin();
+            
+            if (verbose()) {
+                dataLog(&quot;Index #&quot;, index, &quot;: &quot;, tmp, &quot;\n&quot;);
+                dataLog(&quot;  &quot;, tmp, &quot;: &quot;, entry, &quot;\n&quot;);
+                dataLog(&quot;  clobberIndex = &quot;, clobberIndex, &quot;\n&quot;);
+                // This could be so much faster.
+                BasicBlock* block = m_code[0];
+                for (BasicBlock* candidateBlock : m_code) {
+                    if (m_startIndex[candidateBlock] &gt; index)
+                        break;
+                    block = candidateBlock;
+                }
+                unsigned instIndex = (index - m_startIndex[block] + 1) / 2;
+                dataLog(&quot;  At: &quot;, pointerDump(block), &quot;, instIndex = &quot;, instIndex, &quot;\n&quot;);
+                dataLog(&quot;    Prev: &quot;, pointerDump(block-&gt;get(instIndex - 1)), &quot;\n&quot;);
+                dataLog(&quot;    Next: &quot;, pointerDump(block-&gt;get(instIndex)), &quot;\n&quot;);
+                dataLog(&quot;  Active:\n&quot;);
+                for (Tmp tmp : m_active)
+                    dataLog(&quot;    &quot;, tmp, &quot;: &quot;, m_map[tmp], &quot;\n&quot;);
+            }
+            
+            // This is ExpireOldIntervals in Fig. 1.
+            while (!m_active.isEmpty()) {
+                Tmp tmp = m_active.first();
+                TmpData&amp; entry = m_map[tmp];
+                
+                bool expired = entry.interval.end() &lt;= index;
+                
+                if (!expired)
+                    break;
+                
+                m_active.removeFirst();
+                m_activeRegs.remove(entry.assigned);
+            }
+
+            // If necessary, compute the set of registers that this tmp could even use. This is not
+            // part of Fig. 1, but it's a technique that the authors claim to have implemented in one of
+            // their two implementations. There may be other more efficient ways to do this, but this
+            // implementation gets some perf wins from piggy-backing this calculation in the scan.
+            //
+            // Note that the didBuild flag sticks through spilling. Spilling doesn't change the
+            // interference situation.
+            //
+            // Note that we could short-circuit this if we're dealing with a spillable tmp, there are no
+            // free registers, and this register's interval ends after the one on the top of the active
+            // stack.
+            if (!entry.didBuildPossibleRegs) {
+                // Advance the clobber index until it's at a clobber that is relevant to us.
+                while (clobberIndex &lt; m_clobbers.size() &amp;&amp; m_clobbers[clobberIndex].index &lt; index)
+                    clobberIndex++;
+                
+                RegisterSet possibleRegs = m_registerSet;
+                for (size_t i = clobberIndex; i &lt; m_clobbers.size() &amp;&amp; m_clobbers[i].index &lt; entry.interval.end(); ++i)
+                    possibleRegs.exclude(m_clobbers[i].regs);
+                
+                entry.possibleRegs = possibleRegs;
+                entry.didBuildPossibleRegs = true;
+            }
+            
+            if (verbose())
+                dataLog(&quot;  Possible regs: &quot;, entry.possibleRegs, &quot;\n&quot;);
+            
+            // Find a free register that we are allowed to use.
+            if (m_active.size() != m_registers.size()) {
+                bool didAssign = false;
+                for (Reg reg : m_registers) {
+                    // FIXME: Could do priority coloring here.
+                    // https://bugs.webkit.org/show_bug.cgi?id=170304
+                    if (!m_activeRegs.contains(reg) &amp;&amp; entry.possibleRegs.contains(reg)) {
+                        assign(tmp, reg);
+                        didAssign = true;
+                        break;
+                    }
+                }
+                if (didAssign)
+                    continue;
+            }
+            
+            // This is SpillAtInterval in Fig. 1, but modified to handle clobbers.
+            Tmp spillTmp = m_active.takeLast(
+                [&amp;] (Tmp spillCandidate) -&gt; bool {
+                    return entry.possibleRegs.contains(m_map[spillCandidate].assigned);
+                });
+            if (!spillTmp) {
+                spill(tmp);
+                continue;
+            }
+            TmpData&amp; spillEntry = m_map[spillTmp];
+            RELEASE_ASSERT(spillEntry.assigned);
+            if (spillEntry.isUnspillable ||
+                (!entry.isUnspillable &amp;&amp; spillEntry.interval.end() &lt;= entry.interval.end())) {
+                spill(tmp);
+                addToActive(spillTmp);
+                continue;
+            }
+            
+            assign(tmp, spillEntry.assigned);
+            spill(spillTmp);
+        }
+    }
+    
+    void addToActive(Tmp tmp)
+    {
+        if (m_map[tmp].isUnspillable) {
+            m_active.prepend(tmp);
+            return;
+        }
+        
+        m_active.appendAndBubble(
+            tmp,
+            [&amp;] (Tmp otherTmp) -&gt; bool {
+                TmpData&amp; otherEntry = m_map[otherTmp];
+                if (otherEntry.isUnspillable)
+                    return false;
+                return m_map[otherTmp].interval.end() &gt; m_map[tmp].interval.end();
+            });
+    }
+    
+    void assign(Tmp tmp, Reg reg)
+    {
+        TmpData&amp; entry = m_map[tmp];
+        RELEASE_ASSERT(!entry.spilled);
+        entry.assigned = reg;
+        m_activeRegs.add(reg);
+        addToActive(tmp);
+    }
+    
+    void spill(Tmp tmp)
+    {
+        TmpData&amp; entry = m_map[tmp];
+        RELEASE_ASSERT(!entry.isUnspillable);
+        entry.spilled = m_code.addStackSlot(8, StackSlotKind::Spill);
+        entry.assigned = Reg();
+        m_didSpill = true;
+    }
+    
+    void emitSpillCode()
+    {
+        for (BasicBlock* block : m_code) {
+            size_t indexOfHead = this-&gt;indexOfHead(block);
+            for (unsigned instIndex = 0; instIndex &lt; block-&gt;size(); ++instIndex) {
+                Inst&amp; inst = block-&gt;at(instIndex);
+                unsigned indexOfEarly = indexOfHead + instIndex * 2;
+                
+                // First try to spill directly.
+                for (unsigned i = 0; i &lt; inst.args.size(); ++i) {
+                    Arg&amp; arg = inst.args[i];
+                    if (!arg.isTmp())
+                        continue;
+                    if (arg.isReg())
+                        continue;
+                    if (arg.bank() != bank)
+                        continue;
+                    StackSlot* spilled = m_map[arg.tmp()].spilled;
+                    if (!spilled)
+                        continue;
+                    if (!inst.admitsStack(i))
+                        continue;
+                    arg = Arg::stack(spilled);
+                }
+                
+                // Fall back on the hard way.
+                inst.forEachTmp(
+                    [&amp;] (Tmp&amp; tmp, Arg::Role role, Bank tmpBank, Width) {
+                        if (tmp.isReg())
+                            return;
+                        if (tmpBank != bank)
+                            return;
+                        StackSlot* spilled = m_map[tmp].spilled;
+                        if (!spilled)
+                            return;
+                        Opcode move = bank == GP ? Move : MoveDouble;
+                        tmp = addSpillTmpWithInterval(interval(indexOfEarly, Arg::timing(role)));
+                        if (role == Arg::Scratch)
+                            return;
+                        if (Arg::isAnyUse(role))
+                            m_insertionSets[block].insert(instIndex, secondPhase, move, inst.origin, Arg::stack(spilled), tmp);
+                        if (Arg::isAnyDef(role))
+                            m_insertionSets[block].insert(instIndex + 1, firstPhase, move, inst.origin, tmp, Arg::stack(spilled));
+                    });
+            }
+        }
+    }
+    
+    void insertSpillCode()
+    {
+        for (BasicBlock* block : m_code)
+            m_insertionSets[block].execute(block);
+    }
+    
+    void assignRegisters()
+    {
+        if (verbose()) {
+            dataLog(&quot;About to allocate registers. State of all tmps:\n&quot;);
+            for (unsigned tmpIndex = 0; tmpIndex &lt; m_code.numTmps(bank); ++tmpIndex) {
+                Tmp tmp = Tmp::tmpForIndex(bank, tmpIndex);
+                dataLog(&quot;    &quot;, tmp, &quot;: &quot;, m_map[tmp], &quot;\n&quot;);
+            }
+            dataLog(&quot;IR:\n&quot;);
+            dataLog(m_code);
+        }
+        
+        for (BasicBlock* block : m_code) {
+            for (Inst&amp; inst : *block) {
+                if (verbose())
+                    dataLog(&quot;At: &quot;, inst, &quot;\n&quot;);
+                inst.forEachTmpFast(
+                    [&amp;] (Tmp&amp; tmp) {
+                        if (tmp.isReg())
+                            return;
+                        if (tmp.bank() != bank)
+                            return;
+                        
+                        Reg reg = m_map[tmp].assigned;
+                        if (!reg) {
+                            dataLog(&quot;Failed to allocate reg for: &quot;, tmp, &quot;\n&quot;);
+                            RELEASE_ASSERT_NOT_REACHED();
+                        }
+                        tmp = Tmp(reg);
+                    });
+            }
+        }
+    }
+    
+    Code&amp; m_code;
+    Vector&lt;Reg&gt; m_registers;
+    RegisterSet m_registerSet;
+    IndexMap&lt;BasicBlock*, size_t&gt; m_startIndex;
+    IndexMap&lt;Tmp::Indexed&lt;bank&gt;, TmpData&gt; m_map;
+    IndexMap&lt;BasicBlock*, PhaseInsertionSet&gt; m_insertionSets;
+    Vector&lt;Clobber&gt; m_clobbers; // After we allocate this, we happily point pointers into it.
+    Vector&lt;Tmp&gt; m_tmps;
+    Deque&lt;Tmp&gt; m_active;
+    RegisterSet m_activeRegs;
+    bool m_didSpill { false };
+};
+
+template&lt;Bank bank&gt;
+void runLinearScan(Code&amp; code)
+{
+    if (verbose())
+        dataLog(&quot;Air before linear scan for &quot;, bank, &quot;:\n&quot;, code);
+    LinearScan&lt;bank&gt; linearScan(code);
+    linearScan.run();
+    if (verbose())
+        dataLog(&quot;Air after linear scan for &quot;, bank, &quot;:\n&quot;, code);
+}
+
+} // anonymous namespace
+
+void allocateRegistersByLinearScan(Code&amp; code)
+{
+    PhaseScope phaseScope(code, &quot;allocateRegistersByLinearScan&quot;);
+    padInterference(code);
+    runLinearScan&lt;FP&gt;(code);
+    runLinearScan&lt;GP&gt;(code);
+    fixSpillsAfterTerminals(code);
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateRegistersByLinearScanh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.h (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByLinearScan.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+#include &quot;CPU.h&quot;
+#include &quot;Options.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// This implements the Poletto and Sarkar register allocator called &quot;linear scan&quot;:
+// http://dl.acm.org/citation.cfm?id=330250
+//
+// This is not Air's primary register allocator. We use it only when running at optLevel&lt;2. That's not
+// the default level. This register allocator is optimized primarily for running quickly. It's expected
+// that improvements to this register allocator should focus on improving its execution time without much
+// regard for the quality of generated code. If you want good code, use graph coloring.
+//
+// For Air's primary register allocator, see AirAllocateRegistersByGraphColoring.h|cpp.
+void allocateRegistersByLinearScan(Code&amp;);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Now we handle the spill slots.
</span><span class="cx">     StackSlotLiveness liveness(code);
</span><del>-    IndexMap&lt;StackSlot, HashSet&lt;StackSlot*&gt;&gt; interference(code.stackSlots().size());
</del><ins>+    IndexMap&lt;StackSlot*, HashSet&lt;StackSlot*&gt;&gt; interference(code.stackSlots().size());
</ins><span class="cx">     Vector&lt;StackSlot*&gt; slots;
</span><span class="cx"> 
</span><span class="cx">     // We will perform some spill coalescing. To make that effective, we need to be able to identify
</span><span class="lines">@@ -309,7 +309,7 @@
</span><span class="cx">             return a.frequency &gt; b.frequency;
</span><span class="cx">         });
</span><span class="cx">     
</span><del>-    IndexMap&lt;StackSlot, StackSlot*&gt; remappedStackSlots(code.stackSlots().size());
</del><ins>+    IndexMap&lt;StackSlot*, StackSlot*&gt; remappedStackSlots(code.stackSlots().size());
</ins><span class="cx">     auto remap = [&amp;] (StackSlot* slot) -&gt; StackSlot* {
</span><span class="cx">         if (!slot)
</span><span class="cx">             return nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirArgcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirArg.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirArg.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirArg.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -282,6 +282,37 @@
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void printInternal(PrintStream&amp; out, Arg::Phase phase)
+{
+    switch (phase) {
+    case Arg::Early:
+        out.print(&quot;Early&quot;);
+        return;
+    case Arg::Late:
+        out.print(&quot;Late&quot;);
+        return;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void printInternal(PrintStream&amp; out, Arg::Timing timing)
+{
+    switch (timing) {
+    case Arg::OnlyEarly:
+        out.print(&quot;OnlyEarly&quot;);
+        return;
+    case Arg::OnlyLate:
+        out.print(&quot;OnlyLate&quot;);
+        return;
+    case Arg::EarlyAndLate:
+        out.print(&quot;EarlyAndLate&quot;);
+        return;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
</ins><span class="cx"> void printInternal(PrintStream&amp; out, Arg::Role role)
</span><span class="cx"> {
</span><span class="cx">     switch (role) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirArgh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirArg.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirArg.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirArg.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -92,6 +92,17 @@
</span><span class="cx">         Cold,
</span><span class="cx">         Warm
</span><span class="cx">     };
</span><ins>+    
+    enum Phase : int8_t {
+        Early,
+        Late
+    };
+    
+    enum Timing : int8_t {
+        OnlyEarly,
+        OnlyLate,
+        EarlyAndLate
+    };
</ins><span class="cx"> 
</span><span class="cx">     enum Role : int8_t {
</span><span class="cx">         // Use means that the Inst will read from this value before doing anything else.
</span><span class="lines">@@ -253,7 +264,82 @@
</span><span class="cx">     {
</span><span class="cx">         return isColdUse(role) ? Cold : Warm;
</span><span class="cx">     }
</span><del>-
</del><ins>+    
+    static bool activeAt(Role role, Phase phase)
+    {
+        switch (role) {
+        case Use:
+        case ColdUse:
+        case EarlyDef:
+        case EarlyZDef:
+        case UseAddr:
+            return phase == Early;
+        case LateUse:
+        case LateColdUse:
+        case Def:
+        case ZDef:
+            return phase == Late;
+        case UseDef:
+        case UseZDef:
+        case Scratch:
+            return true;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    
+    static bool activeAt(Timing timing, Phase phase)
+    {
+        switch (timing) {
+        case OnlyEarly:
+            return phase == Early;
+        case OnlyLate:
+            return phase == Late;
+        case EarlyAndLate:
+            return true;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    
+    static Timing timing(Role role)
+    {
+        switch (role) {
+        case Use:
+        case ColdUse:
+        case EarlyDef:
+        case EarlyZDef:
+        case UseAddr:
+            return OnlyEarly;
+        case LateUse:
+        case LateColdUse:
+        case Def:
+        case ZDef:
+            return OnlyLate;
+        case UseDef:
+        case UseZDef:
+        case Scratch:
+            return EarlyAndLate;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    
+    template&lt;typename Func&gt;
+    static void forEachPhase(Timing timing, const Func&amp; func)
+    {
+        if (activeAt(timing, Early))
+            func(Early);
+        if (activeAt(timing, Late))
+            func(Late);
+    }
+    
+    template&lt;typename Func&gt;
+    static void forEachPhase(Role role, const Func&amp; func)
+    {
+        if (activeAt(role, Early))
+            func(Early);
+        if (activeAt(role, Late))
+            func(Late);
+    }
+    
</ins><span class="cx">     // Returns true if the Role implies that the Inst will Use the Arg before doing anything else.
</span><span class="cx">     static bool isEarlyUse(Role role)
</span><span class="cx">     {
</span><span class="lines">@@ -1354,6 +1440,8 @@
</span><span class="cx"> 
</span><span class="cx"> JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Kind);
</span><span class="cx"> JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Temperature);
</span><ins>+JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Phase);
+JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Timing);
</ins><span class="cx"> JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Role);
</span><span class="cx"> JS_EXPORT_PRIVATE void printInternal(PrintStream&amp;, JSC::B3::Air::Arg::Signedness);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> class BlockInsertionSet;
</span><span class="cx"> class Code;
</span><span class="cx"> class InsertionSet;
</span><ins>+class PhaseInsertionSet;
</ins><span class="cx"> 
</span><span class="cx"> class BasicBlock {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(BasicBlock);
</span><span class="lines">@@ -140,6 +141,7 @@
</span><span class="cx">     friend class BlockInsertionSet;
</span><span class="cx">     friend class Code;
</span><span class="cx">     friend class InsertionSet;
</span><ins>+    friend class PhaseInsertionSet;
</ins><span class="cx">     template&lt;typename&gt; friend class B3::GenericBlockInsertionSet;
</span><span class="cx">     
</span><span class="cx">     BasicBlock(unsigned index, double frequency);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirBlockWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirBlockWorklist.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirBlockWorklist.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirBlockWorklist.h        2017-03-30 22:55:44 UTC (rev 214636)
</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-2017 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,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><del>-typedef GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; BlockWorklist;
</del><ins>+typedef GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; BlockWorklist;
</ins><span class="cx"> 
</span><span class="cx"> // When you say BlockWith&lt;int&gt; you should read it as &quot;block with an int&quot;.
</span><span class="cx"> template&lt;typename T&gt; using BlockWith = GraphNodeWith&lt;BasicBlock*, T&gt;;
</span><span class="lines">@@ -41,11 +41,11 @@
</span><span class="cx"> // permits forcibly enqueueing things even if the block has already been seen. It's useful for
</span><span class="cx"> // things like building a spanning tree, in which case T (the auxiliary payload) would be the
</span><span class="cx"> // successor index.
</span><del>-template&lt;typename T&gt; using ExtendedBlockWorklist = ExtendedGraphNodeWorklist&lt;BasicBlock*, T, IndexSet&lt;BasicBlock&gt;&gt;;
</del><ins>+template&lt;typename T&gt; using ExtendedBlockWorklist = ExtendedGraphNodeWorklist&lt;BasicBlock*, T, IndexSet&lt;BasicBlock*&gt;&gt;;
</ins><span class="cx"> 
</span><span class="cx"> typedef GraphNodeWithOrder&lt;BasicBlock*&gt; BlockWithOrder;
</span><span class="cx"> 
</span><del>-typedef PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; PostOrderBlockWorklist;
</del><ins>+typedef PostOrderGraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock*&gt;&gt; PostOrderBlockWorklist;
</ins><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCFGh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCFG.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCFG.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirCFG.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -39,8 +39,8 @@
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     typedef BasicBlock* Node;
</span><del>-    typedef IndexSet&lt;BasicBlock&gt; Set;
-    template&lt;typename T&gt; using Map = IndexMap&lt;BasicBlock, T&gt;;
</del><ins>+    typedef IndexSet&lt;BasicBlock*&gt; Set;
+    template&lt;typename T&gt; using Map = IndexMap&lt;BasicBlock*, T&gt;;
</ins><span class="cx">     typedef Vector&lt;BasicBlock*, 4&gt; List;
</span><span class="cx"> 
</span><span class="cx">     CFG(Code&amp; code)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">     Node root() { return m_code[0]; }
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename T&gt;
</span><del>-    Map&lt;T&gt; newMap() { return IndexMap&lt;JSC::B3::Air::BasicBlock, T&gt;(m_code.size()); }
</del><ins>+    Map&lt;T&gt; newMap() { return IndexMap&lt;JSC::B3::Air::BasicBlock*, T&gt;(m_code.size()); }
</ins><span class="cx"> 
</span><span class="cx">     SuccessorCollection&lt;BasicBlock, BasicBlock::SuccessorList&gt; successors(Node node) { return node-&gt;successorBlocks(); }
</span><span class="cx">     BasicBlock::PredecessorList&amp; predecessors(Node node) { return node-&gt;predecessors(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirEliminateDeadCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx">     PhaseScope phaseScope(code, &quot;eliminateDeadCode&quot;);
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;Tmp&gt; liveTmps;
</span><del>-    IndexSet&lt;StackSlot&gt; liveStackSlots;
</del><ins>+    IndexSet&lt;StackSlot*&gt; liveStackSlots;
</ins><span class="cx">     bool changed;
</span><span class="cx"> 
</span><span class="cx">     auto isArgLive = [&amp;] (const Arg&amp; arg) -&gt; bool {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -547,7 +547,7 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     Code&amp; m_code;
</span><del>-    IndexMap&lt;BasicBlock, State&gt; m_atHead;
</del><ins>+    IndexMap&lt;BasicBlock*, State&gt; m_atHead;
</ins><span class="cx">     State m_state;
</span><span class="cx">     BasicBlock* m_block { nullptr };
</span><span class="cx">     unsigned m_instIndex { 0 };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixPartialRegisterStallscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -155,10 +155,10 @@
</span><span class="cx"> 
</span><span class="cx">     // For each block, this provides the distance to the last instruction setting each register
</span><span class="cx">     // on block *entry*.
</span><del>-    IndexMap&lt;BasicBlock, FPDefDistance&gt; lastDefDistance(code.size());
</del><ins>+    IndexMap&lt;BasicBlock*, FPDefDistance&gt; lastDefDistance(code.size());
</ins><span class="cx"> 
</span><span class="cx">     // Blocks with dirty distance at head.
</span><del>-    IndexSet&lt;BasicBlock&gt; dirty;
</del><ins>+    IndexSet&lt;BasicBlock*&gt; dirty;
</ins><span class="cx"> 
</span><span class="cx">     // First, we compute the local distance for each block and push it to the successors.
</span><span class="cx">     for (BasicBlock* block : code) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixSpillsAfterTerminalscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.cpp (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,99 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;AirFixSpillsAfterTerminals.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirBlockInsertionSet.h&quot;
+#include &quot;AirCode.h&quot;
+#include &quot;AirInsertionSet.h&quot;
+#include &quot;AirInstInlines.h&quot;
+#include &quot;AirTmpInlines.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+void fixSpillsAfterTerminals(Code&amp; code)
+{
+    // Because there may be terminals that produce values, IRC may
+    // want to spill those terminals. It'll happen to spill it after
+    // the terminal. If we left the graph in this state, it'd be invalid
+    // because a terminal must be the last instruction in a block.
+    // We fix that here.
+
+    BlockInsertionSet blockInsertionSet(code);
+    InsertionSet insertionSet(code);
+
+    for (BasicBlock* block : code) {
+        unsigned terminalIndex = block-&gt;size();
+        bool foundTerminal = false;
+        while (terminalIndex--) {
+            if (block-&gt;at(terminalIndex).isTerminal()) {
+                foundTerminal = true;
+                break;
+            }
+        }
+        ASSERT_UNUSED(foundTerminal, foundTerminal);
+
+        if (terminalIndex == block-&gt;size() - 1)
+            continue;
+
+        // There must be instructions after the terminal because it's not the last instruction.
+        ASSERT(terminalIndex &lt; block-&gt;size() - 1);
+        Vector&lt;Inst, 1&gt; instsToMove;
+        for (unsigned i = terminalIndex + 1; i &lt; block-&gt;size(); i++)
+            instsToMove.append(block-&gt;at(i));
+        RELEASE_ASSERT(instsToMove.size());
+
+        for (FrequentedBlock&amp; frequentedSuccessor : block-&gt;successors()) {
+            BasicBlock* successor = frequentedSuccessor.block();
+            // If successor's only predecessor is block, we can plant the spill inside
+            // the successor. Otherwise, we must split the critical edge and create
+            // a new block for the spill.
+            if (successor-&gt;numPredecessors() == 1) {
+                insertionSet.insertInsts(0, instsToMove);
+                insertionSet.execute(successor);
+            } else {
+                BasicBlock* newBlock = blockInsertionSet.insertBefore(successor, successor-&gt;frequency());
+                for (const Inst&amp; inst : instsToMove)
+                    newBlock-&gt;appendInst(inst);
+                newBlock-&gt;appendInst(Inst(Jump, instsToMove.last().origin));
+                newBlock-&gt;successors().append(successor);
+                frequentedSuccessor.block() = newBlock;
+            }
+        }
+
+        block-&gt;resize(terminalIndex + 1);
+    }
+
+    if (blockInsertionSet.execute())
+        code.resetReachability();
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixSpillsAfterTerminalsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.h (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixSpillsAfterTerminals.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// Because there may be terminals that produce values, the register allocator may
+// want to spill those terminals. It'll happen to spill it after
+// the terminal. If we left the graph in this state, it'd be invalid
+// because a terminal must be the last instruction in a block.
+// We fix that here.
+void fixSpillsAfterTerminals(Code&amp;);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</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;AirAllocateRegistersByGraphColoring.h&quot;
</span><ins>+#include &quot;AirAllocateRegistersByLinearScan.h&quot;
</ins><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><span class="lines">@@ -57,7 +58,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><del>-void prepareForGeneration(Code&amp; code)
</del><ins>+void prepareForGeneration(Code&amp; code, unsigned optLevel)
</ins><span class="cx"> {
</span><span class="cx">     TimingScope timingScope(&quot;Air::prepareForGeneration&quot;);
</span><span class="cx">     
</span><span class="lines">@@ -89,19 +90,23 @@
</span><span class="cx">     // For debugging, you can use spillEverything() to put everything to the stack between each Inst.
</span><span class="cx">     if (Options::airSpillsEverything())
</span><span class="cx">         spillEverything(code);
</span><ins>+    else if (optLevel &gt;= 2)
+        allocateRegistersByGraphColoring(code);
</ins><span class="cx">     else
</span><del>-        allocateRegistersByGraphColoring(code);
</del><ins>+        allocateRegistersByLinearScan(code);
</ins><span class="cx"> 
</span><span class="cx">     if (Options::logAirRegisterPressure()) {
</span><span class="cx">         dataLog(&quot;Register pressure after register allocation:\n&quot;);
</span><span class="cx">         logRegisterPressure(code);
</span><span class="cx">     }
</span><ins>+    
+    if (optLevel &gt;= 2) {
+        // 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"> 
</span><del>-    // 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);
-
</del><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">@@ -165,7 +170,7 @@
</span><span class="cx">         if (block)
</span><span class="cx">             context.blockLabels[block] = Box&lt;CCallHelpers::Label&gt;::create();
</span><span class="cx">     }
</span><del>-    IndexMap&lt;BasicBlock, CCallHelpers::JumpList&gt; blockJumps(code.size());
</del><ins>+    IndexMap&lt;BasicBlock*, CCallHelpers::JumpList&gt; blockJumps(code.size());
</ins><span class="cx"> 
</span><span class="cx">     auto link = [&amp;] (CCallHelpers::Jump jump, BasicBlock* target) {
</span><span class="cx">         if (context.blockLabels[target]-&gt;isSet()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGenerateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 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">@@ -27,6 +27,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3Common.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CCallHelpers;
</span><span class="lines">@@ -37,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> // This takes an Air::Code that hasn't had any stack allocation and optionally hasn't had any
</span><span class="cx"> // register allocation and does both of those things.
</span><del>-JS_EXPORT_PRIVATE void prepareForGeneration(Code&amp;);
</del><ins>+JS_EXPORT_PRIVATE void prepareForGeneration(Code&amp;, unsigned optLevel = defaultOptLevel());
</ins><span class="cx"> 
</span><span class="cx"> // This generates the code using the given CCallHelpers instance. Note that this may call callbacks
</span><span class="cx"> // in the supplied code as it is generating.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGenerationContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">     typedef SharedTask&lt;LatePathFunction&gt; LatePath;
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;RefPtr&lt;LatePath&gt;&gt; latePaths;
</span><del>-    IndexMap&lt;BasicBlock, Box&lt;CCallHelpers::Label&gt;&gt; blockLabels;
</del><ins>+    IndexMap&lt;BasicBlock*, Box&lt;CCallHelpers::Label&gt;&gt; blockLabels;
</ins><span class="cx">     BasicBlock* currentBlock { nullptr };
</span><span class="cx">     unsigned indexInBlock { UINT_MAX };
</span><span class="cx">     Code* code { nullptr };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInsertionSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInsertionSet.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInsertionSet.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirInsertionSet.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx">         appendInsertion(Insertion(index, std::forward&lt;Inst&gt;(inst)));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    template &lt;typename InstVector&gt;
</del><ins>+    template&lt;typename InstVector&gt;
</ins><span class="cx">     void insertInsts(size_t index, const InstVector&amp; insts)
</span><span class="cx">     {
</span><span class="cx">         for (const Inst&amp; inst : insts)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInstcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInst.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInst.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirInst.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -60,7 +60,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool Inst::needsPadding(Inst* prevInst, Inst* nextInst)
</span><span class="cx"> {
</span><del>-    return prevInst &amp;&amp; nextInst &amp;&amp; prevInst-&gt;hasLateUseOrDef() &amp;&amp; nextInst-&gt;hasEarlyDef();
</del><ins>+    bool result = prevInst &amp;&amp; nextInst &amp;&amp; prevInst-&gt;hasLateUseOrDef() &amp;&amp; nextInst-&gt;hasEarlyDef();
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Inst::hasArgEffects()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -55,6 +55,14 @@
</span><span class="cx"> 
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Code before lowerAfterRegAlloc:\n&quot;, code);
</span><ins>+    
+    // FIXME:
+    // 1) This should bail early if there are no Shuffles or ColdCCalls.
+    //    https://bugs.webkit.org/show_bug.cgi?id=170305
+    // 2) We should not introduce Shuffles for normal calls.
+    //    https://bugs.webkit.org/show_bug.cgi?id=170306
+    // 3) We should emit ColdCCall only at optLevel==1.
+    //    https://bugs.webkit.org/show_bug.cgi?id=170307
</ins><span class="cx"> 
</span><span class="cx">     HashMap&lt;Inst*, RegisterSet&gt; usedRegisters;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLowerEntrySwitchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">     // Now duplicate them.
</span><span class="cx">     Vector&lt;FrequentedBlock&gt; entrypoints;
</span><span class="cx">     entrypoints.append(FrequentedBlock(code[0], entrypointFrequencies[0]));
</span><del>-    IndexMap&lt;BasicBlock, BasicBlock*&gt; map(code.size());
</del><ins>+    IndexMap&lt;BasicBlock*, BasicBlock*&gt; map(code.size());
</ins><span class="cx">     for (unsigned entrypointIndex = 1; entrypointIndex &lt; code.proc().numEntrypoints(); ++entrypointIndex) {
</span><span class="cx">         map.clear();
</span><span class="cx">         for (BasicBlock* block : worklist.seen().values(code))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -649,7 +649,7 @@
</span><span class="cx"> Move32 U:G:32, ZD:G:32, S:G:32
</span><span class="cx">     Addr, Addr, Tmp
</span><span class="cx"> 
</span><del>-StoreZero32 U:G:32
</del><ins>+StoreZero32 D:G:32
</ins><span class="cx">     Addr
</span><span class="cx">     Index
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirPhaseInsertionSetcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.cpp (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;AirPhaseInsertionSet.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirBasicBlock.h&quot;
+#include &lt;wtf/BubbleSort.h&gt;
+
+namespace JSC { namespace B3 { namespace Air {
+
+void PhaseInsertionSet::execute(BasicBlock* block)
+{
+    bubbleSort(m_insertions.begin(), m_insertions.end());
+    executeInsertions(block-&gt;m_insts, m_insertions);
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirPhaseInsertionSeth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.h (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirPhaseInsertionSet.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+/*
+ * Copyright (C) 2017 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. 
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirInsertionSet.h&quot;
+#include &lt;wtf/Insertion.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC { namespace B3 { namespace Air {
+
+class BasicBlock;
+class Code;
+
+// Phased insertions allow you to ascribe phases to the things inserted at an instruction boundary.
+class PhaseInsertion : public Insertion {
+public:
+    PhaseInsertion() { }
+    
+    template&lt;typename T&gt;
+    PhaseInsertion(size_t index, unsigned phase, T&amp;&amp; element)
+        : Insertion(index, std::forward&lt;T&gt;(element))
+        , m_phase(phase)
+    {
+    }
+    
+    unsigned phase() const { return m_phase; }
+    
+    bool operator&lt;(const PhaseInsertion&amp; other) const
+    {
+        if (index() != other.index())
+            return index() &lt; other.index();
+        return m_phase &lt; other.m_phase;
+    }
+
+private:
+    unsigned m_phase { 0 };
+};
+
+class PhaseInsertionSet {
+public:
+    PhaseInsertionSet()
+    {
+    }
+    
+    template&lt;typename T&gt;
+    void appendInsertion(T&amp;&amp; insertion)
+    {
+        m_insertions.append(std::forward&lt;T&gt;(insertion));
+    }
+    
+    template&lt;typename Inst&gt;
+    void insertInst(size_t index, unsigned phase, Inst&amp;&amp; inst)
+    {
+        appendInsertion(PhaseInsertion(index, phase, std::forward&lt;Inst&gt;(inst)));
+    }
+    
+    template&lt;typename... Arguments&gt;
+    void insert(size_t index, unsigned phase, Arguments&amp;&amp;... arguments)
+    {
+        insertInst(index, phase, Inst(std::forward&lt;Arguments&gt;(arguments)...));
+    }
+    
+    void execute(BasicBlock*);
+
+private:
+    Vector&lt;PhaseInsertion, 8&gt; m_insertions;
+};
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirRegLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;AirBasicBlock.h&quot;
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirInst.h&quot;
</span><ins>+#include &quot;AirLiveness.h&quot;
</ins><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="lines">@@ -54,6 +55,19 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        // If you computed Tmp liveness for some bank, you can use reg liveness to fill in the blanks.
+        // Note that what happens to the registers not belonging to the bank is arbitrary - they may get
+        // set or not.
+        template&lt;Bank bank&gt;
+        LocalCalc(TmpLiveness&lt;bank&gt;&amp; liveness, BasicBlock* block)
+            : m_block(block)
+        {
+            for (Tmp tmp : liveness.liveAtTail(block)) {
+                if (tmp.isReg())
+                    m_workset.set(tmp.reg());
+            }
+        }
+        
</ins><span class="cx">         const RegisterSet&amp; live() const
</span><span class="cx">         {
</span><span class="cx">             return m_workset;
</span><span class="lines">@@ -84,8 +98,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    IndexMap&lt;BasicBlock, RegisterSet&gt; m_liveAtHead;
-    IndexMap&lt;BasicBlock, RegisterSet&gt; m_liveAtTail;
</del><ins>+    IndexMap&lt;BasicBlock*, RegisterSet&gt; m_liveAtHead;
+    IndexMap&lt;BasicBlock*, RegisterSet&gt; m_liveAtTail;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AirArgInlines.h&quot;
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><ins>+#include &quot;AirFixSpillsAfterTerminals.h&quot;
</ins><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">@@ -46,7 +47,7 @@
</span><span class="cx">     padInterference(code);
</span><span class="cx"> 
</span><span class="cx">     // We want to know the set of registers used at every point in every basic block.
</span><del>-    IndexMap&lt;BasicBlock, Vector&lt;RegisterSet&gt;&gt; usedRegisters(code.size());
</del><ins>+    IndexMap&lt;BasicBlock*, Vector&lt;RegisterSet&gt;&gt; usedRegisters(code.size());
</ins><span class="cx">     GPLiveness gpLiveness(code);
</span><span class="cx">     FPLiveness fpLiveness(code);
</span><span class="cx">     for (BasicBlock* block : code) {
</span><span class="lines">@@ -173,10 +174,13 @@
</span><span class="cx">                     RELEASE_ASSERT(chosenReg);
</span><span class="cx"> 
</span><span class="cx">                     tmp = Tmp(chosenReg);
</span><ins>+                    
+                    if (role == Arg::Scratch)
+                        return;
</ins><span class="cx"> 
</span><span class="cx">                     Opcode move = bank == GP ? Move : MoveDouble;
</span><span class="cx"> 
</span><del>-                    if (Arg::isAnyUse(role) &amp;&amp; role != Arg::Scratch)
</del><ins>+                    if (Arg::isAnyUse(role))
</ins><span class="cx">                         insertionSet.insert(instIndex, move, inst.origin, arg, tmp);
</span><span class="cx">                     if (Arg::isAnyDef(role))
</span><span class="cx">                         insertionSet.insert(instIndex + 1, move, inst.origin, tmp, arg);
</span><span class="lines">@@ -184,6 +188,8 @@
</span><span class="cx">         }
</span><span class="cx">         insertionSet.execute(block);
</span><span class="cx">     }
</span><ins>+    
+    fixSpillsAfterTerminals(code);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirTmpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirTmp.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirTmp.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirTmp.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</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-2017 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,8 +28,15 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirTmpInlines.h&quot;
+
</ins><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+template&lt;&gt; const char* const Tmp::Indexed&lt;GP&gt;::dumpPrefix = &quot;%tmp&quot;;
+template&lt;&gt; const char* const Tmp::Indexed&lt;FP&gt;::dumpPrefix = &quot;%ftmp&quot;;
+template&lt;&gt; const char* const Tmp::AbsolutelyIndexed&lt;GP&gt;::dumpPrefix = &quot;%abs&quot;;
+template&lt;&gt; const char* const Tmp::AbsolutelyIndexed&lt;FP&gt;::dumpPrefix = &quot;%fabs&quot;;
+
</ins><span class="cx"> void Tmp::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     if (!*this) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirTmph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirTmp.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirTmp.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirTmp.h        2017-03-30 22:55:44 UTC (rev 214636)
</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-2017 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">@@ -74,6 +74,14 @@
</span><span class="cx">         result.m_value = encodeFPTmp(index);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+    
+    static Tmp tmpForIndex(Bank bank, unsigned index)
+    {
+        if (bank == GP)
+            return gpTmpForIndex(index);
+        ASSERT(bank == FP);
+        return fpTmpForIndex(index);
+    }
</ins><span class="cx"> 
</span><span class="cx">     explicit operator bool() const { return !!m_value; }
</span><span class="cx">     
</span><span class="lines">@@ -154,7 +162,16 @@
</span><span class="cx">             return gpTmpIndex();
</span><span class="cx">         return fpTmpIndex();
</span><span class="cx">     }
</span><del>-
</del><ins>+    
+    template&lt;Bank bank&gt; class Indexed;
+    template&lt;Bank bank&gt; class AbsolutelyIndexed;
+    
+    template&lt;Bank bank&gt;
+    Indexed&lt;bank&gt; indexed() const;
+    
+    template&lt;Bank bank&gt;
+    AbsolutelyIndexed&lt;bank&gt; absolutelyIndexed() const;
+    
</ins><span class="cx">     bool isAlive() const
</span><span class="cx">     {
</span><span class="cx">         return !!*this;
</span><span class="lines">@@ -195,6 +212,8 @@
</span><span class="cx">         result.m_value = static_cast&lt;int&gt;(index);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+    
+    static Tmp tmpForAbsoluteIndex(Bank, unsigned);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static int encodeGP(unsigned index)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirTmpInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirTmpInlines.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirTmpInlines.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/air/AirTmpInlines.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -92,6 +92,58 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+template&lt;Bank theBank&gt;
+class Tmp::Indexed : public Tmp {
+public:
+    static const char* const dumpPrefix;
+    
+    Indexed(Tmp tmp)
+        : Tmp(tmp)
+    {
+    }
+    
+    unsigned index() const
+    {
+        return tmpIndex(theBank);
+    }
+};
+
+template&lt;Bank theBank&gt;
+class Tmp::AbsolutelyIndexed : public Tmp {
+public:
+    static const char* const dumpPrefix;
+
+    AbsolutelyIndexed(Tmp tmp)
+        : Tmp(tmp)
+    {
+    }
+    
+    unsigned index() const
+    {
+        return AbsoluteTmpMapper&lt;theBank&gt;::absoluteIndex(*this);
+    }
+};
+
+template&lt;Bank theBank&gt;
+inline Tmp::Indexed&lt;theBank&gt; Tmp::indexed() const
+{
+    return Indexed&lt;theBank&gt;(*this);
+}
+
+template&lt;Bank theBank&gt;
+inline Tmp::AbsolutelyIndexed&lt;theBank&gt; Tmp::absolutelyIndexed() const
+{
+    return AbsolutelyIndexed&lt;theBank&gt;(*this);
+}
+
+inline Tmp Tmp::tmpForAbsoluteIndex(Bank bank, unsigned index)
+{
+    if (bank == GP)
+        return AbsoluteTmpMapper&lt;GP&gt;::tmpFromAbsoluteIndex(index);
+    ASSERT(bank == FP);
+    return AbsoluteTmpMapper&lt;FP&gt;::tmpFromAbsoluteIndex(index);
+}
+
</ins><span class="cx"> } } } // namespace JSC::B3::Air
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx">         CRASH(); \
</span><span class="cx">     } while (false)
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;Compilation&gt; compileProc(Procedure&amp; procedure, unsigned optLevel = 1)
</del><ins>+std::unique_ptr&lt;Compilation&gt; compileProc(Procedure&amp; procedure, unsigned optLevel = defaultOptLevel())
</ins><span class="cx"> {
</span><span class="cx">     return std::make_unique&lt;Compilation&gt;(B3::compile(procedure, optLevel));
</span><span class="cx"> }
</span><span class="lines">@@ -987,6 +987,7 @@
</span><span class="cx"> 
</span><span class="cx">     test(0);
</span><span class="cx">     test(1);
</span><ins>+    test(2);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void testMulAddArgsLeft()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -102,8 +102,16 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Also allow add/remove/contains terminology, which means the same thing as set/clear/get.
</span><del>-    void add(Reg reg) { set(reg); }
-    void remove(Reg reg) { clear(reg); }
</del><ins>+    bool add(Reg reg)
+    {
+        ASSERT(!!reg);
+        return !m_bits.testAndSet(reg.index());
+    }
+    bool remove(Reg reg)
+    {
+        ASSERT(!!reg);
+        return m_bits.testAndClear(reg.index());
+    }
</ins><span class="cx">     bool contains(Reg reg) const { return get(reg); }
</span><span class="cx">     
</span><span class="cx">     void merge(const RegisterSet&amp; other) { m_bits.merge(other.m_bits); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -225,6 +225,7 @@
</span><span class="cx">     v(bool, useFTLJIT, true, Normal, &quot;allows the FTL JIT to be used if true&quot;) \
</span><span class="cx">     v(bool, useFTLTBAA, true, Normal, nullptr) \
</span><span class="cx">     v(bool, validateFTLOSRExitLiveness, false, Normal, nullptr) \
</span><ins>+    v(unsigned, defaultB3OptLevel, 2, Normal, nullptr) \
</ins><span class="cx">     v(bool, b3AlwaysFailsBeforeCompile, false, Normal, nullptr) \
</span><span class="cx">     v(bool, b3AlwaysFailsBeforeLink, false, Normal, nullptr) \
</span><span class="cx">     v(bool, ftlCrashes, false, Normal, nullptr) /* fool-proof way of checking that you ended up in the FTL. ;-) */\
</span><span class="lines">@@ -398,6 +399,8 @@
</span><span class="cx">     v(bool, logB3PhaseTimes, false, Normal, nullptr) \
</span><span class="cx">     v(double, rareBlockPenalty, 0.001, Normal, nullptr) \
</span><span class="cx">     v(bool, airSpillsEverything, false, Normal, nullptr) \
</span><ins>+    v(bool, airLinearScanVerbose, false, Normal, nullptr) \
+    v(bool, airLinearScanSpillsEverything, false, Normal, nullptr) \
</ins><span class="cx">     v(bool, airForceBriggsAllocator, false, Normal, nullptr) \
</span><span class="cx">     v(bool, airForceIRCAllocator, false, Normal, nullptr) \
</span><span class="cx">     v(bool, coalesceSpillSlots, true, Normal, nullptr) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include &quot;B3Common.h&quot;
</ins><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -48,7 +49,7 @@
</span><span class="cx">     CCallHelpers::Call jsEntrypointToWasmEntrypointCall;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;, MemoryMode, unsigned optLevel = 1);
</del><ins>+Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;, MemoryMode, unsigned optLevel = B3::defaultOptLevel());
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/ChangeLog        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2017-03-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should support linear scan for optLevel&lt;2
+        https://bugs.webkit.org/show_bug.cgi?id=170161
+
+        Reviewed by Saam Barati.
+        
+        This change introduces a new low-latency register allocator. It can allocate registers very
+        quickly by doing a relatively poor job. Implementing this algorithm required beefing up some of
+        our core algorithms.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/Deque.h: Make it possible to do some basic priority queueing with this data structure.
+        (WTF::inlineCapacity&gt;::removeAllMatching):
+        (WTF::inlineCapacity&gt;::appendAndBubble):
+        (WTF::inlineCapacity&gt;::takeLast):
+        * wtf/IndexKeyType.h: Added. This makes it possible to use IndexMap and IndexSet with value or pointer types. Previously they just worked with pointer types.
+        (WTF::IndexKeyType::index):
+        * wtf/IndexMap.h: Adopt IndexKeyType.
+        (WTF::IndexMap::operator[]):
+        (WTF::IndexMap::append):
+        * wtf/IndexSet.h: Adopt IndexKeyType.
+        (WTF::IndexSet::add):
+        (WTF::IndexSet::addAll):
+        (WTF::IndexSet::remove):
+        (WTF::IndexSet::contains):
+        (WTF::IndexSet::Iterable::iterator::operator*):
+        * wtf/Range.h: Added. This used to be B3::HeapRange. This generalizes that data structure to any kind of range stuff.
+        (WTF::Range::Range):
+        (WTF::Range::top):
+        (WTF::Range::operator==):
+        (WTF::Range::operator!=):
+        (WTF::Range::operator bool):
+        (WTF::Range::operator|):
+        (WTF::Range::operator|=):
+        (WTF::Range::begin):
+        (WTF::Range::end):
+        (WTF::Range::overlaps):
+        (WTF::Range::dump):
+        * wtf/RangeSet.h:
+        (WTF::RangeSet::add):
+
</ins><span class="cx"> 2017-03-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Move platformThreadSignal to WTF
</span></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -23,6 +23,8 @@
</span><span class="cx"> /* Begin PBXBuildFile section */
</span><span class="cx">                 0F0D85B417234CC100338210 /* NoLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0D85B317234CB100338210 /* NoLock.h */; };
</span><span class="cx">                 0F0FCDDE1DD167F900CCAB53 /* LockAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FCDDD1DD167F900CCAB53 /* LockAlgorithm.h */; };
</span><ins>+                0F2AC5611E89F70C0001EE3F /* Range.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5601E89F70C0001EE3F /* Range.h */; };
+                0F2AC5631E8A01490001EE3F /* IndexKeyType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5621E8A01490001EE3F /* IndexKeyType.h */; };
</ins><span class="cx">                 0F2B66A617B6B4FB00A7AE3F /* DeferrableRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */; };
</span><span class="cx">                 0F2B66A717B6B4FD00A7AE3F /* FlipBytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */; };
</span><span class="cx">                 0F30BA901E78708E002CA847 /* GlobalVersion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F30BA8A1E78708E002CA847 /* GlobalVersion.cpp */; };
</span><span class="lines">@@ -408,6 +410,8 @@
</span><span class="cx"> /* Begin PBXFileReference section */
</span><span class="cx">                 0F0D85B317234CB100338210 /* NoLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NoLock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0FCDDD1DD167F900CCAB53 /* LockAlgorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockAlgorithm.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F2AC5601E89F70C0001EE3F /* Range.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Range.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2AC5621E8A01490001EE3F /* IndexKeyType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexKeyType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeferrableRefCounted.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlipBytes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F300B7D18AB48B400A6D72E /* HashMethod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashMethod.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1018,10 +1022,11 @@
</span><span class="cx">                                 A8A472BA151A825A004123FF /* HashTraits.h */,
</span><span class="cx">                                 A8A472BB151A825A004123FF /* HexNumber.h */,
</span><span class="cx">                                 FE8925AF1D00DAEC0046907E /* Indenter.h */,
</span><del>-                                9C67C542589348E285B49699 /* IndexedContainerIterator.h */,
</del><ins>+                                0F2AC5621E8A01490001EE3F /* IndexKeyType.h */,
</ins><span class="cx">                                 5B43383A5D0B463C9433D933 /* IndexMap.h */,
</span><span class="cx">                                 3137E1D7DBD84AC38FAE4D34 /* IndexSet.h */,
</span><span class="cx">                                 2684D4351C000D400081D663 /* IndexSparseSet.h */,
</span><ins>+                                9C67C542589348E285B49699 /* IndexedContainerIterator.h */,
</ins><span class="cx">                                 A8A472BC151A825A004123FF /* InlineASM.h */,
</span><span class="cx">                                 A70DA0821799F04D00529A9B /* Insertion.h */,
</span><span class="cx">                                 7CDD7FF7186D291E007433CD /* IteratorAdaptors.h */,
</span><span class="lines">@@ -1100,6 +1105,7 @@
</span><span class="cx">                                 A8A472FB151A825B004123FF /* RandomNumber.cpp */,
</span><span class="cx">                                 A8A472FC151A825B004123FF /* RandomNumber.h */,
</span><span class="cx">                                 A8A472FD151A825B004123FF /* RandomNumberSeed.h */,
</span><ins>+                                0F2AC5601E89F70C0001EE3F /* Range.h */,
</ins><span class="cx">                                 0F725CAB1C50461600AD943A /* RangeSet.h */,
</span><span class="cx">                                 0F87105916643F190090B0AD /* RawPointer.h */,
</span><span class="cx">                                 0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */,
</span><span class="lines">@@ -1485,6 +1491,7 @@
</span><span class="cx">                                 C916B975F02F4F7E8B4AB12D /* IndexMap.h in Headers */,
</span><span class="cx">                                 C8B0E1A1E01A486EB95E0D11 /* IndexSet.h in Headers */,
</span><span class="cx">                                 2684D4361C000D400081D663 /* IndexSparseSet.h in Headers */,
</span><ins>+                                0F2AC5631E8A01490001EE3F /* IndexKeyType.h in Headers */,
</ins><span class="cx">                                 A8A473DC151A825B004123FF /* InlineASM.h in Headers */,
</span><span class="cx">                                 A70DA0841799F04D00529A9B /* Insertion.h in Headers */,
</span><span class="cx">                                 26147B0A15DDCCDC00DDB907 /* IntegerToStringConversion.h in Headers */,
</span><span class="lines">@@ -1586,6 +1593,7 @@
</span><span class="cx">                                 430B47891AAAAC1A001223DA /* StringCommon.h in Headers */,
</span><span class="cx">                                 A8A4743E151A825B004123FF /* StringConcatenate.h in Headers */,
</span><span class="cx">                                 7CD4C2701E2C82B900929470 /* StringConcatenateNumbers.h in Headers */,
</span><ins>+                                0F2AC5611E89F70C0001EE3F /* Range.h in Headers */,
</ins><span class="cx">                                 A8A4742C151A825B004123FF /* StringExtras.h in Headers */,
</span><span class="cx">                                 A8A4743F151A825B004123FF /* StringHash.h in Headers */,
</span><span class="cx">                                 A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -100,6 +100,7 @@
</span><span class="cx">     RAMSize.h
</span><span class="cx">     RandomNumber.h
</span><span class="cx">     RandomNumberSeed.h
</span><ins>+    Range.h
</ins><span class="cx">     RangeSet.h
</span><span class="cx">     RawPointer.h
</span><span class="cx">     RecursiveLockAdapter.h
</span></span></pre></div>
<a id="trunkSourceWTFwtfDequeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Deque.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Deque.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/wtf/Deque.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2007, 2008, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2009 Google Inc. All rights reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -89,6 +89,19 @@
</span><span class="cx">     void removeLast();
</span><span class="cx">     void remove(iterator&amp;);
</span><span class="cx">     void remove(const_iterator&amp;);
</span><ins>+    
+    template&lt;typename Func&gt; void removeAllMatching(const Func&amp;);
+    
+    // This is a priority enqueue. The callback is given a value, and if it returns true, then this
+    // will put the appended value before that value. It will keep bubbling until the callback returns
+    // false or the value ends up at the head of the queue.
+    template&lt;typename U, typename Func&gt;
+    void appendAndBubble(U&amp;&amp;, const Func&amp;);
+    
+    // Remove and return the last element for which the callback returns true. Returns a null version of
+    // T if it the callback always returns false.
+    template&lt;typename Func&gt;
+    T takeLast(const Func&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void clear();
</span><span class="cx"> 
</span><span class="lines">@@ -524,6 +537,55 @@
</span><span class="cx">     checkValidity();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T, size_t inlineCapacity&gt;
+template&lt;typename Func&gt;
+inline void Deque&lt;T, inlineCapacity&gt;::removeAllMatching(const Func&amp; func)
+{
+    size_t count = size();
+    while (count--) {
+        T value = takeFirst();
+        if (!func(value))
+            append(WTFMove(value));
+    }
+}
+
+template&lt;typename T, size_t inlineCapacity&gt;
+template&lt;typename U, typename Func&gt;
+inline void Deque&lt;T, inlineCapacity&gt;::appendAndBubble(U&amp;&amp; value, const Func&amp; func)
+{
+    append(WTFMove(value));
+    iterator begin = this-&gt;begin();
+    iterator iter = end();
+    --iter;
+    while (iter != begin) {
+        iterator prev = iter;
+        --prev;
+        if (!func(*prev))
+            return;
+        std::swap(*prev, *iter);
+        iter = prev;
+    }
+}
+
+template&lt;typename T, size_t inlineCapacity&gt;
+template&lt;typename Func&gt;
+inline T Deque&lt;T, inlineCapacity&gt;::takeLast(const Func&amp; func)
+{
+    unsigned count = 0;
+    unsigned size = this-&gt;size();
+    while (count &lt; size) {
+        T candidate = takeLast();
+        if (func(candidate)) {
+            while (count--)
+                append(takeFirst());
+            return candidate;
+        }
+        count++;
+        prepend(WTFMove(candidate));
+    }
+    return T();
+}
+
</ins><span class="cx"> #ifdef NDEBUG
</span><span class="cx"> template&lt;typename T, size_t inlineCapacity&gt; inline void DequeIteratorBase&lt;T, inlineCapacity&gt;::checkValidity() const { }
</span><span class="cx"> template&lt;typename T, size_t inlineCapacity&gt; inline void DequeIteratorBase&lt;T, inlineCapacity&gt;::checkValidity(const DequeIteratorBase&lt;T, inlineCapacity&gt;&amp;) const { }
</span></span></pre></div>
<a id="trunkSourceWTFwtfIndexKeyTypeh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/IndexKeyType.h (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/IndexKeyType.h                                (rev 0)
+++ trunk/Source/WTF/wtf/IndexKeyType.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2017 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. 
+ */
+
+#pragma once
+
+namespace WTF {
+
+template&lt;typename T&gt;
+struct IndexKeyType {
+    static size_t index(const T&amp; key) { return key.index(); }
+};
+
+template&lt;typename T&gt;
+struct IndexKeyType&lt;T*&gt; {
+    static size_t index(T* key) { return key-&gt;index(); }
+};
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfIndexMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/IndexMap.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/IndexMap.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/wtf/IndexMap.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/IndexKeyType.h&gt;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -70,18 +71,24 @@
</span><span class="cx">         return m_vector[index];
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Value&amp; operator[](Key* key)
</del><ins>+    Value&amp; operator[](const Key&amp; key)
</ins><span class="cx">     {
</span><del>-        return m_vector[key-&gt;index()];
</del><ins>+        return m_vector[IndexKeyType&lt;Key&gt;::index(key)];
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    const Value&amp; operator[](Key* key) const
</del><ins>+    const Value&amp; operator[](const Key&amp; key) const
</ins><span class="cx">     {
</span><del>-        return m_vector[key-&gt;index()];
</del><ins>+        return m_vector[IndexKeyType&lt;Key&gt;::index(key)];
</ins><span class="cx">     }
</span><ins>+    
+    void append(const Key&amp; key, Value value)
+    {
+        RELEASE_ASSERT(IndexKeyType&lt;Key&gt;::index(key) == m_vector.size());
+        m_vector.append(value);
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    Vector&lt;Value&gt; m_vector;
</del><ins>+    Vector&lt;Value, 0, UnsafeVectorOverflow&gt; m_vector;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span></span></pre></div>
<a id="trunkSourceWTFwtfIndexSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/IndexSet.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/IndexSet.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/wtf/IndexSet.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 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">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/BitVector.h&gt;
</span><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><ins>+#include &lt;wtf/IndexKeyType.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="lines">@@ -42,9 +43,9 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool add(T* value)
</del><ins>+    bool add(const T&amp; value)
</ins><span class="cx">     {
</span><del>-        return !m_set.set(value-&gt;index());
</del><ins>+        return !m_set.set(IndexKeyType&lt;T&gt;::index(value));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename Iterable&gt;
</span><span class="lines">@@ -51,21 +52,21 @@
</span><span class="cx">     bool addAll(const Iterable&amp; iterable)
</span><span class="cx">     {
</span><span class="cx">         bool result = false;
</span><del>-        for (T* value : iterable)
</del><ins>+        for (const T&amp; value : iterable)
</ins><span class="cx">             result |= add(value);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool remove(T* value)
</del><ins>+    bool remove(const T&amp; value)
</ins><span class="cx">     {
</span><del>-        return m_set.clear(value-&gt;index());
</del><ins>+        return m_set.clear(IndexKeyType&lt;T&gt;::index(value));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool contains(T* value) const
</del><ins>+    bool contains(const T&amp; value) const
</ins><span class="cx">     {
</span><span class="cx">         if (!value)
</span><span class="cx">             return false;
</span><del>-        return m_set.get(value-&gt;index());
</del><ins>+        return m_set.get(IndexKeyType&lt;T&gt;::index(value));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     size_t size() const
</span><span class="lines">@@ -100,7 +101,7 @@
</span><span class="cx">             {
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            T* operator*()
</del><ins>+            T operator*()
</ins><span class="cx">             {
</span><span class="cx">                 return m_collection-&gt;at(*m_iter);
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceWTFwtfRangeh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/Range.h (0 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Range.h                                (rev 0)
+++ trunk/Source/WTF/wtf/Range.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -0,0 +1,137 @@
</span><ins>+/*
+ * Copyright (C) 2015-2017 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. 
+ */
+
+#pragma once
+
+#include &lt;limits.h&gt;
+#include &lt;wtf/MathExtras.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace WTF {
+
+// Note that the 'begin' is inclusive, while the 'end' is exclusive. These two ranges are non-
+// overlapping:
+//
+//     rangeA = 0...8
+//     rangeB = 8...16
+
+template&lt;typename PassedType&gt;
+class Range {
+public:
+    typedef PassedType Type;
+    
+    Range()
+        : m_begin(0)
+        , m_end(0)
+    {
+    }
+
+    explicit Range(Type value)
+        : m_begin(value)
+        , m_end(value + 1)
+    {
+        ASSERT(m_end &gt;= m_begin);
+    }
+
+    Range(Type begin, Type end)
+        : m_begin(begin)
+        , m_end(end)
+    {
+        ASSERT(m_end &gt;= m_begin);
+        if (m_begin == m_end) {
+            // Canonicalize empty ranges.
+            m_begin = 0;
+            m_end = 0;
+        }
+    }
+
+    static Range top()
+    {
+        return Range(std::numeric_limits&lt;Type&gt;::min(), std::numeric_limits&lt;Type&gt;::max());
+    }
+
+    bool operator==(const Range&amp; other) const
+    {
+        return m_begin == other.m_begin
+            &amp;&amp; m_end == other.m_end;
+    }
+
+    bool operator!=(const Range&amp; other) const
+    {
+        return !(*this == other);
+    }
+    
+    explicit operator bool() const { return m_begin != m_end; }
+
+    Range operator|(const Range&amp; other) const
+    {
+        if (!*this)
+            return other;
+        if (!other)
+            return *this;
+        return Range(
+            std::min(m_begin, other.m_begin),
+            std::max(m_end, other.m_end));
+    }
+    
+    Range&amp; operator|=(const Range&amp; other)
+    {
+        return *this = *this | other;
+    }
+    
+    Type begin() const { return m_begin; }
+    Type end() const { return m_end; }
+
+    bool overlaps(const Range&amp; other) const
+    {
+        return WTF::rangesOverlap(m_begin, m_end, other.m_begin, other.m_end);
+    }
+
+    void dump(PrintStream&amp; out) const
+    {
+        if (*this == Range()) {
+            out.print(&quot;Bottom&quot;);
+            return;
+        }
+        if (*this == top()) {
+            out.print(&quot;Top&quot;);
+            return;
+        }
+        if (m_begin == m_end + 1) {
+            out.print(m_begin);
+            return;
+        }
+        out.print(m_begin, &quot;...&quot;, m_end);
+    }
+
+private:
+    Type m_begin;
+    Type m_end;
+};
+
+} // namespace WTF
+
+using WTF::Range;
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfRangeSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/RangeSet.h (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/RangeSet.h        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Source/WTF/wtf/RangeSet.h        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -77,6 +77,10 @@
</span><span class="cx">         m_isCompact = false;
</span><span class="cx"> 
</span><span class="cx">         // We append without compacting only if doing so is guaranteed not to resize the vector.
</span><ins>+        // FIXME: This heuristic is almost certainly wrong, because we don't control the capacity. I
+        // think that this means that we will sometimes be rage-compacting when we are just shy of the
+        // capacity.
+        // https://bugs.webkit.org/show_bug.cgi?id=170308
</ins><span class="cx">         if (m_ranges.size() + 1 &lt; m_ranges.capacity()) {
</span><span class="cx">             m_ranges.append(range);
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Tools/ChangeLog        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-03-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should support linear scan for optLevel&lt;2
+        https://bugs.webkit.org/show_bug.cgi?id=170161
+
+        Reviewed by Saam Barati.
+        
+        This makes us run a bunch of JS tests at optLevel=1 to force testing of this new compiler
+        pipeline.
+
+        * Scripts/run-jsc-stress-tests:
+
</ins><span class="cx"> 2017-03-30  Aakash Jain  &lt;aakash_jain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Support tvOS and watchOS in webkitdirs.pm
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (214635 => 214636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2017-03-30 22:41:14 UTC (rev 214635)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2017-03-30 22:55:44 UTC (rev 214636)
</span><span class="lines">@@ -428,6 +428,7 @@
</span><span class="cx"> BASE_OPTIONS = [&quot;--useFTLJIT=false&quot;, &quot;--useFunctionDotArguments=true&quot;, &quot;--maxPerThreadStackUsage=1572864&quot;]
</span><span class="cx"> EAGER_OPTIONS = [&quot;--thresholdForJITAfterWarmUp=10&quot;, &quot;--thresholdForJITSoon=10&quot;, &quot;--thresholdForOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForOptimizeAfterLongWarmUp=20&quot;, &quot;--thresholdForOptimizeSoon=20&quot;, &quot;--thresholdForFTLOptimizeAfterWarmUp=20&quot;, &quot;--thresholdForFTLOptimizeSoon=20&quot;, &quot;--maximumEvalCacheableSourceLength=150000&quot;, &quot;--useEagerCodeBlockJettisonTiming=true&quot;]
</span><span class="cx"> NO_CJIT_OPTIONS = [&quot;--useConcurrentJIT=false&quot;, &quot;--thresholdForJITAfterWarmUp=100&quot;, &quot;--scribbleFreeCells=true&quot;]
</span><ins>+B3O1_OPTIONS = [&quot;--defaultB3OptLevel=1&quot;]
</ins><span class="cx"> FTL_OPTIONS = [&quot;--useFTLJIT=true&quot;]
</span><span class="cx"> 
</span><span class="cx"> def shouldCollectContinuously?
</span><span class="lines">@@ -853,6 +854,10 @@
</span><span class="cx">     run(&quot;misc-ftl-no-cjit&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runFTLNoCJITB3O1(*optionalTestSpecificOptions)
+    run(&quot;ftl-no-cjit-b3o1&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O1_OPTIONS + optionalTestSpecificOptions))
+end
+
</ins><span class="cx"> def runFTLNoCJITValidate(*optionalTestSpecificOptions)
</span><span class="cx">     run(&quot;ftl-no-cjit-validate-sampling-profiler&quot;, &quot;--validateGraph=true&quot;, &quot;--useSamplingProfiler=true&quot;, &quot;--airForceIRCAllocator=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="lines">@@ -885,6 +890,10 @@
</span><span class="cx">     run(&quot;ftl-eager-no-cjit&quot;, &quot;--validateGraph=true&quot;, &quot;--airForceIRCAllocator=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runFTLEagerNoCJITB3O1(*optionalTestSpecificOptions)
+    run(&quot;ftl-eager-no-cjit&quot;, &quot;--validateGraph=true&quot;, &quot;--airForceIRCAllocator=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + B3O1_OPTIONS + optionalTestSpecificOptions))
+end
+
</ins><span class="cx"> def runFTLEagerNoCJITOSRValidation(*optionalTestSpecificOptions)
</span><span class="cx">     run(&quot;ftl-eager-no-cjit-osr-validation&quot;, &quot;--validateFTLOSRExitLiveness=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="lines">@@ -934,10 +943,12 @@
</span><span class="cx"> 
</span><span class="cx">             runNoFTL
</span><span class="cx">             runFTLNoCJITValidate
</span><ins>+            runFTLNoCJITB3O1
</ins><span class="cx">             runFTLNoCJITNoPutStackValidate
</span><span class="cx">             runFTLNoCJITNoInlineValidate
</span><span class="cx">             runFTLEager
</span><span class="cx">             runFTLEagerNoCJITValidate
</span><ins>+            runFTLEagerNoCJITB3O1
</ins><span class="cx">             runFTLNoCJITSmallPool
</span><span class="cx">         end
</span><span class="cx">     end
</span><span class="lines">@@ -959,6 +970,7 @@
</span><span class="cx"> 
</span><span class="cx">             runNoFTL
</span><span class="cx">             runFTLNoCJITValidate
</span><ins>+            runFTLNoCJITB3O1
</ins><span class="cx">             runFTLNoCJITNoPutStackValidate
</span><span class="cx">             runFTLNoCJITNoInlineValidate
</span><span class="cx">             runFTLEager
</span><span class="lines">@@ -988,6 +1000,7 @@
</span><span class="cx"> 
</span><span class="cx">     runFTLNoCJITOSRValidation
</span><span class="cx">     runFTLNoCJITNoAccessInlining
</span><ins>+    runFTLNoCJITB3O1
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def defaultSpotCheck
</span><span class="lines">@@ -1010,6 +1023,7 @@
</span><span class="cx">         runNoFTL
</span><span class="cx">         runFTLNoCJITValidate
</span><span class="cx">         runFTLNoCJITNoInlineValidate
</span><ins>+        runFTLNoCJITB3O1
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1279,6 +1293,10 @@
</span><span class="cx">     runLayoutTest(&quot;ftl-eager-no-cjit&quot;, &quot;--testTheFTL=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS))
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runLayoutTestFTLEagerNoCJITB3O1
+    runLayoutTest(&quot;ftl-eager-no-cjit-b3o1&quot;, &quot;--testTheFTL=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + B3O1_OPTIONS))
+end
+
</ins><span class="cx"> def noFTLRunLayoutTest
</span><span class="cx">     if !$jitTests
</span><span class="cx">         return
</span><span class="lines">@@ -1463,6 +1481,10 @@
</span><span class="cx">     runNoisyTest(&quot;ftl-no-cjit&quot;, &quot;--validateBytecode=true&quot;, &quot;--validateGraphAtEachPhase=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS))
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runNoisyTestNoCJITB3O1
+    runNoisyTest(&quot;ftl-no-cjit&quot;, &quot;--validateBytecode=true&quot;, &quot;--validateGraphAtEachPhase=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O1_OPTIONS))
+end
+
</ins><span class="cx"> def runNoisyTestEagerNoCJIT
</span><span class="cx">     runNoisyTest(&quot;ftl-eager-no-cjit&quot;, &quot;--validateBytecode=true&quot;, &quot;--validateGraphAtEachPhase=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS))
</span><span class="cx"> end
</span><span class="lines">@@ -1472,6 +1494,7 @@
</span><span class="cx">     if $jitTests and $isFTLPlatform
</span><span class="cx">         runNoisyTestNoFTL
</span><span class="cx">         runNoisyTestNoCJIT
</span><ins>+        runNoisyTestNoCJITB3O1
</ins><span class="cx">         runNoisyTestEagerNoCJIT
</span><span class="cx">     end
</span><span class="cx"> end
</span></span></pre>
</div>
</div>

</body>
</html>