<!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>[165196] 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/165196">165196</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-03-06 10:33:18 -0800 (Thu, 06 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Clarify how we deal with &quot;special&quot; registers
https://bugs.webkit.org/show_bug.cgi?id=129806

Reviewed by Michael Saboff.
        
Previously we had two different places that defined what &quot;stack&quot; registers are, a thing
called &quot;specialRegisters&quot; that had unclear meaning, and a really weird &quot;firstRealRegister&quot;/
&quot;secondRealRegister&quot;/&quot;nextRegister&quot; idiom in MacroAssembler that appeared to only be used by
one place and had a baked-in notion of what it meant for a register to be &quot;real&quot; or not.
        
It's not cool to use words like &quot;real&quot; and &quot;special&quot; to describe registers, especially if you
fail to qualify what that means. This originally made sense on X86 - &quot;real&quot; registers were
the ones that weren't &quot;stack related&quot; (so &quot;real&quot; was the opposite of &quot;stack&quot;). But on ARM64,
you also have to worry about the LR register, which we'd want to say is &quot;not real&quot; but it's
also not a &quot;stack&quot; register. This got super confusing.
        
So, this patch removes any mention of &quot;real&quot; registers, consolidates the knowledge of what is
a &quot;stack&quot; register, and uses the word special only in places where it's clearly defined and
where no better word comes to mind.
        
This cleans up the code and fixes what seems like it was probably a harmless ARM64 bug: the
Reg and RegisterSet data structures would sometimes think that FP was Q0. Somehow this
magically didn't break anything because you never need to save/restore either FP or Q0, but
it was still super weird.

* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::lastRegister):
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::nextRegister):
* ftl/FTLLocation.cpp:
(JSC::FTL::Location::restoreInto):
* ftl/FTLSaveRestore.cpp:
(JSC::FTL::saveAllRegisters):
(JSC::FTL::restoreAllRegisters):
* ftl/FTLSlowPathCall.cpp:
* jit/RegisterSet.cpp:
(JSC::RegisterSet::reservedHardwareRegisters):
(JSC::RegisterSet::runtimeRegisters):
(JSC::RegisterSet::specialRegisters):
(JSC::RegisterSet::calleeSaveRegisters):
* jit/RegisterSet.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerARM64Assemblerh">trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/MacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLocationcpp">trunk/Source/JavaScriptCore/ftl/FTLLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSaveRestorecpp">trunk/Source/JavaScriptCore/ftl/FTLSaveRestore.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLSlowPathCallcpp">trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSetcpp">trunk/Source/JavaScriptCore/jit/RegisterSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -1,5 +1,49 @@
</span><span class="cx"> 2014-03-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Clarify how we deal with &quot;special&quot; registers
+        https://bugs.webkit.org/show_bug.cgi?id=129806
+
+        Reviewed by Michael Saboff.
+        
+        Previously we had two different places that defined what &quot;stack&quot; registers are, a thing
+        called &quot;specialRegisters&quot; that had unclear meaning, and a really weird &quot;firstRealRegister&quot;/
+        &quot;secondRealRegister&quot;/&quot;nextRegister&quot; idiom in MacroAssembler that appeared to only be used by
+        one place and had a baked-in notion of what it meant for a register to be &quot;real&quot; or not.
+        
+        It's not cool to use words like &quot;real&quot; and &quot;special&quot; to describe registers, especially if you
+        fail to qualify what that means. This originally made sense on X86 - &quot;real&quot; registers were
+        the ones that weren't &quot;stack related&quot; (so &quot;real&quot; was the opposite of &quot;stack&quot;). But on ARM64,
+        you also have to worry about the LR register, which we'd want to say is &quot;not real&quot; but it's
+        also not a &quot;stack&quot; register. This got super confusing.
+        
+        So, this patch removes any mention of &quot;real&quot; registers, consolidates the knowledge of what is
+        a &quot;stack&quot; register, and uses the word special only in places where it's clearly defined and
+        where no better word comes to mind.
+        
+        This cleans up the code and fixes what seems like it was probably a harmless ARM64 bug: the
+        Reg and RegisterSet data structures would sometimes think that FP was Q0. Somehow this
+        magically didn't break anything because you never need to save/restore either FP or Q0, but
+        it was still super weird.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::lastRegister):
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::nextRegister):
+        * ftl/FTLLocation.cpp:
+        (JSC::FTL::Location::restoreInto):
+        * ftl/FTLSaveRestore.cpp:
+        (JSC::FTL::saveAllRegisters):
+        (JSC::FTL::restoreAllRegisters):
+        * ftl/FTLSlowPathCall.cpp:
+        * jit/RegisterSet.cpp:
+        (JSC::RegisterSet::reservedHardwareRegisters):
+        (JSC::RegisterSet::runtimeRegisters):
+        (JSC::RegisterSet::specialRegisters):
+        (JSC::RegisterSet::calleeSaveRegisters):
+        * jit/RegisterSet.h:
+
+2014-03-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         Unreviewed, fix build.
</span><span class="cx"> 
</span><span class="cx">         * disassembler/ARM64Disassembler.cpp:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerARM64Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2014 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">@@ -478,7 +478,7 @@
</span><span class="cx">     typedef ARM64Registers::FPRegisterID FPRegisterID;
</span><span class="cx">     
</span><span class="cx">     static RegisterID firstRegister() { return ARM64Registers::x0; }
</span><del>-    static RegisterID lastRegister() { return ARM64Registers::x28; }
</del><ins>+    static RegisterID lastRegister() { return ARM64Registers::sp; }
</ins><span class="cx">     
</span><span class="cx">     static FPRegisterID firstFPRegister() { return ARM64Registers::q0; }
</span><span class="cx">     static FPRegisterID lastFPRegister() { return ARM64Registers::q31; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssembler.h (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2012, 2013, 2014 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">@@ -69,32 +69,11 @@
</span><span class="cx"> class MacroAssembler : public MacroAssemblerBase {
</span><span class="cx"> public:
</span><span class="cx"> 
</span><del>-    static bool isStackRelated(RegisterID reg)
-    {
-        return reg == stackPointerRegister || reg == framePointerRegister;
-    }
-    
-    static RegisterID firstRealRegister()
-    {
-        RegisterID firstRegister = MacroAssembler::firstRegister();
-        while (MacroAssembler::isStackRelated(firstRegister))
-            firstRegister = static_cast&lt;RegisterID&gt;(firstRegister + 1);
-        return firstRegister;
-    }
-    
</del><span class="cx">     static RegisterID nextRegister(RegisterID reg)
</span><span class="cx">     {
</span><del>-        RegisterID result = static_cast&lt;RegisterID&gt;(reg + 1);
-        while (MacroAssembler::isStackRelated(result))
-            result = static_cast&lt;RegisterID&gt;(result + 1);
-        return result;
</del><ins>+        return static_cast&lt;RegisterID&gt;(reg + 1);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    static RegisterID secondRealRegister()
-    {
-        return nextRegister(firstRealRegister());
-    }
-    
</del><span class="cx">     static FPRegisterID nextFPRegister(FPRegisterID reg)
</span><span class="cx">     {
</span><span class="cx">         return static_cast&lt;FPRegisterID&gt;(reg + 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLocation.cpp (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLocation.cpp        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/ftl/FTLLocation.cpp        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;FTLSaveRestore.h&quot;
</span><ins>+#include &quot;RegisterSet.h&quot;
</ins><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="lines">@@ -157,7 +158,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Location::restoreInto(MacroAssembler&amp; jit, char* savedRegisters, GPRReg result, unsigned numFramesToPop) const
</span><span class="cx"> {
</span><del>-    if (involvesGPR() &amp;&amp; MacroAssembler::isStackRelated(gpr())) {
</del><ins>+    if (involvesGPR() &amp;&amp; RegisterSet::stackRegisters().get(gpr())) {
</ins><span class="cx">         // Make the result GPR contain the appropriate stack register.
</span><span class="cx">         if (numFramesToPop) {
</span><span class="cx">             jit.move(MacroAssembler::framePointerRegister, result);
</span><span class="lines">@@ -174,7 +175,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (isGPR()) {
</span><del>-        if (MacroAssembler::isStackRelated(gpr())) {
</del><ins>+        if (RegisterSet::stackRegisters().get(gpr())) {
</ins><span class="cx">             // Already restored into result.
</span><span class="cx">         } else
</span><span class="cx">             jit.load64(savedRegisters + offsetOfGPR(gpr()), result);
</span><span class="lines">@@ -197,7 +198,7 @@
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     case Indirect:
</span><del>-        if (MacroAssembler::isStackRelated(gpr())) {
</del><ins>+        if (RegisterSet::stackRegisters().get(gpr())) {
</ins><span class="cx">             // The stack register is already recovered into result.
</span><span class="cx">             jit.load64(MacroAssembler::Address(result, offset()), result);
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSaveRestorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSaveRestore.cpp (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSaveRestore.cpp        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/ftl/FTLSaveRestore.cpp        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;FPRInfo.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><ins>+#include &quot;RegisterSet.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><span class="lines">@@ -69,38 +70,77 @@
</span><span class="cx">     return offsetOfFPR(reg.fpr());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+namespace {
+
+struct Regs {
+    Regs()
+    {
+        special = RegisterSet::stackRegisters();
+        special.merge(RegisterSet::reservedHardwareRegisters());
+        
+        first = MacroAssembler::firstRegister();
+        while (special.get(first))
+            first = MacroAssembler::nextRegister(first);
+        second = MacroAssembler::nextRegister(first);
+        while (special.get(second))
+            second = MacroAssembler::nextRegister(second);
+    }
+    
+    RegisterSet special;
+    GPRReg first;
+    GPRReg second;
+};
+
+} // anonymous namespace
+
</ins><span class="cx"> void saveAllRegisters(MacroAssembler&amp; jit, char* scratchMemory)
</span><span class="cx"> {
</span><ins>+    Regs regs;
+    
</ins><span class="cx">     // Get the first register out of the way, so that we can use it as a pointer.
</span><del>-    jit.poke64(MacroAssembler::firstRealRegister(), 0);
-    jit.move(MacroAssembler::TrustedImmPtr(scratchMemory), MacroAssembler::firstRealRegister());
</del><ins>+    jit.poke64(regs.first, 0);
+    jit.move(MacroAssembler::TrustedImmPtr(scratchMemory), regs.first);
</ins><span class="cx">     
</span><span class="cx">     // Get all of the other GPRs out of the way.
</span><del>-    for (MacroAssembler::RegisterID reg = MacroAssembler::secondRealRegister(); reg &lt;= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg))
-        jit.store64(reg, MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfGPR(reg)));
</del><ins>+    for (MacroAssembler::RegisterID reg = regs.second; reg &lt;= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
+        if (regs.special.get(reg))
+            continue;
+        jit.store64(reg, MacroAssembler::Address(regs.first, offsetOfGPR(reg)));
+    }
</ins><span class="cx">     
</span><span class="cx">     // Restore the first register into the second one and save it.
</span><del>-    jit.peek64(MacroAssembler::secondRealRegister(), 0);
-    jit.store64(MacroAssembler::secondRealRegister(), MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfGPR(MacroAssembler::firstRealRegister())));
</del><ins>+    jit.peek64(regs.second, 0);
+    jit.store64(regs.second, MacroAssembler::Address(regs.first, offsetOfGPR(regs.first)));
</ins><span class="cx">     
</span><span class="cx">     // Finally save all FPR's.
</span><del>-    for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg &lt;= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg))
-        jit.storeDouble(reg, MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfFPR(reg)));
</del><ins>+    for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg &lt;= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
+        if (regs.special.get(reg))
+            continue;
+        jit.storeDouble(reg, MacroAssembler::Address(regs.first, offsetOfFPR(reg)));
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void restoreAllRegisters(MacroAssembler&amp; jit, char* scratchMemory)
</span><span class="cx"> {
</span><ins>+    Regs regs;
+    
</ins><span class="cx">     // Give ourselves a pointer to the scratch memory.
</span><del>-    jit.move(MacroAssembler::TrustedImmPtr(scratchMemory), MacroAssembler::firstRealRegister());
</del><ins>+    jit.move(MacroAssembler::TrustedImmPtr(scratchMemory), regs.first);
</ins><span class="cx">     
</span><span class="cx">     // Restore all FPR's.
</span><del>-    for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg &lt;= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg))
-        jit.loadDouble(MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfFPR(reg)), reg);
</del><ins>+    for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg &lt;= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
+        if (regs.special.get(reg))
+            continue;
+        jit.loadDouble(MacroAssembler::Address(regs.first, offsetOfFPR(reg)), reg);
+    }
</ins><span class="cx">     
</span><del>-    for (MacroAssembler::RegisterID reg = MacroAssembler::secondRealRegister(); reg &lt;= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg))
-        jit.load64(MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfGPR(reg)), reg);
</del><ins>+    for (MacroAssembler::RegisterID reg = regs.second; reg &lt;= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
+        if (regs.special.get(reg))
+            continue;
+        jit.load64(MacroAssembler::Address(regs.first, offsetOfGPR(reg)), reg);
+    }
</ins><span class="cx">     
</span><del>-    jit.load64(MacroAssembler::Address(MacroAssembler::firstRealRegister(), offsetOfGPR(MacroAssembler::firstRealRegister())), MacroAssembler::firstRealRegister());
</del><ins>+    jit.load64(MacroAssembler::Address(regs.first, offsetOfGPR(regs.first)), regs.first);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLSlowPathCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -52,8 +52,9 @@
</span><span class="cx">         , m_numArgs(numArgs)
</span><span class="cx">         , m_returnRegister(returnRegister)
</span><span class="cx">     {
</span><del>-        // We don't care that you're using callee-save or stack registers.
</del><ins>+        // We don't care that you're using callee-save, stack, or hardware registers.
</ins><span class="cx">         m_usedRegisters.exclude(RegisterSet::stackRegisters());
</span><ins>+        m_usedRegisters.exclude(RegisterSet::reservedHardwareRegisters());
</ins><span class="cx">         m_usedRegisters.exclude(RegisterSet::calleeSaveRegisters());
</span><span class="cx">         
</span><span class="cx">         // The return register doesn't need to be saved.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.cpp (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -42,21 +42,34 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegisterSet RegisterSet::specialRegisters()
</del><ins>+RegisterSet RegisterSet::reservedHardwareRegisters()
</ins><span class="cx"> {
</span><span class="cx">     RegisterSet result;
</span><del>-    result.merge(stackRegisters());
-    result.set(GPRInfo::callFrameRegister);
</del><ins>+#if CPU(ARM64)
+    result.set(ARM64Registers::lr);
+#endif
+    return result;
+}
+
+RegisterSet RegisterSet::runtimeRegisters()
+{
+    RegisterSet result;
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     result.set(GPRInfo::tagTypeNumberRegister);
</span><span class="cx">     result.set(GPRInfo::tagMaskRegister);
</span><span class="cx"> #endif
</span><del>-#if CPU(ARM64)
-    result.set(ARM64Registers::lr);
-#endif
</del><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterSet RegisterSet::specialRegisters()
+{
+    RegisterSet result;
+    result.merge(stackRegisters());
+    result.merge(reservedHardwareRegisters());
+    result.merge(runtimeRegisters());
+    return result;
+}
+
</ins><span class="cx"> RegisterSet RegisterSet::calleeSaveRegisters()
</span><span class="cx"> {
</span><span class="cx">     RegisterSet result;
</span><span class="lines">@@ -69,7 +82,9 @@
</span><span class="cx">     result.set(X86Registers::r15);
</span><span class="cx"> #elif CPU(ARM64)
</span><span class="cx">     // We don't include LR in the set of callee-save registers even though it technically belongs
</span><del>-    // there. But, the way we use this list, it makes no sense to have it there.
</del><ins>+    // there. This is because we use this set to describe the set of registers that need to be saved
+    // beyond what you would save by the platform-agnostic &quot;preserve return address&quot; and &quot;restore
+    // return address&quot; operations in CCallHelpers.
</ins><span class="cx">     for (
</span><span class="cx">         ARM64Registers::RegisterID reg = ARM64Registers::x19;
</span><span class="cx">         reg &lt;= ARM64Registers::x28;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (165195 => 165196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2014-03-06 18:05:20 UTC (rev 165195)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2014-03-06 18:33:18 UTC (rev 165196)
</span><span class="lines">@@ -42,7 +42,9 @@
</span><span class="cx">     RegisterSet() { }
</span><span class="cx">     
</span><span class="cx">     static RegisterSet stackRegisters();
</span><del>-    static RegisterSet specialRegisters();
</del><ins>+    static RegisterSet reservedHardwareRegisters();
+    static RegisterSet runtimeRegisters();
+    static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
</ins><span class="cx">     static RegisterSet calleeSaveRegisters();
</span><span class="cx">     static RegisterSet allGPRs();
</span><span class="cx">     static RegisterSet allFPRs();
</span></span></pre>
</div>
</div>

</body>
</html>