<!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>[192187] 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/192187">192187</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-11-09 16:26:37 -0800 (Mon, 09 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>B3-&gt;Air lowering should support CCall
https://bugs.webkit.org/show_bug.cgi?id=151043

Reviewed by Geoffrey Garen.

Adds support for lowering CCall to Air, and adds a test that makes calls. I cannot test doubles
until https://bugs.webkit.org/show_bug.cgi?id=151002 lands, but this does test integer
arguments pretty thoroughly including a test for lots of arguments. That test ensures that the
arguments go to registers and the stack in the right order and such.

* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::createCompare):
(JSC::B3::Air::LowerToAir::marshallCCallArgument):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.h:
* b3/air/AirCCallSpecial.cpp:
(JSC::B3::Air::CCallSpecial::forEachArg):
(JSC::B3::Air::CCallSpecial::isValid):
(JSC::B3::Air::CCallSpecial::admitsStack):
(JSC::B3::Air::CCallSpecial::generate):
* b3/air/AirCCallSpecial.h:
* b3/testb3.cpp:
(JSC::B3::testCompare):
(JSC::B3::simpleFunction):
(JSC::B3::testCallSimple):
(JSC::B3::functionWithHellaArguments):
(JSC::B3::testCallFunctionWithHellaArguments):
(JSC::B3::run):
* jit/FPRInfo.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Opcodeh">trunk/Source/JavaScriptCore/b3/B3Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCCallSpecialcpp">trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCCallSpecialh">trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitFPRInfoh">trunk/Source/JavaScriptCore/jit/FPRInfo.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-11-09  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        B3-&gt;Air lowering should support CCall
+        https://bugs.webkit.org/show_bug.cgi?id=151043
+
+        Reviewed by Geoffrey Garen.
+
+        Adds support for lowering CCall to Air, and adds a test that makes calls. I cannot test doubles
+        until https://bugs.webkit.org/show_bug.cgi?id=151002 lands, but this does test integer
+        arguments pretty thoroughly including a test for lots of arguments. That test ensures that the
+        arguments go to registers and the stack in the right order and such.
+
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::createCompare):
+        (JSC::B3::Air::LowerToAir::marshallCCallArgument):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.h:
+        * b3/air/AirCCallSpecial.cpp:
+        (JSC::B3::Air::CCallSpecial::forEachArg):
+        (JSC::B3::Air::CCallSpecial::isValid):
+        (JSC::B3::Air::CCallSpecial::admitsStack):
+        (JSC::B3::Air::CCallSpecial::generate):
+        * b3/air/AirCCallSpecial.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testCompare):
+        (JSC::B3::simpleFunction):
+        (JSC::B3::testCallSimple):
+        (JSC::B3::functionWithHellaArguments):
+        (JSC::B3::testCallFunctionWithHellaArguments):
+        (JSC::B3::run):
+        * jit/FPRInfo.h:
+
</ins><span class="cx"> 2015-11-09  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: $0 stops working after navigating to a different domain
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -28,12 +28,14 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirCCallSpecial.h&quot;
</ins><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirInsertionSet.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;AirStackSlot.h&quot;
</span><span class="cx"> #include &quot;B3ArgumentRegValue.h&quot;
</span><span class="cx"> #include &quot;B3BasicBlockInlines.h&quot;
</span><ins>+#include &quot;B3CCallValue.h&quot;
</ins><span class="cx"> #include &quot;B3CheckSpecial.h&quot;
</span><span class="cx"> #include &quot;B3Commutativity.h&quot;
</span><span class="cx"> #include &quot;B3IndexMap.h&quot;
</span><span class="lines">@@ -1148,6 +1150,27 @@
</span><span class="cx">             inverted);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template&lt;typename BankInfo&gt;
+    Arg marshallCCallArgument(unsigned&amp; argumentCount, unsigned&amp; stackCount, Value* child)
+    {
+        unsigned argumentIndex = argumentCount++;
+        if (argumentIndex &lt; BankInfo::numberOfArgumentRegisters) {
+            Tmp result = Tmp(BankInfo::toArgumentRegister(argumentIndex));
+            append(relaxedMoveForType(child-&gt;type()), immOrTmp(child), result);
+            return result;
+        }
+
+        // Compute the place that this goes onto the stack. On X86_64 and probably other calling
+        // conventions that don't involve obsolete computers and operating systems, sub-pointer-size
+        // arguments are still given a full pointer-sized stack slot. Hence we don't have to consider
+        // the type of the argument when deducing the stack index.
+        unsigned stackIndex = stackCount++;
+
+        Arg result = Arg::callArg(stackIndex * sizeof(void*));
+        appendStore(child, result);
+        return result;
+    }
+
</ins><span class="cx">     void lower()
</span><span class="cx">     {
</span><span class="cx">         switch (m_value-&gt;opcode()) {
</span><span class="lines">@@ -1336,6 +1359,70 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case CCall: {
+            CCallValue* cCall = m_value-&gt;as&lt;CCallValue&gt;();
+            Inst inst(Patch, cCall, Arg::special(m_code.cCallSpecial()));
+
+            // This is a bit weird - we have a super intense contract with Arg::CCallSpecial. It might
+            // be better if we factored Air::CCallSpecial out of the Air namespace and made it a B3
+            // thing.
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151045
+
+            // We have a ton of flexibility regarding the callee argument, but currently, we don't
+            // use it yet. It gets weird for reasons:
+            // 1) We probably will never take advantage of this. We don't have C calls to locations
+            //    loaded from addresses. We have JS calls like that, but those use Patchpoints.
+            // 2) On X86_64 we still don't support call with BaseIndex.
+            // 3) On non-X86, we don't natively support any kind of loading from address.
+            // 4) We don't have an isValidForm() for the CCallSpecial so we have no smart way to
+            //    decide.
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151052
+            inst.args.append(tmp(cCall-&gt;child(0)));
+
+            // We need to tell Air what registers this defines.
+            inst.args.append(Tmp(GPRInfo::returnValueGPR));
+            inst.args.append(Tmp(GPRInfo::returnValueGPR2));
+            inst.args.append(Tmp(FPRInfo::returnValueFPR));
+
+            // Now marshall the arguments. This is where we implement the C calling convention. After
+            // this, Air does not know what the convention is; it just takes our word for it.
+            unsigned gpArgumentCount = 0;
+            unsigned fpArgumentCount = 0;
+            unsigned stackCount = 0;
+            for (unsigned i = 1; i &lt; cCall-&gt;numChildren(); ++i) {
+                Value* argChild = cCall-&gt;child(i);
+                Arg arg;
+                
+                switch (Arg::typeForB3Type(argChild-&gt;type())) {
+                case Arg::GP:
+                    arg = marshallCCallArgument&lt;GPRInfo&gt;(gpArgumentCount, stackCount, argChild);
+                    break;
+
+                case Arg::FP:
+                    arg = marshallCCallArgument&lt;FPRInfo&gt;(fpArgumentCount, stackCount, argChild);
+                    break;
+                }
+
+                if (arg.isTmp())
+                    inst.args.append(arg);
+            }
+            
+            m_insts.last().append(WTF::move(inst));
+
+            switch (cCall-&gt;type()) {
+            case Void:
+                break;
+            case Int32:
+            case Int64:
+                append(Move, Tmp(GPRInfo::returnValueGPR), tmp(cCall));
+                break;
+            case Double:
+                append(MoveDouble, Tmp(FPRInfo::returnValueFPR), tmp(cCall));
+                break;
+            }
+            return;
+        }
+
</ins><span class="cx">         case Patchpoint: {
</span><span class="cx">             PatchpointValue* patchpointValue = m_value-&gt;as&lt;PatchpointValue&gt;();
</span><span class="cx">             ensureSpecial(m_patchpointSpecial);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.h (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -133,7 +133,7 @@
</span><span class="cx">     Store,
</span><span class="cx"> 
</span><span class="cx">     // This is a regular ordinary C function call, using the system C calling convention. Make sure
</span><del>-    // that the arguments are passed using the right types.
</del><ins>+    // that the arguments are passed using the right types. The first argument is the callee.
</ins><span class="cx">     CCall,
</span><span class="cx"> 
</span><span class="cx">     // This is a patchpoint. Use the PatchpointValue class. This is viewed as behaving like a call,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCCallSpecialcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -44,9 +44,14 @@
</span><span class="cx"> 
</span><span class="cx"> void CCallSpecial::forEachArg(Inst&amp; inst, const ScopedLambda&lt;Inst::EachArgCallback&gt;&amp; callback)
</span><span class="cx"> {
</span><del>-    callback(inst.args[1], Arg::Use, Arg::GP);
</del><ins>+    for (unsigned i = 0; i &lt; numCalleeArgs; ++i)
+        callback(inst.args[calleeArgOffset + i], Arg::Use, Arg::GP);
+    for (unsigned i = 0; i &lt; numReturnGPArgs; ++i)
+        callback(inst.args[returnGPArgOffset + i], Arg::Def, Arg::GP);
+    for (unsigned i = 0; i &lt; numReturnFPArgs; ++i)
+        callback(inst.args[returnFPArgOffset + i], Arg::Def, Arg::FP);
</ins><span class="cx">     
</span><del>-    for (unsigned i = 2; i &lt; inst.args.size(); ++i) {
</del><ins>+    for (unsigned i = argArgOffset; i &lt; inst.args.size(); ++i) {
</ins><span class="cx">         // For the type, we can just query the arg's type. The arg will have a type, because we
</span><span class="cx">         // require these args to be argument registers.
</span><span class="cx">         callback(inst.args[i], Arg::Use, inst.args[i].type());
</span><span class="lines">@@ -55,31 +60,41 @@
</span><span class="cx"> 
</span><span class="cx"> bool CCallSpecial::isValid(Inst&amp; inst)
</span><span class="cx"> {
</span><del>-    if (inst.args.size() &lt; 2)
</del><ins>+    if (inst.args.size() &lt; argArgOffset)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    switch (inst.args[1].kind()) {
-    case Arg::Imm:
-        if (is32Bit())
</del><ins>+    for (unsigned i = 0; i &lt; numCalleeArgs; ++i) {
+        Arg&amp; arg = inst.args[i + calleeArgOffset];
+        if (!arg.isGP())
+            return false;
+        switch (arg.kind()) {
+        case Arg::Imm:
+            if (is32Bit())
+                break;
+            return false;
+        case Arg::Imm64:
+            if (is64Bit())
+                break;
+            return false;
+        case Arg::Tmp:
+        case Arg::Addr:
+        case Arg::Stack:
+        case Arg::CallArg:
</ins><span class="cx">             break;
</span><ins>+        default:
+            return false;
+        }
+    }
+
+    // Return args need to be exact.
+    if (inst.args[returnGPArgOffset + 0] != Tmp(GPRInfo::returnValueGPR))
</ins><span class="cx">         return false;
</span><del>-    case Arg::Imm64:
-        if (is64Bit())
-            break;
</del><ins>+    if (inst.args[returnGPArgOffset + 1] != Tmp(GPRInfo::returnValueGPR2))
</ins><span class="cx">         return false;
</span><del>-    case Arg::Tmp:
-    case Arg::Addr:
-    case Arg::Stack:
-    case Arg::CallArg:
-        break;
-    default:
</del><ins>+    if (inst.args[returnFPArgOffset + 0] != Tmp(FPRInfo::returnValueFPR))
</ins><span class="cx">         return false;
</span><del>-    }
</del><span class="cx"> 
</span><del>-    if (!inst.args[1].isGP())
-        return false;
-
-    for (unsigned i = 2; i &lt; inst.args.size(); ++i) {
</del><ins>+    for (unsigned i = argArgOffset; i &lt; inst.args.size(); ++i) {
</ins><span class="cx">         if (!inst.args[i].isReg())
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -91,8 +106,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool CCallSpecial::admitsStack(Inst&amp;, unsigned argIndex)
</span><span class="cx"> {
</span><del>-    // Arg 1 can be a stack address for sure.
-    if (argIndex == 1)
</del><ins>+    // The callee can be on the stack.
+    if (argIndex == calleeArgOffset)
</ins><span class="cx">         return true;
</span><span class="cx">     
</span><span class="cx">     return false;
</span><span class="lines">@@ -104,17 +119,17 @@
</span><span class="cx"> 
</span><span class="cx"> CCallHelpers::Jump CCallSpecial::generate(Inst&amp; inst, CCallHelpers&amp; jit, GenerationContext&amp;)
</span><span class="cx"> {
</span><del>-    switch (inst.args[1].kind()) {
</del><ins>+    switch (inst.args[calleeArgOffset].kind()) {
</ins><span class="cx">     case Arg::Imm:
</span><span class="cx">     case Arg::Imm64:
</span><del>-        jit.move(inst.args[1].asTrustedImmPtr(), scratchRegister);
</del><ins>+        jit.move(inst.args[calleeArgOffset].asTrustedImmPtr(), scratchRegister);
</ins><span class="cx">         jit.call(scratchRegister);
</span><span class="cx">         break;
</span><span class="cx">     case Arg::Tmp:
</span><del>-        jit.call(inst.args[1].gpr());
</del><ins>+        jit.call(inst.args[calleeArgOffset].gpr());
</ins><span class="cx">         break;
</span><span class="cx">     case Arg::Addr:
</span><del>-        jit.call(inst.args[1].asAddress());
</del><ins>+        jit.call(inst.args[calleeArgOffset].asAddress());
</ins><span class="cx">         break;
</span><span class="cx">     default:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCCallSpecialh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.h (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.h        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/b3/air/AirCCallSpecial.h        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -34,12 +34,13 @@
</span><span class="cx"> 
</span><span class="cx"> // Use this special for constructing a C call. Arg 0 is of course a Special arg that refers to the
</span><span class="cx"> // CCallSpecial object. Arg 1 is the callee, and it can be an ImmPtr, a register, or an address. The
</span><del>-// remaining args are just the set of argument registers used by this call. For arguments that go to
-// the stack, you have to do the grunt work of doing those stack stores. In fact, the only reason why
-// we specify the argument registers as arguments to a call is so that the liveness analysis can see
-// that they get used here. It would be wrong to automagically report all argument registers as being
-// used because if we had a call that didn't pass them, then they'd appear to be live until some
-// clobber point or the prologue, whichever happened sooner.
</del><ins>+// next three args - arg 2, arg 3, and arg 4 - hold the return value GPRs and FPR. The remaining args
+// are just the set of argument registers used by this call. For arguments that go to the stack, you
+// have to do the grunt work of doing those stack stores. In fact, the only reason why we specify the
+// argument registers as arguments to a call is so that the liveness analysis can see that they get
+// used here. It would be wrong to automagically report all argument registers as being used because
+// if we had a call that didn't pass them, then they'd appear to be live until some clobber point or
+// the prologue, whichever happened sooner.
</ins><span class="cx"> 
</span><span class="cx"> class CCallSpecial : public Special {
</span><span class="cx"> public:
</span><span class="lines">@@ -63,6 +64,17 @@
</span><span class="cx">     void deepDumpImpl(PrintStream&amp;) const override;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    static const unsigned specialArgOffset = 0;
+    static const unsigned numSpecialArgs = 1;
+    static const unsigned calleeArgOffset = numSpecialArgs;
+    static const unsigned numCalleeArgs = 1;
+    static const unsigned returnGPArgOffset = numSpecialArgs + numCalleeArgs;
+    static const unsigned numReturnGPArgs = 2;
+    static const unsigned returnFPArgOffset = numSpecialArgs + numCalleeArgs + numReturnGPArgs;
+    static const unsigned numReturnFPArgs = 1;
+    static const unsigned argArgOffset =
+        numSpecialArgs + numCalleeArgs + numReturnGPArgs + numReturnFPArgs;
+    
</ins><span class="cx">     RegisterSet m_clobberedRegs;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3ArgumentRegValue.h&quot;
</span><span class="cx"> #include &quot;B3BasicBlockInlines.h&quot;
</span><ins>+#include &quot;B3CCallValue.h&quot;
</ins><span class="cx"> #include &quot;B3Compilation.h&quot;
</span><span class="cx"> #include &quot;B3Const32Value.h&quot;
</span><span class="cx"> #include &quot;B3ConstPtrValue.h&quot;
</span><span class="lines">@@ -2647,6 +2648,50 @@
</span><span class="cx">     variants(-left, -right);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+int simpleFunction(int a, int b)
+{
+    return a + b;
+}
+
+void testCallSimple(int a, int b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;CCallValue&gt;(
+            proc, Int32, Origin(),
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), bitwise_cast&lt;void*&gt;(simpleFunction)),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1)));
+
+    CHECK(compileAndRun&lt;int&gt;(proc, a, b) == a + b);
+}
+
+int functionWithHellaArguments(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, int z)
+{
+    return (a &lt;&lt; 0) + (b &lt;&lt; 1) + (c &lt;&lt; 2) + (d &lt;&lt; 3) + (e &lt;&lt; 4) + (f &lt;&lt; 5) + (g &lt;&lt; 6) + (h &lt;&lt; 7) + (i &lt;&lt; 8) + (j &lt;&lt; 9) + (k &lt;&lt; 10) + (l &lt;&lt; 11) + (m &lt;&lt; 12) + (n &lt;&lt; 13) + (o &lt;&lt; 14) + (p &lt;&lt; 15) + (q &lt;&lt; 16) + (r &lt;&lt; 17) + (s &lt;&lt; 18) + (t &lt;&lt; 19) + (u &lt;&lt; 20) + (v &lt;&lt; 21) + (w &lt;&lt; 22) + (x &lt;&lt; 23) + (y &lt;&lt; 24) + (z &lt;&lt; 25);
+}
+
+void testCallFunctionWithHellaArguments()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Vector&lt;Value*&gt; args;
+    for (unsigned i = 0; i &lt; 26; ++i)
+        args.append(root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), i + 1));
+
+    CCallValue* call = root-&gt;appendNew&lt;CCallValue&gt;(
+        proc, Int32, Origin(),
+        root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), bitwise_cast&lt;void*&gt;(functionWithHellaArguments)));
+    call-&gt;children().appendVector(args);
+    
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), call);
+
+    CHECK(compileAndRun&lt;int&gt;(proc) == functionWithHellaArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
+}
+
</ins><span class="cx"> void testReturnDouble(double value)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -3122,6 +3167,9 @@
</span><span class="cx">     RUN(testLoad&lt;uint16_t&gt;(Load16Z, 1000000000));
</span><span class="cx">     RUN(testLoad&lt;uint16_t&gt;(Load16Z, -1000000000));
</span><span class="cx"> 
</span><ins>+    RUN(testCallSimple(1, 2));
+    RUN(testCallFunctionWithHellaArguments());
+
</ins><span class="cx">     RUN(testReturnDouble(0.0));
</span><span class="cx">     RUN(testReturnDouble(-0.0));
</span><span class="cx">     RUN(testReturnDouble(42.5));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitFPRInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/FPRInfo.h (192186 => 192187)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/FPRInfo.h        2015-11-10 00:19:26 UTC (rev 192186)
+++ trunk/Source/JavaScriptCore/jit/FPRInfo.h        2015-11-10 00:26:37 UTC (rev 192187)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef FPRReg RegisterType;
</span><span class="cx">     static const unsigned numberOfRegisters = 6;
</span><ins>+    static const unsigned numberOfArgumentRegisters = 8;
</ins><span class="cx"> 
</span><span class="cx">     // Temporary registers.
</span><span class="cx">     static const FPRReg fpRegT0 = X86Registers::xmm0;
</span><span class="lines">@@ -56,6 +57,10 @@
</span><span class="cx">     static const FPRReg argumentFPR1 = X86Registers::xmm1; // fpRegT1
</span><span class="cx">     static const FPRReg argumentFPR2 = X86Registers::xmm2; // fpRegT2
</span><span class="cx">     static const FPRReg argumentFPR3 = X86Registers::xmm3; // fpRegT3
</span><ins>+    static const FPRReg argumentFPR4 = X86Registers::xmm4; // fpRegT4
+    static const FPRReg argumentFPR5 = X86Registers::xmm5; // fpRegT5
+    static const FPRReg argumentFPR6 = X86Registers::xmm6;
+    static const FPRReg argumentFPR7 = X86Registers::xmm7;
</ins><span class="cx"> #endif
</span><span class="cx">     // On X86 the return will actually be on the x87 stack,
</span><span class="cx">     // so we'll copy to xmm0 for sanity!
</span></span></pre>
</div>
</div>

</body>
</html>