<!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>[207004] trunk/Source/JavaScriptCore</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/207004">207004</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-10-10 10:12:34 -0700 (Mon, 10 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Air should expose API for pinning registers
https://bugs.webkit.org/show_bug.cgi?id=163175

Reviewed by Keith Miller.
        
You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this
register behave as follows:
        
- B3 and Air will emit no code that modifies the value in this register, except if that
  happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it).
- B3 and Air will allow others to modify the register. For example, if the register is not
  callee-save, then the compiler knows that the register's value will be trashed by any
  C-style call.
- Air will be happy to emit code that reads from this register, including coalescing tmps
  with it, so longer as there is no interference (i.e. no chance of the register's value
  changing). For example, if we went back to having pinned tag registers, we would tell B3
  to use them by (1) excluding them from any clobber set (easy, since they're callee save)
  and (2) emitting ArgumentReg to grab their value. There's a test that does this.
        
This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 
already used this API when choosing registers in register allocation. Code now also vends a
mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if
a register can be mutated. Doing it this way means that most of this is a purely mechanical
change. The calls to mutableRegs() are the places where we had to change logic:
        
- The register allocators needs to know that coalescing with a precolored pinned tmp is free.
- The callee-save handler needs to know that we're not supposed to save/restore pinned
  registers.
        
Note that in this scheme, pinned registers are simply registers that do not appear in
regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So,
this means that you can also pin registers by calling setRegsInPriorityOrder() and passing a
vector that excludes some registers. More generally, this means that clients can now tweak
the register allocator's register preferences, since the ordering in that list reflects the
order in which the allocator will try registers.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::pinRegister):
* b3/B3Procedure.h:
* b3/air/AirCode.cpp:
(JSC::B3::Air::Code::Code):
(JSC::B3::Air::Code::setRegsInPriorityOrder):
(JSC::B3::Air::Code::pinRegister):
* b3/air/AirCode.h:
(JSC::B3::Air::Code::regsInPriorityOrder):
(JSC::B3::Air::Code::mutableRegs):
(JSC::B3::Air::Code::isPinned):
(JSC::B3::Air::Code::regsInPriorityOrderImpl):
(JSC::B3::Air::Code::proc): Deleted.
* b3/air/AirEmitShuffle.cpp:
(JSC::B3::Air::emitShuffle):
* b3/air/AirEmitShuffle.h:
* b3/air/AirHandleCalleeSaves.cpp:
(JSC::B3::Air::handleCalleeSaves):
* b3/air/AirIteratedRegisterCoalescing.cpp:
* b3/air/AirLowerAfterRegAlloc.cpp:
(JSC::B3::Air::lowerAfterRegAlloc):
* b3/air/AirRegisterPriority.cpp: Removed.
* b3/air/AirRegisterPriority.h: Removed.
* b3/air/AirSpillEverything.cpp:
(JSC::B3::Air::spillEverything):
* b3/air/testair.cpp:
(JSC::B3::Air::testShuffleBroadcastAllRegs):
(JSC::B3::Air::testShuffleShiftAllRegs):
(JSC::B3::Air::testShuffleRotateAllRegs):
(JSC::B3::Air::testShuffleShiftMemoryAllRegs):
(JSC::B3::Air::testShuffleShiftMemoryAllRegs64):
(JSC::B3::Air::testShuffleShiftMemoryAllRegsMixedWidth):
(JSC::B3::Air::testShuffleRotateMemoryAllRegs64):
(JSC::B3::Air::testShuffleRotateMemoryAllRegsMixedWidth):
* b3/testb3.cpp:
(JSC::B3::testPinRegisters):
(JSC::B3::run):
* jit/RegisterSet.h:</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="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedureh">trunk/Source/JavaScriptCore/b3/B3Procedure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCodecpp">trunk/Source/JavaScriptCore/b3/air/AirCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCodeh">trunk/Source/JavaScriptCore/b3/air/AirCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirEmitShufflecpp">trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirEmitShuffleh">trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirHandleCalleeSavescpp">trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirIteratedRegisterCoalescingcpp">trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp">trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp">trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airtestaircpp">trunk/Source/JavaScriptCore/b3/air/testair.cpp</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>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirRegisterPrioritycpp">trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirRegisterPriorityh">trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -96,7 +96,6 @@
</span><span class="cx">     b3/air/AirLowerMacros.cpp
</span><span class="cx">     b3/air/AirOptimizeBlockOrder.cpp
</span><span class="cx">     b3/air/AirPhaseScope.cpp
</span><del>-    b3/air/AirRegisterPriority.cpp
</del><span class="cx">     b3/air/AirReportUsedRegisters.cpp
</span><span class="cx">     b3/air/AirSimplifyCFG.cpp
</span><span class="cx">     b3/air/AirSpecial.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2016-10-09  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should expose API for pinning registers
+        https://bugs.webkit.org/show_bug.cgi?id=163175
+
+        Reviewed by Keith Miller.
+        
+        You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this
+        register behave as follows:
+        
+        - B3 and Air will emit no code that modifies the value in this register, except if that
+          happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it).
+        - B3 and Air will allow others to modify the register. For example, if the register is not
+          callee-save, then the compiler knows that the register's value will be trashed by any
+          C-style call.
+        - Air will be happy to emit code that reads from this register, including coalescing tmps
+          with it, so longer as there is no interference (i.e. no chance of the register's value
+          changing). For example, if we went back to having pinned tag registers, we would tell B3
+          to use them by (1) excluding them from any clobber set (easy, since they're callee save)
+          and (2) emitting ArgumentReg to grab their value. There's a test that does this.
+        
+        This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 
+        already used this API when choosing registers in register allocation. Code now also vends a
+        mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if
+        a register can be mutated. Doing it this way means that most of this is a purely mechanical
+        change. The calls to mutableRegs() are the places where we had to change logic:
+        
+        - The register allocators needs to know that coalescing with a precolored pinned tmp is free.
+        - The callee-save handler needs to know that we're not supposed to save/restore pinned
+          registers.
+        
+        Note that in this scheme, pinned registers are simply registers that do not appear in
+        regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So,
+        this means that you can also pin registers by calling setRegsInPriorityOrder() and passing a
+        vector that excludes some registers. More generally, this means that clients can now tweak
+        the register allocator's register preferences, since the ordering in that list reflects the
+        order in which the allocator will try registers.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::pinRegister):
+        * b3/B3Procedure.h:
+        * b3/air/AirCode.cpp:
+        (JSC::B3::Air::Code::Code):
+        (JSC::B3::Air::Code::setRegsInPriorityOrder):
+        (JSC::B3::Air::Code::pinRegister):
+        * b3/air/AirCode.h:
+        (JSC::B3::Air::Code::regsInPriorityOrder):
+        (JSC::B3::Air::Code::mutableRegs):
+        (JSC::B3::Air::Code::isPinned):
+        (JSC::B3::Air::Code::regsInPriorityOrderImpl):
+        (JSC::B3::Air::Code::proc): Deleted.
+        * b3/air/AirEmitShuffle.cpp:
+        (JSC::B3::Air::emitShuffle):
+        * b3/air/AirEmitShuffle.h:
+        * b3/air/AirHandleCalleeSaves.cpp:
+        (JSC::B3::Air::handleCalleeSaves):
+        * b3/air/AirIteratedRegisterCoalescing.cpp:
+        * b3/air/AirLowerAfterRegAlloc.cpp:
+        (JSC::B3::Air::lowerAfterRegAlloc):
+        * b3/air/AirRegisterPriority.cpp: Removed.
+        * b3/air/AirRegisterPriority.h: Removed.
+        * b3/air/AirSpillEverything.cpp:
+        (JSC::B3::Air::spillEverything):
+        * b3/air/testair.cpp:
+        (JSC::B3::Air::testShuffleBroadcastAllRegs):
+        (JSC::B3::Air::testShuffleShiftAllRegs):
+        (JSC::B3::Air::testShuffleRotateAllRegs):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegs):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegs64):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegsMixedWidth):
+        (JSC::B3::Air::testShuffleRotateMemoryAllRegs64):
+        (JSC::B3::Air::testShuffleRotateMemoryAllRegsMixedWidth):
+        * b3/testb3.cpp:
+        (JSC::B3::testPinRegisters):
+        (JSC::B3::run):
+        * jit/RegisterSet.h:
+
</ins><span class="cx"> 2016-10-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         B3 should know about mutable pinned registers
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -875,8 +875,6 @@
</span><span class="cx">                 0FEC85811BDACDC70080FF74 /* AirInstInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC855C1BDACDC70080FF74 /* AirInstInlines.h */; };
</span><span class="cx">                 0FEC85831BDACDC70080FF74 /* AirPhaseScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */; };
</span><span class="cx">                 0FEC85841BDACDC70080FF74 /* AirPhaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */; };
</span><del>-                0FEC85851BDACDC70080FF74 /* AirRegisterPriority.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */; };
-                0FEC85861BDACDC70080FF74 /* AirRegisterPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */; };
</del><span class="cx">                 0FEC85871BDACDC70080FF74 /* AirSpecial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */; };
</span><span class="cx">                 0FEC85881BDACDC70080FF74 /* AirSpecial.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85631BDACDC70080FF74 /* AirSpecial.h */; };
</span><span class="cx">                 0FEC85891BDACDC70080FF74 /* AirSpillEverything.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85641BDACDC70080FF74 /* AirSpillEverything.cpp */; };
</span><span class="lines">@@ -3151,8 +3149,6 @@
</span><span class="cx">                 0FEC855C1BDACDC70080FF74 /* AirInstInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirInstInlines.h; path = b3/air/AirInstInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirPhaseScope.cpp; path = b3/air/AirPhaseScope.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirPhaseScope.h; path = b3/air/AirPhaseScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirRegisterPriority.cpp; path = b3/air/AirRegisterPriority.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirRegisterPriority.h; path = b3/air/AirRegisterPriority.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSpecial.cpp; path = b3/air/AirSpecial.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC85631BDACDC70080FF74 /* AirSpecial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirSpecial.h; path = b3/air/AirSpecial.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEC85641BDACDC70080FF74 /* AirSpillEverything.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSpillEverything.cpp; path = b3/air/AirSpillEverything.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5063,8 +5059,6 @@
</span><span class="cx">                                 0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */,
</span><span class="cx">                                 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */,
</span><span class="cx">                                 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */,
</span><del>-                                0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */,
-                                0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */,
</del><span class="cx">                                 0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */,
</span><span class="cx">                                 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */,
</span><span class="cx">                                 0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */,
</span><span class="lines">@@ -7260,7 +7254,6 @@
</span><span class="cx">                                 0FEC85801BDACDC70080FF74 /* AirInst.h in Headers */,
</span><span class="cx">                                 0FEC85811BDACDC70080FF74 /* AirInstInlines.h in Headers */,
</span><span class="cx">                                 0FEC85841BDACDC70080FF74 /* AirPhaseScope.h in Headers */,
</span><del>-                                0FEC85861BDACDC70080FF74 /* AirRegisterPriority.h in Headers */,
</del><span class="cx">                                 0F45703D1BE45F0A0062A629 /* AirReportUsedRegisters.h in Headers */,
</span><span class="cx">                                 0FEC85881BDACDC70080FF74 /* AirSpecial.h in Headers */,
</span><span class="cx">                                 0FEC858A1BDACDC70080FF74 /* AirSpillEverything.h in Headers */,
</span><span class="lines">@@ -9001,7 +8994,6 @@
</span><span class="cx">                                 0FEC857D1BDACDC70080FF74 /* AirInsertionSet.cpp in Sources */,
</span><span class="cx">                                 0FEC857F1BDACDC70080FF74 /* AirInst.cpp in Sources */,
</span><span class="cx">                                 0FEC85831BDACDC70080FF74 /* AirPhaseScope.cpp in Sources */,
</span><del>-                                0FEC85851BDACDC70080FF74 /* AirRegisterPriority.cpp in Sources */,
</del><span class="cx">                                 0F45703C1BE45F0A0062A629 /* AirReportUsedRegisters.cpp in Sources */,
</span><span class="cx">                                 0FEC85871BDACDC70080FF74 /* AirSpecial.cpp in Sources */,
</span><span class="cx">                                 0FEC85891BDACDC70080FF74 /* AirSpillEverything.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -305,6 +305,11 @@
</span><span class="cx">     code().requestCallArgAreaSizeInBytes(size);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Procedure::pinRegister(Reg reg)
+{
+    code().pinRegister(reg);
+}
+
</ins><span class="cx"> unsigned Procedure::frameSize() const
</span><span class="cx"> {
</span><span class="cx">     return code().frameSize();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.h (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.h        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.h        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -212,8 +212,11 @@
</span><span class="cx">     unsigned callArgAreaSizeInBytes() const;
</span><span class="cx">     void requestCallArgAreaSizeInBytes(unsigned size);
</span><span class="cx"> 
</span><ins>+    // This tells the register allocators to stay away from this register.
+    JS_EXPORT_PRIVATE void pinRegister(Reg);
+
</ins><span class="cx">     JS_EXPORT_PRIVATE unsigned frameSize() const;
</span><del>-    const RegisterAtOffsetList&amp; calleeSaveRegisters() const;
</del><ins>+    JS_EXPORT_PRIVATE const RegisterAtOffsetList&amp; calleeSaveRegisters() const;
</ins><span class="cx"> 
</span><span class="cx">     PCToOriginMap&amp; pcToOriginMap() { return m_pcToOriginMap; }
</span><span class="cx">     PCToOriginMap releasePCToOriginMap() { return WTFMove(m_pcToOriginMap); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCode.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCode.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirCode.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -40,6 +40,26 @@
</span><span class="cx">     : m_proc(proc)
</span><span class="cx">     , m_lastPhaseName(&quot;initial&quot;)
</span><span class="cx"> {
</span><ins>+    // Come up with initial orderings of registers. The user may replace this with something else.
+    Arg::forEachType(
+        [&amp;] (Arg::Type type) {
+            Vector&lt;Reg&gt; result;
+            RegisterSet all = type == Arg::GP ? RegisterSet::allGPRs() : RegisterSet::allFPRs();
+            all.exclude(RegisterSet::stackRegisters());
+            all.exclude(RegisterSet::reservedHardwareRegisters());
+            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
+            all.forEach(
+                [&amp;] (Reg reg) {
+                    if (!calleeSave.get(reg))
+                        result.append(reg);
+                });
+            all.forEach(
+                [&amp;] (Reg reg) {
+                    if (calleeSave.get(reg))
+                        result.append(reg);
+                });
+            setRegsInPriorityOrder(type, result);
+        });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Code::~Code()
</span><span class="lines">@@ -46,6 +66,25 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Code::setRegsInPriorityOrder(Arg::Type type, const Vector&lt;Reg&gt;&amp; regs)
+{
+    regsInPriorityOrderImpl(type) = regs;
+    m_mutableRegs = RegisterSet();
+    Arg::forEachType(
+        [&amp;] (Arg::Type type) {
+            for (Reg reg : regsInPriorityOrder(type))
+                m_mutableRegs.set(reg);
+        });
+}
+
+void Code::pinRegister(Reg reg)
+{
+    Vector&lt;Reg&gt;&amp; regs = regsInPriorityOrderImpl(Arg(Tmp(reg)).type());
+    regs.removeFirst(reg);
+    m_mutableRegs.clear(reg);
+    ASSERT(!regs.contains(reg));
+}
+
</ins><span class="cx"> BasicBlock* Code::addBlock(double frequency)
</span><span class="cx"> {
</span><span class="cx">     std::unique_ptr&lt;BasicBlock&gt; block(new BasicBlock(m_blocks.size(), frequency));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCode.h (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCode.h        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirCode.h        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -63,6 +63,27 @@
</span><span class="cx">     ~Code();
</span><span class="cx"> 
</span><span class="cx">     Procedure&amp; proc() { return m_proc; }
</span><ins>+    
+    const Vector&lt;Reg&gt;&amp; regsInPriorityOrder(Arg::Type type) const
+    {
+        switch (type) {
+        case Arg::GP:
+            return m_gpRegsInPriorityOrder;
+        case Arg::FP:
+            return m_fpRegsInPriorityOrder;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    
+    void setRegsInPriorityOrder(Arg::Type, const Vector&lt;Reg&gt;&amp;);
+    
+    // This is the set of registers that Air is allowed to emit code to mutate. It's derived from
+    // regsInPriorityOrder. Any registers not in this set are said to be &quot;pinned&quot;.
+    const RegisterSet&amp; mutableRegs() const { return m_mutableRegs; }
+    
+    bool isPinned(Reg reg) const { return !mutableRegs().get(reg); }
+    
+    void pinRegister(Reg);
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE BasicBlock* addBlock(double frequency = 1);
</span><span class="cx"> 
</span><span class="lines">@@ -250,7 +271,21 @@
</span><span class="cx">     
</span><span class="cx">     Code(Procedure&amp;);
</span><span class="cx"> 
</span><ins>+    Vector&lt;Reg&gt;&amp; regsInPriorityOrderImpl(Arg::Type type)
+    {
+        switch (type) {
+        case Arg::GP:
+            return m_gpRegsInPriorityOrder;
+        case Arg::FP:
+            return m_fpRegsInPriorityOrder;
+        }
+        ASSERT_NOT_REACHED();
+    }
+
</ins><span class="cx">     Procedure&amp; m_proc; // Some meta-data, like byproducts, is stored in the Procedure.
</span><ins>+    Vector&lt;Reg&gt; m_gpRegsInPriorityOrder;
+    Vector&lt;Reg&gt; m_fpRegsInPriorityOrder;
+    RegisterSet m_mutableRegs;
</ins><span class="cx">     SparseCollection&lt;StackSlot&gt; m_stackSlots;
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;BasicBlock&gt;&gt; m_blocks;
</span><span class="cx">     SparseCollection&lt;Special&gt; m_specials;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirEmitShufflecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -28,8 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirCode.h&quot;
</ins><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><del>-#include &quot;AirRegisterPriority.h&quot;
</del><span class="cx"> #include &lt;wtf/GraphNodeWorklist.h&gt;
</span><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -40,8 +40,8 @@
</span><span class="cx"> bool verbose = false;
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Functor&gt;
</span><del>-Tmp findPossibleScratch(Arg::Type type, const Functor&amp; functor) {
-    for (Reg reg : regsInPriorityOrder(type)) {
</del><ins>+Tmp findPossibleScratch(Code&amp; code, Arg::Type type, const Functor&amp; functor) {
+    for (Reg reg : code.regsInPriorityOrder(type)) {
</ins><span class="cx">         Tmp tmp(reg);
</span><span class="cx">         if (functor(tmp))
</span><span class="cx">             return tmp;
</span><span class="lines">@@ -49,9 +49,9 @@
</span><span class="cx">     return Tmp();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Tmp findPossibleScratch(Arg::Type type, const Arg&amp; arg1, const Arg&amp; arg2) {
</del><ins>+Tmp findPossibleScratch(Code&amp; code, Arg::Type type, const Arg&amp; arg1, const Arg&amp; arg2) {
</ins><span class="cx">     return findPossibleScratch(
</span><del>-        type,
</del><ins>+        code, type,
</ins><span class="cx">         [&amp;] (Tmp tmp) -&gt; bool {
</span><span class="cx">             return !arg1.usesTmp(tmp) &amp;&amp; !arg2.usesTmp(tmp);
</span><span class="cx">         });
</span><span class="lines">@@ -79,7 +79,8 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Vector&lt;Inst&gt; emitShuffle(
</span><del>-    Vector&lt;ShufflePair&gt; pairs, std::array&lt;Arg, 2&gt; scratches, Arg::Type type, Value* origin)
</del><ins>+    Code&amp; code, Vector&lt;ShufflePair&gt; pairs, std::array&lt;Arg, 2&gt; scratches, Arg::Type type,
+    Value* origin)
</ins><span class="cx"> {
</span><span class="cx">     if (verbose) {
</span><span class="cx">         dataLog(
</span><span class="lines">@@ -303,7 +304,7 @@
</span><span class="cx">         
</span><span class="cx">         if (!isValidForm(move, pair.src().kind(), pair.dst().kind())) {
</span><span class="cx">             Tmp scratch =
</span><del>-                getScratch(scratchIndex, findPossibleScratch(type, pair.src(), pair.dst()));
</del><ins>+                getScratch(scratchIndex, findPossibleScratch(code, type, pair.src(), pair.dst()));
</ins><span class="cx">             RELEASE_ASSERT(scratch);
</span><span class="cx">             if (isValidForm(move, pair.src().kind(), Arg::Tmp))
</span><span class="cx">                 result.append(Inst(moveForWidth(pair.width()), origin, pair.src(), scratch));
</span><span class="lines">@@ -435,7 +436,7 @@
</span><span class="cx">                     // Moving data between two spills is rare. To get here a lot of rare stuff has to
</span><span class="cx">                     // all happen at once.
</span><span class="cx">                     
</span><del>-                    Tmp scratch = getScratch(0, findPossibleScratch(type, left, right));
</del><ins>+                    Tmp scratch = getScratch(0, findPossibleScratch(code, type, left, right));
</ins><span class="cx">                     RELEASE_ASSERT(scratch);
</span><span class="cx">                     result.append(Inst(moveForWidth(swapWidth), origin, left, scratch));
</span><span class="cx">                     result.append(Inst(swap, origin, scratch, right));
</span><span class="lines">@@ -469,7 +470,7 @@
</span><span class="cx">             // available register file.
</span><span class="cx"> 
</span><span class="cx">             Tmp scratch = findPossibleScratch(
</span><del>-                type,
</del><ins>+                code, type,
</ins><span class="cx">                 [&amp;] (Tmp tmp) -&gt; bool {
</span><span class="cx">                     for (ShufflePair pair : rotate.loop) {
</span><span class="cx">                         if (pair.src().usesTmp(tmp))
</span><span class="lines">@@ -512,7 +513,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Vector&lt;Inst&gt; emitShuffle(
</span><del>-    const Vector&lt;ShufflePair&gt;&amp; pairs,
</del><ins>+    Code&amp; code, const Vector&lt;ShufflePair&gt;&amp; pairs,
</ins><span class="cx">     const std::array&lt;Arg, 2&gt;&amp; gpScratch, const std::array&lt;Arg, 2&gt;&amp; fpScratch,
</span><span class="cx">     Value* origin)
</span><span class="cx"> {
</span><span class="lines">@@ -531,8 +532,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;Inst&gt; result;
</span><del>-    result.appendVector(emitShuffle(gpPairs, gpScratch, Arg::GP, origin));
-    result.appendVector(emitShuffle(fpPairs, fpScratch, Arg::FP, origin));
</del><ins>+    result.appendVector(emitShuffle(code, gpPairs, gpScratch, Arg::GP, origin));
+    result.appendVector(emitShuffle(code, fpPairs, fpScratch, Arg::FP, origin));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirEmitShuffleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirEmitShuffle.h        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -37,6 +37,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Air {
</span><span class="cx"> 
</span><ins>+class Code;
+
</ins><span class="cx"> class ShufflePair {
</span><span class="cx"> public:
</span><span class="cx">     ShufflePair()
</span><span class="lines">@@ -100,12 +102,12 @@
</span><span class="cx"> // NOTE: Use this method (and its friend below) to emit shuffles after register allocation. Before
</span><span class="cx"> // register allocation it is much better to simply use the Shuffle instruction.
</span><span class="cx"> Vector&lt;Inst&gt; emitShuffle(
</span><del>-    Vector&lt;ShufflePair&gt;, std::array&lt;Arg, 2&gt; scratch, Arg::Type, Value* origin);
</del><ins>+    Code&amp; code, Vector&lt;ShufflePair&gt;, std::array&lt;Arg, 2&gt; scratch, Arg::Type, Value* origin);
</ins><span class="cx"> 
</span><span class="cx"> // Perform a shuffle that involves any number of types. Pass scratch registers or memory locations
</span><span class="cx"> // for each type according to the rules above.
</span><span class="cx"> Vector&lt;Inst&gt; emitShuffle(
</span><del>-    const Vector&lt;ShufflePair&gt;&amp;,
</del><ins>+    Code&amp; code, const Vector&lt;ShufflePair&gt;&amp;,
</ins><span class="cx">     const std::array&lt;Arg, 2&gt;&amp; gpScratch, const std::array&lt;Arg, 2&gt;&amp; fpScratch,
</span><span class="cx">     Value* origin);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirHandleCalleeSavescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Now we filter to really get the callee saves.
</span><span class="cx">     usedCalleeSaves.filter(RegisterSet::calleeSaveRegisters());
</span><ins>+    usedCalleeSaves.filter(code.mutableRegs());
</ins><span class="cx">     usedCalleeSaves.exclude(RegisterSet::stackRegisters()); // We don't need to save FP here.
</span><span class="cx"> 
</span><span class="cx">     if (!usedCalleeSaves.numberOfSetRegisters())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirIteratedRegisterCoalescingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -33,7 +33,6 @@
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><del>-#include &quot;AirRegisterPriority.h&quot;
</del><span class="cx"> #include &quot;AirTmpInlines.h&quot;
</span><span class="cx"> #include &quot;AirTmpWidth.h&quot;
</span><span class="cx"> #include &quot;AirUseCounts.h&quot;
</span><span class="lines">@@ -57,8 +56,11 @@
</span><span class="cx">         , m_lastPrecoloredRegisterIndex(lastPrecoloredRegisterIndex)
</span><span class="cx">         , m_unspillableTmps(unspillableTmp)
</span><span class="cx">     {
</span><ins>+        for (Reg reg : m_regsInPriorityOrder)
+            m_mutableRegs.set(reg);
+        
</ins><span class="cx">         initializeDegrees(tmpArraySize);
</span><del>-
</del><ins>+        
</ins><span class="cx">         m_adjacencyList.resize(tmpArraySize);
</span><span class="cx">         m_moveList.resize(tmpArraySize);
</span><span class="cx">         m_coalescedTmps.fill(0, tmpArraySize);
</span><span class="lines">@@ -161,7 +163,7 @@
</span><span class="cx">             std::swap(u, v);
</span><span class="cx"> 
</span><span class="cx">         if (traceDebug)
</span><del>-            dataLog(&quot;Coalescing move at index&quot;, moveIndex, &quot; u = &quot;, u, &quot; v = &quot;, v, &quot;\n&quot;);
</del><ins>+            dataLog(&quot;Coalescing move at index &quot;, moveIndex, &quot; u = &quot;, u, &quot; v = &quot;, v, &quot;\n&quot;);
</ins><span class="cx"> 
</span><span class="cx">         if (u == v) {
</span><span class="cx">             addWorkList(u);
</span><span class="lines">@@ -461,8 +463,15 @@
</span><span class="cx"> 
</span><span class="cx">     bool precoloredCoalescingHeuristic(IndexType u, IndexType v)
</span><span class="cx">     {
</span><ins>+        if (traceDebug)
+            dataLog(&quot;    Checking precoloredCoalescingHeuristic\n&quot;);
</ins><span class="cx">         ASSERT(isPrecolored(u));
</span><span class="cx">         ASSERT(!isPrecolored(v));
</span><ins>+        
+        // If u is a pinned register then it's always safe to coalesce. Note that when we call this,
+        // we have already proved that there is no interference between u and v.
+        if (!m_mutableRegs.get(m_coloredTmp[u]))
+            return true;
</ins><span class="cx"> 
</span><span class="cx">         // If any adjacent of the non-colored node is not an adjacent of the colored node AND has a degree &gt;= K
</span><span class="cx">         // there is a risk that this node needs to have the same color as our precolored node. If we coalesce such
</span><span class="lines">@@ -549,6 +558,7 @@
</span><span class="cx">     typedef SimpleClassHashTraits&lt;InterferenceEdge&gt; InterferenceEdgeHashTraits;
</span><span class="cx"> 
</span><span class="cx">     const Vector&lt;Reg&gt;&amp; m_regsInPriorityOrder;
</span><ins>+    RegisterSet m_mutableRegs;
</ins><span class="cx">     IndexType m_lastPrecoloredRegisterIndex { 0 };
</span><span class="cx"> 
</span><span class="cx">     // The interference graph.
</span><span class="lines">@@ -727,7 +737,7 @@
</span><span class="cx"> class ColoringAllocator : public AbstractColoringAllocator&lt;unsigned&gt; {
</span><span class="cx"> public:
</span><span class="cx">     ColoringAllocator(Code&amp; code, TmpWidth&amp; tmpWidth, const UseCounts&lt;Tmp&gt;&amp; useCounts, const HashSet&lt;unsigned&gt;&amp; unspillableTmp)
</span><del>-        : AbstractColoringAllocator&lt;unsigned&gt;(regsInPriorityOrder(type), AbsoluteTmpMapper&lt;type&gt;::lastMachineRegisterIndex(), tmpArraySize(code), unspillableTmp)
</del><ins>+        : AbstractColoringAllocator&lt;unsigned&gt;(code.regsInPriorityOrder(type), AbsoluteTmpMapper&lt;type&gt;::lastMachineRegisterIndex(), tmpArraySize(code), unspillableTmp)
</ins><span class="cx">         , m_code(code)
</span><span class="cx">         , m_tmpWidth(tmpWidth)
</span><span class="cx">         , m_useCounts(useCounts)
</span><span class="lines">@@ -839,7 +849,7 @@
</span><span class="cx">         if (!reg) {
</span><span class="cx">             // We only care about Tmps that interfere. A Tmp that never interfere with anything
</span><span class="cx">             // can take any register.
</span><del>-            reg = regsInPriorityOrder(type).first();
</del><ins>+            reg = m_code.regsInPriorityOrder(type).first();
</ins><span class="cx">         }
</span><span class="cx">         return reg;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -36,7 +36,6 @@
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><del>-#include &quot;AirRegisterPriority.h&quot;
</del><span class="cx"> #include &quot;B3CCallValue.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="lines">@@ -86,7 +85,7 @@
</span><span class="cx">         std::array&lt;Arg, 2&gt; result;
</span><span class="cx">         for (unsigned i = 0; i &lt; 2; ++i) {
</span><span class="cx">             bool found = false;
</span><del>-            for (Reg reg : regsInPriorityOrder(type)) {
</del><ins>+            for (Reg reg : code.regsInPriorityOrder(type)) {
</ins><span class="cx">                 if (!set.get(reg)) {
</span><span class="cx">                     result[i] = Tmp(reg);
</span><span class="cx">                     set.set(reg);
</span><span class="lines">@@ -134,7 +133,7 @@
</span><span class="cx">                 std::array&lt;Arg, 2&gt; gpScratch = getScratches(set, Arg::GP);
</span><span class="cx">                 std::array&lt;Arg, 2&gt; fpScratch = getScratches(set, Arg::FP);
</span><span class="cx">                 insertionSet.insertInsts(
</span><del>-                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
</del><ins>+                    instIndex, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
</ins><span class="cx">                 inst = Inst();
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -193,7 +192,7 @@
</span><span class="cx">                     dataLog(&quot;Pre-call pairs for &quot;, inst, &quot;: &quot;, listDump(pairs), &quot;\n&quot;);
</span><span class="cx">                 
</span><span class="cx">                 insertionSet.insertInsts(
</span><del>-                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
</del><ins>+                    instIndex, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
</ins><span class="cx"> 
</span><span class="cx">                 inst = buildCCall(code, inst.origin, destinations);
</span><span class="cx">                 if (oldKind.traps)
</span><span class="lines">@@ -224,7 +223,7 @@
</span><span class="cx">                 fpScratch = getScratches(liveRegs, Arg::FP);
</span><span class="cx">                 
</span><span class="cx">                 insertionSet.insertInsts(
</span><del>-                    instIndex + 1, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
</del><ins>+                    instIndex + 1, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirRegisterPrioritycpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -1,104 +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;AirRegisterPriority.h&quot;
-
-#if ENABLE(B3_JIT)
-
-#include &quot;RegisterSet.h&quot;
-
-namespace JSC { namespace B3 { namespace Air {
-
-const Vector&lt;GPRReg&gt;&amp; gprsInPriorityOrder()
-{
-    static Vector&lt;GPRReg&gt;* result;
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result = new Vector&lt;GPRReg&gt;();
-            RegisterSet all = RegisterSet::allGPRs();
-            all.exclude(RegisterSet::stackRegisters());
-            all.exclude(RegisterSet::reservedHardwareRegisters());
-            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
-            all.forEach(
-                [&amp;] (Reg reg) {
-                    if (!calleeSave.get(reg))
-                        result-&gt;append(reg.gpr());
-                });
-            all.forEach(
-                [&amp;] (Reg reg) {
-                    if (calleeSave.get(reg))
-                        result-&gt;append(reg.gpr());
-                });
-        });
-    return *result;
-}
-
-const Vector&lt;FPRReg&gt;&amp; fprsInPriorityOrder()
-{
-    static Vector&lt;FPRReg&gt;* result;
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result = new Vector&lt;FPRReg&gt;();
-            RegisterSet all = RegisterSet::allFPRs();
-            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
-            all.forEach(
-                [&amp;] (Reg reg) {
-                    if (!calleeSave.get(reg))
-                        result-&gt;append(reg.fpr());
-                });
-            all.forEach(
-                [&amp;] (Reg reg) {
-                    if (calleeSave.get(reg))
-                        result-&gt;append(reg.fpr());
-                });
-        });
-    return *result;
-}
-
-const Vector&lt;Reg&gt;&amp; regsInPriorityOrder(Arg::Type type)
-{
-    static Vector&lt;Reg&gt;* result[Arg::numTypes];
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result[Arg::GP] = new Vector&lt;Reg&gt;();
-            for (GPRReg reg : gprsInPriorityOrder())
-                result[Arg::GP]-&gt;append(Reg(reg));
-            result[Arg::FP] = new Vector&lt;Reg&gt;();
-            for (FPRReg reg : fprsInPriorityOrder())
-                result[Arg::FP]-&gt;append(Reg(reg));
-        });
-    return *result[type];
-}
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirRegisterPriorityh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.h (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.h        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirRegisterPriority.h        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -1,58 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#pragma once
-
-#if ENABLE(B3_JIT)
-
-#include &quot;AirArg.h&quot;
-#include &quot;FPRInfo.h&quot;
-#include &quot;GPRInfo.h&quot;
-#include &lt;wtf/Vector.h&gt;
-
-namespace JSC { namespace B3 { namespace Air {
-
-const Vector&lt;GPRReg&gt;&amp; gprsInPriorityOrder();
-const Vector&lt;FPRReg&gt;&amp; fprsInPriorityOrder();
-
-template&lt;typename Bank&gt; struct RegistersInPriorityOrder;
-template&lt;&gt; struct RegistersInPriorityOrder&lt;GPRInfo&gt; {
-    const Vector&lt;GPRReg&gt;&amp; inPriorityOrder() { return gprsInPriorityOrder(); }
-};
-template&lt;&gt; struct RegistersInPriorityOrder&lt;FPRInfo&gt; {
-    const Vector&lt;FPRReg&gt;&amp; inPriorityOrder() { return fprsInPriorityOrder(); }
-};
-
-template&lt;typename Bank&gt;
-const Vector&lt;typename Bank::RegisterType&gt;&amp; regsInPriorityOrder()
-{
-    return RegistersInPriorityOrder&lt;Bank&gt;::inPriorityOrder();
-}
-
-JS_EXPORT_PRIVATE const Vector&lt;Reg&gt;&amp; regsInPriorityOrder(Arg::Type);
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirSpillEverythingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -34,7 +34,6 @@
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirLiveness.h&quot;
</span><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><del>-#include &quot;AirRegisterPriority.h&quot;
</del><span class="cx"> #include &lt;wtf/IndexMap.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="lines">@@ -129,7 +128,7 @@
</span><span class="cx">                     switch (role) {
</span><span class="cx">                     case Arg::Use:
</span><span class="cx">                     case Arg::ColdUse:
</span><del>-                        for (Reg reg : regsInPriorityOrder(type)) {
</del><ins>+                        for (Reg reg : code.regsInPriorityOrder(type)) {
</ins><span class="cx">                             if (!setBefore.get(reg)) {
</span><span class="cx">                                 setBefore.set(reg);
</span><span class="cx">                                 chosenReg = reg;
</span><span class="lines">@@ -139,7 +138,7 @@
</span><span class="cx">                         break;
</span><span class="cx">                     case Arg::Def:
</span><span class="cx">                     case Arg::ZDef:
</span><del>-                        for (Reg reg : regsInPriorityOrder(type)) {
</del><ins>+                        for (Reg reg : code.regsInPriorityOrder(type)) {
</ins><span class="cx">                             if (!setAfter.get(reg)) {
</span><span class="cx">                                 setAfter.set(reg);
</span><span class="cx">                                 chosenReg = reg;
</span><span class="lines">@@ -153,7 +152,7 @@
</span><span class="cx">                     case Arg::LateColdUse:
</span><span class="cx">                     case Arg::Scratch:
</span><span class="cx">                     case Arg::EarlyDef:
</span><del>-                        for (Reg reg : regsInPriorityOrder(type)) {
</del><ins>+                        for (Reg reg : code.regsInPriorityOrder(type)) {
</ins><span class="cx">                             if (!setBefore.get(reg) &amp;&amp; !setAfter.get(reg)) {
</span><span class="cx">                                 setAfter.set(reg);
</span><span class="cx">                                 setBefore.set(reg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airtestaircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/testair.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/testair.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/air/testair.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -28,7 +28,6 @@
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirGenerate.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><del>-#include &quot;AirRegisterPriority.h&quot;
</del><span class="cx"> #include &quot;AllowMacroScratchRegisterUsage.h&quot;
</span><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> #include &quot;B3Procedure.h&quot;
</span><span class="lines">@@ -393,7 +392,7 @@
</span><span class="cx">     B3::Procedure proc;
</span><span class="cx">     Code&amp; code = proc.code();
</span><span class="cx"> 
</span><del>-    const Vector&lt;Reg&gt;&amp; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    const Vector&lt;Reg&gt;&amp; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="cx">     root-&gt;append(Move, nullptr, Arg::imm(35), Tmp(GPRInfo::regT0));
</span><span class="lines">@@ -860,7 +859,7 @@
</span><span class="cx">     B3::Procedure proc;
</span><span class="cx">     Code&amp; code = proc.code();
</span><span class="cx"> 
</span><del>-    const Vector&lt;Reg&gt;&amp; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    const Vector&lt;Reg&gt;&amp; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="cx">     for (unsigned i = 0; i &lt; regs.size(); ++i)
</span><span class="lines">@@ -896,7 +895,7 @@
</span><span class="cx">     B3::Procedure proc;
</span><span class="cx">     Code&amp; code = proc.code();
</span><span class="cx"> 
</span><del>-    const Vector&lt;Reg&gt;&amp; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    const Vector&lt;Reg&gt;&amp; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="cx">     for (unsigned i = 0; i &lt; regs.size(); ++i)
</span><span class="lines">@@ -1168,7 +1167,7 @@
</span><span class="cx">     memory[0] = 35;
</span><span class="cx">     memory[1] = 36;
</span><span class="cx"> 
</span><del>-    Vector&lt;Reg&gt; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    Vector&lt;Reg&gt; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx">     regs.removeFirst(Reg(GPRInfo::regT0));
</span><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="lines">@@ -1218,7 +1217,7 @@
</span><span class="cx">     memory[0] = 35000000000000ll;
</span><span class="cx">     memory[1] = 36000000000000ll;
</span><span class="cx"> 
</span><del>-    Vector&lt;Reg&gt; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    Vector&lt;Reg&gt; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx">     regs.removeFirst(Reg(GPRInfo::regT0));
</span><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="lines">@@ -1279,7 +1278,7 @@
</span><span class="cx">     memory[0] = 35000000000000ll;
</span><span class="cx">     memory[1] = 36000000000000ll;
</span><span class="cx"> 
</span><del>-    Vector&lt;Reg&gt; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    Vector&lt;Reg&gt; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx">     regs.removeFirst(Reg(GPRInfo::regT0));
</span><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="lines">@@ -1469,7 +1468,7 @@
</span><span class="cx">     memory[0] = 35000000000000ll;
</span><span class="cx">     memory[1] = 36000000000000ll;
</span><span class="cx"> 
</span><del>-    Vector&lt;Reg&gt; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    Vector&lt;Reg&gt; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx">     regs.removeFirst(Reg(GPRInfo::regT0));
</span><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span><span class="lines">@@ -1521,7 +1520,7 @@
</span><span class="cx">     memory[0] = 35000000000000ll;
</span><span class="cx">     memory[1] = 36000000000000ll;
</span><span class="cx"> 
</span><del>-    Vector&lt;Reg&gt; regs = regsInPriorityOrder(Arg::GP);
</del><ins>+    Vector&lt;Reg&gt; regs = code.regsInPriorityOrder(Arg::GP);
</ins><span class="cx">     regs.removeFirst(Reg(GPRInfo::regT0));
</span><span class="cx"> 
</span><span class="cx">     BasicBlock* root = code.addBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -13327,6 +13327,60 @@
</span><span class="cx">     compile(proc);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testPinRegisters()
+{
+    auto go = [&amp;] (bool pin) {
+        Procedure proc;
+        RegisterSet csrs;
+        csrs.merge(RegisterSet::calleeSaveRegisters());
+        csrs.exclude(RegisterSet::stackRegisters());
+        if (pin) {
+            csrs.forEach(
+                [&amp;] (Reg reg) {
+                    proc.pinRegister(reg);
+                });
+        }
+        BasicBlock* root = proc.addBlock();
+        Value* a = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+        Value* b = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+        Value* c = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+        Value* d = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::regCS0);
+        root-&gt;appendNew&lt;CCallValue&gt;(
+            proc, Void, Origin(),
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), static_cast&lt;intptr_t&gt;(0x1234)));
+        root-&gt;appendNew&lt;CCallValue&gt;(
+            proc, Void, Origin(),
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), static_cast&lt;intptr_t&gt;(0x1235)),
+            a, b, c);
+        PatchpointValue* patchpoint = root-&gt;appendNew&lt;PatchpointValue&gt;(proc, Void, Origin());
+        patchpoint-&gt;appendSomeRegister(d);
+        patchpoint-&gt;setGenerator(
+            [&amp;] (CCallHelpers&amp;, const StackmapGenerationParams&amp; params) {
+                CHECK_EQ(params[0].gpr(), GPRInfo::regCS0);
+            });
+        root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin());
+        auto code = compile(proc);
+        bool usesCSRs = false;
+        for (Air::BasicBlock* block : proc.code()) {
+            for (Air::Inst&amp; inst : *block) {
+                if (inst.kind.opcode == Air::Patch &amp;&amp; inst.origin == patchpoint)
+                    continue;
+                inst.forEachTmpFast(
+                    [&amp;] (Air::Tmp tmp) {
+                        if (tmp.isReg())
+                            usesCSRs |= csrs.get(tmp.reg());
+                    });
+            }
+        }
+        for (const RegisterAtOffset&amp; regAtOffset : proc.calleeSaveRegisters())
+            usesCSRs |= csrs.get(regAtOffset.reg());
+        CHECK_EQ(usesCSRs, !pin);
+    };
+    
+    go(true);
+    go(false);
+}
+
</ins><span class="cx"> // Make sure the compiler does not try to optimize anything out.
</span><span class="cx"> NEVER_INLINE double zero()
</span><span class="cx"> {
</span><span class="lines">@@ -14774,6 +14828,7 @@
</span><span class="cx">     RUN(testTrappingStoreElimination());
</span><span class="cx">     RUN(testMoveConstants());
</span><span class="cx">     RUN(testPCOriginMapDoesntInsertNops());
</span><ins>+    RUN(testPinRegisters());
</ins><span class="cx">     
</span><span class="cx">     if (tasks.isEmpty())
</span><span class="cx">         usage();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (207003 => 207004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-10-10 17:11:42 UTC (rev 207003)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-10-10 17:12:34 UTC (rev 207004)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
</span><span class="cx">     static RegisterSet runtimeRegisters();
</span><span class="cx">     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
</span><del>-    static RegisterSet calleeSaveRegisters();
</del><ins>+    JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
</ins><span class="cx">     static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
</span><span class="cx">     static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt.
</span><span class="cx">     static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     size_t numberOfSetFPRs() const;
</span><span class="cx">     size_t numberOfSetRegisters() const { return m_bits.count(); }
</span><span class="cx">     
</span><del>-    void dump(PrintStream&amp;) const;
</del><ins>+    JS_EXPORT_PRIVATE void dump(PrintStream&amp;) const;
</ins><span class="cx">     
</span><span class="cx">     enum EmptyValueTag { EmptyValue };
</span><span class="cx">     enum DeletedValueTag { DeletedValue };
</span></span></pre>
</div>
</div>

</body>
</html>