<!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>[201668] 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/201668">201668</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-06-03 16:06:39 -0700 (Fri, 03 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add argument_count bytecode for concat
https://bugs.webkit.org/show_bug.cgi?id=158358

Reviewed by Geoffrey Garen.

This patch adds a new argument count bytecode. Normally, we would
just make sure that the argument.length bytecode was fast enough
that we shouldn't need such an bytecode.  However, for the case of
Array.prototype.concat the overhead of the arguments object
allocation in the LLInt was too high and caused regressions.

* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_argumentCount):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getArgumentCount):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_argument_count):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* tests/stress/argument-count-bytecode.js: Added.
(inlineCount):
(inlineCount1):
(inlineCount2):
(inlineCountVarArgs):
(assert):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeIntrinsicRegistryh">trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsUtilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsUtilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMayExitcpp">trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressargumentcountbytecodejs">trunk/Source/JavaScriptCore/tests/stress/argument-count-bytecode.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -1,3 +1,44 @@
</span><ins>+2016-06-03  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add argument_count bytecode for concat
+        https://bugs.webkit.org/show_bug.cgi?id=158358
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds a new argument count bytecode. Normally, we would
+        just make sure that the argument.length bytecode was fast enough
+        that we shouldn't need such an bytecode.  However, for the case of
+        Array.prototype.concat the overhead of the arguments object
+        allocation in the LLInt was too high and caused regressions.
+
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_argumentCount):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getArgumentCount):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_argument_count):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * tests/stress/argument-count-bytecode.js: Added.
+        (inlineCount):
+        (inlineCount1):
+        (inlineCount2):
+        (inlineCountVarArgs):
+        (assert):
+
</ins><span class="cx"> 2016-06-03  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clients of PolymorphicAccess::addCases shouldn't have to malloc
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeIntrinsicRegistryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> class Identifier;
</span><span class="cx"> 
</span><span class="cx"> #define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
</span><ins>+    macro(argumentCount) \
</ins><span class="cx">     macro(assert) \
</span><span class="cx">     macro(isObject) \
</span><span class="cx">     macro(tryGetById) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -9,6 +9,7 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_scoped_arguments&quot;, &quot;length&quot; : 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_cloned_arguments&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_this&quot;, &quot;length&quot; : 5 },
</span><ins>+            { &quot;name&quot; : &quot;op_argument_count&quot;, &quot;length&quot; : 2 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_to_this&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_check_tdz&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_new_object&quot;, &quot;length&quot; : 4 },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     case op_jmp:
</span><span class="cx">     case op_new_object:
</span><span class="cx">     case op_enter:
</span><ins>+    case op_argument_count:
</ins><span class="cx">     case op_catch:
</span><span class="cx">     case op_profile_control_flow:
</span><span class="cx">     case op_create_direct_arguments:
</span><span class="lines">@@ -362,6 +363,7 @@
</span><span class="cx"> #undef LLINT_HELPER_OPCODES
</span><span class="cx">         return;
</span><span class="cx">     // These all have a single destination for the first argument.
</span><ins>+    case op_argument_count:
</ins><span class="cx">     case op_to_index_string:
</span><span class="cx">     case op_get_enumerable_length:
</span><span class="cx">     case op_has_indexed_property:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -818,6 +818,11 @@
</span><span class="cx">             out.printf(&quot;%s&quot;, registerName(r0).data());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        case op_argument_count: {
+            int r0 = (++it)-&gt;u.operand;
+            printLocationOpAndRegisterOperand(out, exec, location, it, &quot;argument_count&quot;, r0);
+            break;
+        }
</ins><span class="cx">         case op_copy_rest: {
</span><span class="cx">             int r0 = (++it)-&gt;u.operand;
</span><span class="cx">             int r1 = (++it)-&gt;u.operand;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -854,6 +854,13 @@
</span><span class="cx">     return (this-&gt;*m_emitter)(generator, dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    ASSERT(!m_args-&gt;m_listNode);
+
+    return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
+}
+
</ins><span class="cx"> RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx"> #ifndef NDEBUG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -1973,7 +1973,7 @@
</span><span class="cx">         forNode(node).setType(m_graph, SpecFunction);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">         forNode(node).setType(SpecInt32Only);
</span><span class="cx">         break;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsUtilities.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsUtilities.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsUtilities.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx">     
</span><span class="cx">     Node* argumentCount;
</span><span class="cx">     if (!inlineCallFrame)
</span><del>-        argumentCount = insertionSet.insertNode(nodeIndex, SpecInt32Only, GetArgumentCount, origin);
</del><ins>+        argumentCount = insertionSet.insertNode(nodeIndex, SpecInt32Only, GetArgumentCountIncludingThis, origin);
</ins><span class="cx">     else {
</span><span class="cx">         VirtualRegister argumentCountRegister(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount);
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -196,6 +196,7 @@
</span><span class="cx">     Terminality handleVarargsCall(Instruction* pc, NodeType op, CallMode);
</span><span class="cx">     void emitFunctionChecks(CallVariant, Node* callTarget, VirtualRegister thisArgumnt);
</span><span class="cx">     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis);
</span><ins>+    Node* getArgumentCount();
</ins><span class="cx">     unsigned inliningCost(CallVariant, int argumentCountIncludingThis, CallMode); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
</span><span class="cx">     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
</span><span class="cx">     bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp;, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
</span><span class="lines">@@ -1322,6 +1323,19 @@
</span><span class="cx">     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck, thisArgument);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Node* ByteCodeParser::getArgumentCount()
+{
+    Node* argumentCount;
+    if (m_inlineStackTop-&gt;m_inlineCallFrame) {
+        if (m_inlineStackTop-&gt;m_inlineCallFrame-&gt;isVarargs())
+            argumentCount = get(VirtualRegister(JSStack::ArgumentCount));
+        else
+            argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop-&gt;m_inlineCallFrame-&gt;arguments.size()))-&gt;value());
+    } else
+        argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(0), OpInfo(SpecInt32Only));
+    return argumentCount;
+}
+
</ins><span class="cx"> void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
</span><span class="cx"> {
</span><span class="cx">     for (int i = 0; i &lt; argumentCountIncludingThis; ++i)
</span><span class="lines">@@ -4886,7 +4900,14 @@
</span><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), result);
</span><span class="cx">             NEXT_OPCODE(op_get_scope);
</span><span class="cx">         }
</span><del>-            
</del><ins>+
+        case op_argument_count: {
+            Node* sub = addToGraph(ArithSub, OpInfo(Arith::Unchecked), OpInfo(SpecInt32Only), getArgumentCount(), addToGraph(JSConstant, OpInfo(m_constantOne)));
+
+            set(VirtualRegister(currentInstruction[1].u.operand), sub);
+            NEXT_OPCODE(op_argument_count);
+        }
+
</ins><span class="cx">         case op_create_direct_arguments: {
</span><span class="cx">             noticeArgumentsUse();
</span><span class="cx">             Node* createArguments = addToGraph(CreateDirectArguments);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -106,6 +106,7 @@
</span><span class="cx">     switch (opcodeID) {
</span><span class="cx">     case op_enter:
</span><span class="cx">     case op_to_this:
</span><ins>+    case op_argument_count:
</ins><span class="cx">     case op_check_tdz:
</span><span class="cx">     case op_create_this:
</span><span class="cx">     case op_bitand:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -502,7 +502,7 @@
</span><span class="cx">         def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), LazyNode(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">         read(AbstractHeap(Stack, JSStack::ArgumentCount));
</span><span class="cx">         def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node));
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx">     case LazyJSConstant:
</span><span class="cx">     case Identity:
</span><span class="cx">     case GetCallee:
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -1508,7 +1508,7 @@
</span><span class="cx">         case DoubleConstant:
</span><span class="cx">         case GetLocal:
</span><span class="cx">         case GetCallee:
</span><del>-        case GetArgumentCount:
</del><ins>+        case GetArgumentCountIncludingThis:
</ins><span class="cx">         case GetRestLength:
</span><span class="cx">         case Flush:
</span><span class="cx">         case PhantomLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     case KillStack:
</span><span class="cx">     case GetStack:
</span><span class="cx">     case GetCallee:
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case GetScope:
</span><span class="cx">     case PhantomLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">     macro(ToThis, NodeResultJS) \
</span><span class="cx">     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
</span><span class="cx">     macro(GetCallee, NodeResultJS) \
</span><del>-    macro(GetArgumentCount, NodeResultInt32) \
</del><ins>+    macro(GetArgumentCountIncludingThis, NodeResultInt32) \
</ins><span class="cx">     \
</span><span class="cx">     /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
</span><span class="cx">     /* Any two nodes that are part of the same Phi graph will share the same */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -737,7 +737,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case GetArgumentCount: {
</del><ins>+        case GetArgumentCountIncludingThis: {
</ins><span class="cx">             setPrediction(SpecInt32Only);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -142,7 +142,7 @@
</span><span class="cx">     case ToThis:
</span><span class="cx">     case CreateThis:
</span><span class="cx">     case GetCallee:
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -4070,7 +4070,7 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case GetArgumentCount: {
</del><ins>+    case GetArgumentCountIncludingThis: {
</ins><span class="cx">         GPRTemporary result(this);
</span><span class="cx">         m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr());
</span><span class="cx">         int32Result(result.gpr(), node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -4007,7 +4007,7 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case GetArgumentCount: {
</del><ins>+    case GetArgumentCountIncludingThis: {
</ins><span class="cx">         GPRTemporary result(this);
</span><span class="cx">         m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr());
</span><span class="cx">         int32Result(result.gpr(), node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -160,7 +160,7 @@
</span><span class="cx">     case GetExecutable:
</span><span class="cx">     case GetScope:
</span><span class="cx">     case GetCallee:
</span><del>-    case GetArgumentCount:
</del><ins>+    case GetArgumentCountIncludingThis:
</ins><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor:
</span><span class="cx">     case MakeRope:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -776,8 +776,8 @@
</span><span class="cx">         case GetCallee:
</span><span class="cx">             compileGetCallee();
</span><span class="cx">             break;
</span><del>-        case GetArgumentCount:
-            compileGetArgumentCount();
</del><ins>+        case GetArgumentCountIncludingThis:
+            compileGetArgumentCountIncludingThis();
</ins><span class="cx">             break;
</span><span class="cx">         case GetScope:
</span><span class="cx">             compileGetScope();
</span><span class="lines">@@ -4670,7 +4670,7 @@
</span><span class="cx">         setJSValue(m_out.loadPtr(addressFor(JSStack::Callee)));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void compileGetArgumentCount()
</del><ins>+    void compileGetArgumentCountIncludingThis()
</ins><span class="cx">     {
</span><span class="cx">         setInt32(m_out.load32(payloadFor(JSStack::ArgumentCount)));
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -223,6 +223,7 @@
</span><span class="cx">         DEFINE_OP(op_create_direct_arguments)
</span><span class="cx">         DEFINE_OP(op_create_scoped_arguments)
</span><span class="cx">         DEFINE_OP(op_create_cloned_arguments)
</span><ins>+        DEFINE_OP(op_argument_count)
</ins><span class="cx">         DEFINE_OP(op_copy_rest)
</span><span class="cx">         DEFINE_OP(op_get_rest_length)
</span><span class="cx">         DEFINE_OP(op_check_tdz)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -491,6 +491,7 @@
</span><span class="cx">         void emit_op_create_direct_arguments(Instruction*);
</span><span class="cx">         void emit_op_create_scoped_arguments(Instruction*);
</span><span class="cx">         void emit_op_create_cloned_arguments(Instruction*);
</span><ins>+        void emit_op_argument_count(Instruction*);
</ins><span class="cx">         void emit_op_copy_rest(Instruction*);
</span><span class="cx">         void emit_op_get_rest_length(Instruction*);
</span><span class="cx">         void emit_op_check_tdz(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -1419,6 +1419,16 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_argument_count(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    load32(payloadFor(JSStack::ArgumentCount), regT0);
+    sub32(TrustedImm32(1), regT0);
+    JSValueRegs result = JSValueRegs::withTwoAvailableRegs(regT0, regT1);
+    boxInt32(regT0, result);
+    emitPutVirtualRegister(dst, result);
+}
+
</ins><span class="cx"> void JIT::emit_op_copy_rest(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -677,6 +677,17 @@
</span><span class="cx">     dispatch(1)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+_llint_op_argument_count:
+    traceExecution()
+    loadisFromInstruction(1, t2)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    subi 1, t0
+    move Int32Tag, t1
+    storei t1, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(2)
+
+
</ins><span class="cx"> _llint_op_get_scope:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadi Callee + PayloadOffset[cfr], t0
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (201667 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -584,6 +584,16 @@
</span><span class="cx">     dispatch(1)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+_llint_op_argument_count:
+    traceExecution()
+    loadisFromInstruction(1, t1)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    subi 1, t0
+    orq TagTypeNumber, t0
+    storeq t0, [cfr, t1, 8]
+    dispatch(2)
+
+
</ins><span class="cx"> _llint_op_get_scope:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadp Callee[cfr], t0
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressargumentcountbytecodejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/argument-count-bytecode.js (0 => 201668)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/argument-count-bytecode.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/argument-count-bytecode.js        2016-06-03 23:06:39 UTC (rev 201668)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+count = createBuiltin(&quot;(function () { return @argumentCount(); })&quot;);
+countNoInline = createBuiltin(&quot;(function () { return @argumentCount(); })&quot;);
+noInline(countNoInline);
+
+
+function inlineCount() { return count(); }
+noInline(inlineCount);
+
+function inlineCount1() { return count(1); }
+noInline(inlineCount1);
+
+function inlineCount2() { return count(1,2); }
+noInline(inlineCount2);
+
+function inlineCountVarArgs(list) { return count(...list); }
+noInline(inlineCountVarArgs);
+
+function assert(condition, message) {
+    if (!condition)
+        throw new Error(message);
+}
+
+for (i = 0; i &lt; 1000000; i++) {
+    assert(count(1,1,2) === 3, i);
+    assert(count() === 0, i);
+    assert(count(1) === 1, i);
+    assert(count(...[1,2,3,4,5]) === 5, i);
+    assert(count(...[]) === 0, i);
+    assert(inlineCount() === 0, i);
+    assert(inlineCount1() === 1, i);
+    assert(inlineCount2() === 2, i);
+    assert(inlineCountVarArgs([1,2,3,4]) === 4, i);
+    assert(inlineCountVarArgs([]) === 0, i);
+    // Insert extra junk so that inlineCountVarArgs.arguments.length !== count.arguments.length
+    assert(inlineCountVarArgs([1], 2, 4) === 1, i);
+    assert(countNoInline(4) === 1, i)
+    assert(countNoInline() === 0, i);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>