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

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

<h3>Log Message</h3>
<pre>[JSC] Default parameter part should be retrieved by op_get_argument opcode instead of changing arity
https://bugs.webkit.org/show_bug.cgi?id=164582

Reviewed by Saam Barati.

JSTests:

* stress/function-with-defaults-inlining.js: Added.
(shouldBe):
(ok):
(a):
* stress/function-with-defaults-non-inlining.js: Added.
(shouldBe):
(ok):
(a):

Source/JavaScriptCore:

Previously we implement the default parameters as follows.

    1. We count the default parameters as the usual parameters.
    2. We just get the argument register.
    3. Check it with op_is_undefined.
    4. And fill the binding with either the argument register or default value.

The above is simple. However, it has the side effect that it always increase the arity of the function.
While `function.length` does not increase, internally, the number of parameters of CodeBlock increases.
This effectively prevent our DFG / FTL to perform inlining: currently we only allows DFG to inline
the function with the arity less than or equal the number of passing arguments. It is OK. But when using
default parameters, we frequently do not pass the argument for the parameter with the default value.
Thus, in our current implementation, we frequently need to fixup the arity. And we frequently fail
to inline the function.

This patch fixes the above problem by not increasing the arity of the function. When we encounter the
parameter with the default value, we use `op_argument` to get the argument instead of using the argument
registers.

This improves six-speed defaults.es6 performance by 4.45x.

    defaults.es6        968.4126+-101.2350   ^    217.6602+-14.8831       ^ definitely 4.4492x faster

* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::initializeNextParameter):
(JSC::BytecodeGenerator::initializeParameters):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::inliningCost):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionMetadata):
* parser/Nodes.cpp:
(JSC::FunctionMetadataNode::FunctionMetadataNode):
* parser/Nodes.h:
(JSC::FunctionParameters::size):
(JSC::FunctionParameters::at):
(JSC::FunctionParameters::append):
(JSC::FunctionParameters::isSimpleParameterList):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::isArrowFunctionParameters):
(JSC::Parser&lt;LexerType&gt;::parseGeneratorFunctionSourceElements):
(JSC::Parser&lt;LexerType&gt;::parseAsyncFunctionSourceElements):
(JSC::Parser&lt;LexerType&gt;::parseFormalParameters):
(JSC::Parser&lt;LexerType&gt;::parseFunctionBody):
(JSC::Parser&lt;LexerType&gt;::parseFunctionParameters):
(JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
* parser/Parser.h:
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createFunctionMetadata):
* runtime/FunctionExecutable.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::createBuiltinFunction):
(JSC::JSFunction::reifyLength):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutablecpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutableh">trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodescpp">trunk/Source/JavaScriptCore/parser/Nodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeFunctionExecutableh">trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressfunctionwithdefaultsinliningjs">trunk/JSTests/stress/function-with-defaults-inlining.js</a></li>
<li><a href="#trunkJSTestsstressfunctionwithdefaultsnoninliningjs">trunk/JSTests/stress/function-with-defaults-non-inlining.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/JSTests/ChangeLog        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -1,5 +1,21 @@
</span><span class="cx"> 2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><ins>+        [JSC] Default parameter part should be retrieved by op_get_argument opcode instead of changing arity
+        https://bugs.webkit.org/show_bug.cgi?id=164582
+
+        Reviewed by Saam Barati.
+
+        * stress/function-with-defaults-inlining.js: Added.
+        (shouldBe):
+        (ok):
+        (a):
+        * stress/function-with-defaults-non-inlining.js: Added.
+        (shouldBe):
+        (ok):
+        (a):
+
+2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
</ins><span class="cx">         [DFG] ToString operation should have fixup for primitives to say this node does not have side effects
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=169544
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsstressfunctionwithdefaultsinliningjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/function-with-defaults-inlining.js (0 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/function-with-defaults-inlining.js                                (rev 0)
+++ trunk/JSTests/stress/function-with-defaults-inlining.js        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+(function () {
+'use strict';
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function ok(value)
+{
+    return value;
+}
+
+function a(b = 42, c = 43, d)
+{
+    return c + ok(b);
+}
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    shouldBe(a(), 85);
+    shouldBe(a(33), 76);
+    shouldBe(a(33, 22), 55);
+}
+}());
</ins></span></pre></div>
<a id="trunkJSTestsstressfunctionwithdefaultsnoninliningjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/function-with-defaults-non-inlining.js (0 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/function-with-defaults-non-inlining.js                                (rev 0)
+++ trunk/JSTests/stress/function-with-defaults-non-inlining.js        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+(function () {
+'use strict';
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function ok(value)
+{
+    return value;
+}
+
+function a(b = 42, c = 43, d)
+{
+    return c + ok(b);
+}
+noInline(a);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    shouldBe(a(), 85);
+    shouldBe(a(33), 76);
+    shouldBe(a(33, 22), 55);
+}
+}());
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -1,5 +1,73 @@
</span><span class="cx"> 2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><ins>+        [JSC] Default parameter part should be retrieved by op_get_argument opcode instead of changing arity
+        https://bugs.webkit.org/show_bug.cgi?id=164582
+
+        Reviewed by Saam Barati.
+
+        Previously we implement the default parameters as follows.
+
+            1. We count the default parameters as the usual parameters.
+            2. We just get the argument register.
+            3. Check it with op_is_undefined.
+            4. And fill the binding with either the argument register or default value.
+
+        The above is simple. However, it has the side effect that it always increase the arity of the function.
+        While `function.length` does not increase, internally, the number of parameters of CodeBlock increases.
+        This effectively prevent our DFG / FTL to perform inlining: currently we only allows DFG to inline
+        the function with the arity less than or equal the number of passing arguments. It is OK. But when using
+        default parameters, we frequently do not pass the argument for the parameter with the default value.
+        Thus, in our current implementation, we frequently need to fixup the arity. And we frequently fail
+        to inline the function.
+
+        This patch fixes the above problem by not increasing the arity of the function. When we encounter the
+        parameter with the default value, we use `op_argument` to get the argument instead of using the argument
+        registers.
+
+        This improves six-speed defaults.es6 performance by 4.45x.
+
+            defaults.es6        968.4126+-101.2350   ^    217.6602+-14.8831       ^ definitely 4.4492x faster
+
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::initializeNextParameter):
+        (JSC::BytecodeGenerator::initializeParameters):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::FunctionNode::emitBytecode):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::inliningCost):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionMetadata):
+        * parser/Nodes.cpp:
+        (JSC::FunctionMetadataNode::FunctionMetadataNode):
+        * parser/Nodes.h:
+        (JSC::FunctionParameters::size):
+        (JSC::FunctionParameters::at):
+        (JSC::FunctionParameters::append):
+        (JSC::FunctionParameters::isSimpleParameterList):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::isArrowFunctionParameters):
+        (JSC::Parser&lt;LexerType&gt;::parseGeneratorFunctionSourceElements):
+        (JSC::Parser&lt;LexerType&gt;::parseAsyncFunctionSourceElements):
+        (JSC::Parser&lt;LexerType&gt;::parseFormalParameters):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionBody):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionParameters):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
+        * parser/Parser.h:
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createFunctionMetadata):
+        * runtime/FunctionExecutable.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::createBuiltinFunction):
+        (JSC::JSFunction::reifyLength):
+
+2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
</ins><span class="cx">         [DFG] ToString operation should have fixup for primitives to say this node does not have side effects
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=169544
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -88,7 +88,6 @@
</span><span class="cx">     , m_typeProfilingStartOffset(node-&gt;functionKeywordStart())
</span><span class="cx">     , m_typeProfilingEndOffset(node-&gt;startStartOffset() + node-&gt;source().length() - 1)
</span><span class="cx">     , m_parameterCount(node-&gt;parameterCount())
</span><del>-    , m_functionLength(node-&gt;functionLength())
</del><span class="cx">     , m_features(0)
</span><span class="cx">     , m_sourceParseMode(node-&gt;parseMode())
</span><span class="cx">     , m_isInStrictContext(node-&gt;isInStrictContext())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -77,7 +77,6 @@
</span><span class="cx">     void setEcmaName(const Identifier&amp; name) { m_ecmaName = name; }
</span><span class="cx">     const Identifier&amp; inferredName() const { return m_inferredName; }
</span><span class="cx">     unsigned parameterCount() const { return m_parameterCount; }; // Excluding 'this'!
</span><del>-    unsigned functionLength() const { return m_functionLength; }
</del><span class="cx">     SourceParseMode parseMode() const { return static_cast&lt;SourceParseMode&gt;(m_sourceParseMode); };
</span><span class="cx"> 
</span><span class="cx">     const SourceCode&amp; classSource() const { return m_classSource; };
</span><span class="lines">@@ -159,7 +158,6 @@
</span><span class="cx">     unsigned m_typeProfilingStartOffset;
</span><span class="cx">     unsigned m_typeProfilingEndOffset;
</span><span class="cx">     unsigned m_parameterCount;
</span><del>-    unsigned m_functionLength;
</del><span class="cx">     CodeFeatures m_features;
</span><span class="cx">     SourceParseMode m_sourceParseMode;
</span><span class="cx">     unsigned m_isInStrictContext : 1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -254,15 +254,8 @@
</span><span class="cx">     // If IsSimpleParameterList is false, we will create a strict-mode like arguments object.
</span><span class="cx">     // IsSimpleParameterList is false if the argument list contains any default parameter values,
</span><span class="cx">     // a rest parameter, or any destructuring patterns.
</span><del>-    bool isSimpleParameterList = true;
</del><span class="cx">     // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope.
</span><del>-    for (size_t i = 0; i &lt; parameters.size(); i++) {
-        std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; parameter = parameters.at(i);
-        bool hasDefaultParameterValue = !!parameter.second;
-        auto pattern = parameter.first;
-        bool isSimpleParameter = !hasDefaultParameterValue &amp;&amp; pattern-&gt;isBindingNode();
-        isSimpleParameterList &amp;= isSimpleParameter;
-    }
</del><ins>+    bool isSimpleParameterList = parameters.isSimpleParameterList();
</ins><span class="cx"> 
</span><span class="cx">     SourceParseMode parseMode = codeBlock-&gt;parseMode();
</span><span class="cx"> 
</span><span class="lines">@@ -983,10 +976,12 @@
</span><span class="cx">             std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; parameter = parameters.at(i);
</span><span class="cx">             if (parameter.first-&gt;isRestParameter())
</span><span class="cx">                 continue;
</span><del>-            RefPtr&lt;RegisterID&gt; parameterValue = &amp;registerFor(virtualRegisterForArgument(1 + i));
-            emitMove(temp.get(), parameterValue.get());
</del><ins>+            if ((i + 1) &lt; m_parameters.size())
+                emitMove(temp.get(), &amp;m_parameters[i + 1]);
+            else
+                emitGetArgument(temp.get(), i);
</ins><span class="cx">             if (parameter.second) {
</span><del>-                RefPtr&lt;RegisterID&gt; condition = emitIsUndefined(newTemporary(), parameterValue.get());
</del><ins>+                RefPtr&lt;RegisterID&gt; condition = emitIsUndefined(newTemporary(), temp.get());
</ins><span class="cx">                 Ref&lt;Label&gt; skipDefaultParameterBecauseNotUndefined = newLabel();
</span><span class="cx">                 emitJumpIfFalse(condition.get(), skipDefaultParameterBecauseNotUndefined.get());
</span><span class="cx">                 emitNode(temp.get(), parameter.second);
</span><span class="lines">@@ -1103,7 +1098,8 @@
</span><span class="cx"> RegisterID* BytecodeGenerator::initializeNextParameter()
</span><span class="cx"> {
</span><span class="cx">     VirtualRegister reg = virtualRegisterForArgument(m_codeBlock-&gt;numParameters());
</span><del>-    RegisterID&amp; parameter = registerFor(reg);
</del><ins>+    m_parameters.grow(m_parameters.size() + 1);
+    auto&amp; parameter = registerFor(reg);
</ins><span class="cx">     parameter.setIndex(reg.offset());
</span><span class="cx">     m_codeBlock-&gt;addParameter();
</span><span class="cx">     return &amp;parameter;
</span><span class="lines">@@ -1113,14 +1109,23 @@
</span><span class="cx"> {
</span><span class="cx">     // Make sure the code block knows about all of our parameters, and make sure that parameters
</span><span class="cx">     // needing destructuring are noted.
</span><del>-    m_parameters.grow(parameters.size() + 1); // reserve space for &quot;this&quot;
</del><span class="cx">     m_thisRegister.setIndex(initializeNextParameter()-&gt;index()); // this
</span><ins>+
+    bool nonSimpleArguments = false;
</ins><span class="cx">     for (unsigned i = 0; i &lt; parameters.size(); ++i) {
</span><del>-        auto pattern = parameters.at(i).first;
</del><ins>+        auto parameter = parameters.at(i);
+        auto pattern = parameter.first;
</ins><span class="cx">         if (pattern-&gt;isRestParameter()) {
</span><span class="cx">             RELEASE_ASSERT(!m_restParameter);
</span><span class="cx">             m_restParameter = static_cast&lt;RestParameterNode*&gt;(pattern);
</span><del>-        } else
</del><ins>+            nonSimpleArguments = true;
+            continue;
+        }
+        if (parameter.second) {
+            nonSimpleArguments = true;
+            continue;
+        }
+        if (!nonSimpleArguments)
</ins><span class="cx">             initializeNextParameter();
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -640,7 +640,6 @@
</span><span class="cx">         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&amp;);
</span><span class="cx">         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
</span><span class="cx">         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property);
</span><del>-        RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
</del><span class="cx">         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
</span><span class="cx">         RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
</span><span class="cx">         RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -3465,13 +3465,13 @@
</span><span class="cx"> void FunctionNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</span><span class="cx"> {
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><del>-        for (size_t i = 0; i &lt; m_parameters-&gt;size(); i++) {
-            // Destructuring parameters are handled in destructuring nodes.
-            if (!m_parameters-&gt;at(i).first-&gt;isBindingNode())
-                continue;
-            BindingNode* parameter = static_cast&lt;BindingNode*&gt;(m_parameters-&gt;at(i).first);
-            RegisterID reg(CallFrame::argumentOffset(i));
-            generator.emitProfileType(&amp;reg, ProfileTypeBytecodeFunctionArgument, parameter-&gt;divotStart(), parameter-&gt;divotEnd());
</del><ins>+        // If the parameter list is non simple one, it is handled in bindValue's code.
+        if (m_parameters-&gt;isSimpleParameterList()) {
+            for (size_t i = 0; i &lt; m_parameters-&gt;size(); i++) {
+                BindingNode* bindingNode = static_cast&lt;BindingNode*&gt;(m_parameters-&gt;at(i).first);
+                RegisterID reg(CallFrame::argumentOffset(i));
+                generator.emitProfileType(&amp;reg, ProfileTypeBytecodeFunctionArgument, bindingNode-&gt;divotStart(), bindingNode-&gt;divotEnd());
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -1424,15 +1424,6 @@
</span><span class="cx">         return UINT_MAX;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // Does the number of arguments we're passing match the arity of the target? We currently
-    // inline only if the number of arguments passed is greater than or equal to the number
-    // arguments expected.
-    if (static_cast&lt;int&gt;(executable-&gt;parameterCount()) + 1 &gt; argumentCountIncludingThis) {
-        if (verbose)
-            dataLog(&quot;    Failing because of arity mismatch.\n&quot;);
-        return UINT_MAX;
-    }
-    
</del><span class="cx">     // Do we have a code block, and does the code block's size match the heuristics/requirements for
</span><span class="cx">     // being an inline candidate? We might not have a code block (1) if code was thrown away,
</span><span class="cx">     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
</span><span class="lines">@@ -1446,6 +1437,16 @@
</span><span class="cx">             dataLog(&quot;    Failing because no code block available.\n&quot;);
</span><span class="cx">         return UINT_MAX;
</span><span class="cx">     }
</span><ins>+
+    // Does the number of arguments we're passing match the arity of the target? We currently
+    // inline only if the number of arguments passed is greater than or equal to the number
+    // arguments expected.
+    if (codeBlock-&gt;numParameters() &gt; argumentCountIncludingThis) {
+        if (verbose)
+            dataLog(&quot;    Failing because of arity mismatch.\n&quot;);
+        return UINT_MAX;
+    }
+
</ins><span class="cx">     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
</span><span class="cx">         codeBlock, kind, callee.isClosureCall());
</span><span class="cx">     if (verbose) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -427,7 +427,7 @@
</span><span class="cx">         unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
</span><span class="cx">         int functionNameStart, int parametersStart, bool inStrictContext, 
</span><span class="cx">         ConstructorKind constructorKind, SuperBinding superBinding,
</span><del>-        unsigned parameterCount, unsigned functionLength,
</del><ins>+        unsigned parameterCount,
</ins><span class="cx">         SourceParseMode mode, bool isArrowFunctionBodyExpression)
</span><span class="cx">     {
</span><span class="cx">         return new (m_parserArena) FunctionMetadataNode(
</span><span class="lines">@@ -434,7 +434,7 @@
</span><span class="cx">             m_parserArena, startLocation, endLocation, startColumn, endColumn, 
</span><span class="cx">             functionKeywordStart, functionNameStart, parametersStart, 
</span><span class="cx">             inStrictContext, constructorKind, superBinding,
</span><del>-            parameterCount, functionLength, mode, isArrowFunctionBodyExpression);
</del><ins>+            parameterCount, mode, isArrowFunctionBodyExpression);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ExpressionNode* createArrowFunctionExpr(const JSTokenLocation&amp; location, const ParserFunctionInfo&lt;ASTBuilder&gt;&amp; functionInfo)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/Nodes.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">     ParserArena&amp;, const JSTokenLocation&amp; startLocation, 
</span><span class="cx">     const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, 
</span><span class="cx">     int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, 
</span><del>-    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, unsigned functionLength, SourceParseMode mode, bool isArrowFunctionBodyExpression)
</del><ins>+    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
</ins><span class="cx">         : Node(endLocation)
</span><span class="cx">         , m_startColumn(startColumn)
</span><span class="cx">         , m_endColumn(endColumn)
</span><span class="lines">@@ -144,7 +144,6 @@
</span><span class="cx">         , m_parametersStart(parametersStart)
</span><span class="cx">         , m_startStartOffset(startLocation.startOffset)
</span><span class="cx">         , m_parameterCount(parameterCount)
</span><del>-        , m_functionLength(functionLength)
</del><span class="cx">         , m_parseMode(mode)
</span><span class="cx">         , m_isInStrictContext(isInStrictContext)
</span><span class="cx">         , m_superBinding(static_cast&lt;unsigned&gt;(superBinding))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -1867,22 +1867,6 @@
</span><span class="cx">         ModuleNameNode* m_moduleName { nullptr };
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    class FunctionParameters : public ParserArenaDeletable {
-    public:
-        FunctionParameters();
-        ALWAYS_INLINE unsigned size() const { return m_patterns.size(); }
-        ALWAYS_INLINE std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; at(unsigned index) { return m_patterns[index]; }
-        ALWAYS_INLINE void append(DestructuringPatternNode* pattern, ExpressionNode* defaultValue) 
-        { 
-            ASSERT(pattern); 
-            m_patterns.append(std::make_pair(pattern, defaultValue));
-        }
-
-    private:
-
-        Vector&lt;std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt;, 3&gt; m_patterns;
-    };
-
</del><span class="cx">     class FunctionMetadataNode final : public Node, public ParserArenaDeletable {
</span><span class="cx">     public:
</span><span class="cx">         using ParserArenaDeletable::operator new;
</span><span class="lines">@@ -1891,7 +1875,7 @@
</span><span class="cx">             ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, 
</span><span class="cx">             unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
</span><span class="cx">             int functionNameStart, int parametersStart, bool isInStrictContext, 
</span><del>-            ConstructorKind, SuperBinding, unsigned parameterCount, unsigned functionLength,
</del><ins>+            ConstructorKind, SuperBinding, unsigned parameterCount,
</ins><span class="cx">             SourceParseMode, bool isArrowFunctionBodyExpression);
</span><span class="cx"> 
</span><span class="cx">         void finishParsing(const SourceCode&amp;, const Identifier&amp;, FunctionMode);
</span><span class="lines">@@ -1911,7 +1895,6 @@
</span><span class="cx">         unsigned startColumn() const { return m_startColumn; }
</span><span class="cx">         unsigned endColumn() const { return m_endColumn; }
</span><span class="cx">         unsigned parameterCount() const { return m_parameterCount; }
</span><del>-        unsigned functionLength() const { return m_functionLength; }
</del><span class="cx">         SourceParseMode parseMode() const { return m_parseMode; }
</span><span class="cx"> 
</span><span class="cx">         void setEndPosition(JSTextPosition);
</span><span class="lines">@@ -1948,7 +1931,6 @@
</span><span class="cx">         SourceCode m_classSource;
</span><span class="cx">         int m_startStartOffset;
</span><span class="cx">         unsigned m_parameterCount;
</span><del>-        unsigned m_functionLength;
</del><span class="cx">         int m_lastLine;
</span><span class="cx">         SourceParseMode m_parseMode;
</span><span class="cx">         unsigned m_isInStrictContext : 1;
</span><span class="lines">@@ -2239,6 +2221,36 @@
</span><span class="cx">         ExpressionNode* m_initializer;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class FunctionParameters : public ParserArenaDeletable {
+    public:
+        FunctionParameters();
+        ALWAYS_INLINE unsigned size() const { return m_patterns.size(); }
+        ALWAYS_INLINE std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; at(unsigned index) { return m_patterns[index]; }
+        ALWAYS_INLINE void append(DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
+        {
+            ASSERT(pattern);
+
+            // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
+            // This implements IsSimpleParameterList in the Ecma 2015 spec.
+            // If IsSimpleParameterList is false, we will create a strict-mode like arguments object.
+            // IsSimpleParameterList is false if the argument list contains any default parameter values,
+            // a rest parameter, or any destructuring patterns.
+            // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope.
+
+            bool hasDefaultParameterValue = defaultValue;
+            bool isSimpleParameter = !hasDefaultParameterValue &amp;&amp; pattern-&gt;isBindingNode();
+            m_isSimpleParameterList &amp;= isSimpleParameter;
+
+            m_patterns.append(std::make_pair(pattern, defaultValue));
+        }
+        ALWAYS_INLINE bool isSimpleParameterList() const { return m_isSimpleParameterList; }
+
+    private:
+
+        Vector&lt;std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt;, 3&gt; m_patterns;
+        bool m_isSimpleParameterList { true };
+    };
+
</ins><span class="cx">     class FuncDeclNode : public StatementNode {
</span><span class="cx">     public:
</span><span class="cx">         FuncDeclNode(const JSTokenLocation&amp;, const Identifier&amp;, FunctionMetadataNode*, const SourceCode&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -286,9 +286,8 @@
</span><span class="cx">             fakeScope-&gt;setSourceParseMode(SourceParseMode::ArrowFunctionMode);
</span><span class="cx"> 
</span><span class="cx">             unsigned parametersCount = 0;
</span><del>-            unsigned functionLength = 0;
</del><span class="cx">             bool isArrowFunctionParameterList = true;
</span><del>-            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount, functionLength) &amp;&amp; consume(CLOSEPAREN) &amp;&amp; match(ARROWFUNCTION);
</del><ins>+            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount) &amp;&amp; consume(CLOSEPAREN) &amp;&amp; match(ARROWFUNCTION);
</ins><span class="cx">             propagateError();
</span><span class="cx">             popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
</span><span class="cx">         }
</span><span class="lines">@@ -465,7 +464,7 @@
</span><span class="cx">         failIfFalse(parseSourceElements(generatorFunctionContext, mode), &quot;Cannot parse the body of a generator&quot;);
</span><span class="cx">         popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
</span><span class="cx">     }
</span><del>-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, SourceParseMode::GeneratorBodyMode, false);
</del><ins>+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
</ins><span class="cx"> 
</span><span class="cx">     info.endLine = tokenLine();
</span><span class="cx">     info.endOffset = m_token.m_data.offset;
</span><span class="lines">@@ -516,7 +515,7 @@
</span><span class="cx">         }
</span><span class="cx">         popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
</span><span class="cx">     }
</span><del>-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, innerParseMode, isArrowFunctionBodyExpression);
</del><ins>+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
</ins><span class="cx"> 
</span><span class="cx">     info.endLine = tokenLine();
</span><span class="cx">     info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
</span><span class="lines">@@ -1840,7 +1839,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; bool Parser&lt;LexerType&gt;::parseFormalParameters(TreeBuilder&amp; context, TreeFormalParameterList list, bool isArrowFunction, unsigned&amp; parameterCount, unsigned&amp; functionLength)
</del><ins>+template &lt;class TreeBuilder&gt; bool Parser&lt;LexerType&gt;::parseFormalParameters(TreeBuilder&amp; context, TreeFormalParameterList list, bool isArrowFunction, unsigned&amp; parameterCount)
</ins><span class="cx"> {
</span><span class="cx"> #define failIfDuplicateIfViolation() \
</span><span class="cx">     if (duplicateParameter) {\
</span><span class="lines">@@ -1854,6 +1853,7 @@
</span><span class="cx">     bool hasDestructuringPattern = false;
</span><span class="cx">     bool isRestParameter = false;
</span><span class="cx">     const Identifier* duplicateParameter = nullptr;
</span><ins>+    unsigned restParameterStart = 0;
</ins><span class="cx">     do {
</span><span class="cx">         TreeDestructuringPattern parameter = 0;
</span><span class="cx">         TreeExpression defaultValue = 0;
</span><span class="lines">@@ -1866,7 +1866,7 @@
</span><span class="cx">             semanticFailIfTrue(!m_parserState.allowAwait &amp;&amp; match(AWAIT), &quot;Can't use 'await' as a parameter name in an async function&quot;);
</span><span class="cx">             TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &amp;duplicateParameter, &amp;hasDestructuringPattern);
</span><span class="cx">             propagateError();
</span><del>-            parameter = context.createRestParameter(destructuringPattern, parameterCount);
</del><ins>+            parameter = context.createRestParameter(destructuringPattern, restParameterStart);
</ins><span class="cx">             failIfTrue(match(COMMA), &quot;Rest parameter should be the last parameter in a function declaration&quot;); // Let's have a good error message for this common case.
</span><span class="cx">             isRestParameter = true;
</span><span class="cx">         } else
</span><span class="lines">@@ -1883,9 +1883,9 @@
</span><span class="cx">             currentScope()-&gt;setHasNonSimpleParameterList();
</span><span class="cx">         context.appendParameter(list, parameter, defaultValue);
</span><span class="cx">         if (!isRestParameter) {
</span><del>-            parameterCount++;
</del><ins>+            restParameterStart++;
</ins><span class="cx">             if (!hasDefaultParameterValues)
</span><del>-                functionLength++;
</del><ins>+                parameterCount++;
</ins><span class="cx">         }
</span><span class="cx">     } while (!isRestParameter &amp;&amp; consume(COMMA));
</span><span class="cx"> 
</span><span class="lines">@@ -1896,7 +1896,7 @@
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="cx"> template &lt;class TreeBuilder&gt; TreeFunctionBody Parser&lt;LexerType&gt;::parseFunctionBody(
</span><span class="cx">     TreeBuilder&amp; context, SyntaxChecker&amp; syntaxChecker, const JSTokenLocation&amp; startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
</span><del>-    ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, unsigned functionLength, SourceParseMode parseMode)
</del><ins>+    ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
</ins><span class="cx"> {
</span><span class="cx">     bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
</span><span class="cx">     if (!isArrowFunctionBodyExpression) {
</span><span class="lines">@@ -1904,7 +1904,7 @@
</span><span class="cx">         if (match(CLOSEBRACE)) {
</span><span class="cx">             unsigned endColumn = tokenColumn();
</span><span class="cx">             SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
</span><del>-            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
</del><ins>+            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1923,7 +1923,7 @@
</span><span class="cx">     }
</span><span class="cx">     unsigned endColumn = tokenColumn();
</span><span class="cx">     SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
</span><del>-    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
</del><ins>+    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static const char* stringForFunctionMode(SourceParseMode mode)
</span><span class="lines">@@ -1977,16 +1977,14 @@
</span><span class="cx">                 
</span><span class="cx">                 if (match(CLOSEPAREN)) {
</span><span class="cx">                     functionInfo.parameterCount = 0;
</span><del>-                    functionInfo.functionLength = 0;
</del><span class="cx">                 } else {
</span><span class="cx">                     bool isArrowFunction = true;
</span><del>-                    failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), &quot;Cannot parse parameters for this &quot;, stringForFunctionMode(mode));
</del><ins>+                    failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), &quot;Cannot parse parameters for this &quot;, stringForFunctionMode(mode));
</ins><span class="cx">                 }
</span><span class="cx">                 
</span><span class="cx">                 consumeOrFail(CLOSEPAREN, &quot;Expected a ')' or a ',' after a parameter declaration&quot;);
</span><span class="cx">             } else {
</span><span class="cx">                 functionInfo.parameterCount = 1;
</span><del>-                functionInfo.functionLength = 1;
</del><span class="cx">                 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
</span><span class="cx">                 failIfFalse(parameter, &quot;Cannot parse parameter pattern&quot;);
</span><span class="cx">                 context.appendParameter(parameterList, parameter, 0);
</span><span class="lines">@@ -2004,7 +2002,6 @@
</span><span class="cx">     if (mode == SourceParseMode::GetterMode) {
</span><span class="cx">         consumeOrFail(CLOSEPAREN, &quot;getter functions must have no parameters&quot;);
</span><span class="cx">         functionInfo.parameterCount = 0;
</span><del>-        functionInfo.functionLength = 0;
</del><span class="cx">     } else if (mode == SourceParseMode::SetterMode) {
</span><span class="cx">         failIfTrue(match(CLOSEPAREN), &quot;setter functions must have one parameter&quot;);
</span><span class="cx">         const Identifier* duplicateParameter = nullptr;
</span><span class="lines">@@ -2018,17 +2015,15 @@
</span><span class="cx">             currentScope()-&gt;setHasNonSimpleParameterList();
</span><span class="cx">         }
</span><span class="cx">         context.appendParameter(parameterList, parameter, defaultValue);
</span><del>-        functionInfo.parameterCount = 1;
-        functionInfo.functionLength = defaultValue ? 0 : 1;
</del><ins>+        functionInfo.parameterCount = defaultValue ? 0 : 1;
</ins><span class="cx">         failIfTrue(match(COMMA), &quot;setter functions must have one parameter&quot;);
</span><span class="cx">         consumeOrFail(CLOSEPAREN, &quot;Expected a ')' after a parameter declaration&quot;);
</span><span class="cx">     } else {
</span><span class="cx">         if (match(CLOSEPAREN)) {
</span><span class="cx">             functionInfo.parameterCount = 0;
</span><del>-            functionInfo.functionLength = 0;
</del><span class="cx">         } else {
</span><span class="cx">             bool isArrowFunction = false;
</span><del>-            failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), &quot;Cannot parse parameters for this &quot;, stringForFunctionMode(mode));
</del><ins>+            failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), &quot;Cannot parse parameters for this &quot;, stringForFunctionMode(mode));
</ins><span class="cx">         }
</span><span class="cx">         consumeOrFail(CLOSEPAREN, &quot;Expected a ')' or a ',' after a parameter declaration&quot;);
</span><span class="cx">     }
</span><span class="lines">@@ -2130,11 +2125,10 @@
</span><span class="cx">                 startLocation, endLocation, startColumn, bodyEndColumn, 
</span><span class="cx">                 functionKeywordStart, functionNameStart, parametersStart, 
</span><span class="cx">                 cachedInfo-&gt;strictMode, constructorKind, functionSuperBinding,
</span><del>-                cachedInfo-&gt;parameterCount, cachedInfo-&gt;functionLength,
</del><ins>+                cachedInfo-&gt;parameterCount,
</ins><span class="cx">                 mode, functionBodyType == ArrowFunctionBodyExpression);
</span><span class="cx">             functionInfo.endOffset = cachedInfo-&gt;endFunctionOffset;
</span><span class="cx">             functionInfo.parameterCount = cachedInfo-&gt;parameterCount;
</span><del>-            functionInfo.functionLength = cachedInfo-&gt;functionLength;
</del><span class="cx"> 
</span><span class="cx">             functionScope-&gt;restoreFromSourceProviderCache(cachedInfo);
</span><span class="cx">             popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
</span><span class="lines">@@ -2302,7 +2296,7 @@
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     auto performParsingFunctionBody = [&amp;] {
</span><del>-        return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, functionInfo.functionLength, mode);
</del><ins>+        return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     if (isGeneratorOrAsyncFunctionWrapperParseMode(mode)) {
</span><span class="lines">@@ -2357,10 +2351,10 @@
</span><span class="cx">     // Any future reparsing can then skip the function.
</span><span class="cx">     // For arrow function is 8 = x=&gt;x + 4 symbols;
</span><span class="cx">     // For ordinary function is 16  = function(){} + 4 symbols
</span><del>-    const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
</del><ins>+    const int minimumSourceLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
</ins><span class="cx">     std::unique_ptr&lt;SourceProviderCacheItem&gt; newInfo;
</span><del>-    int functionLength = functionInfo.endOffset - functionInfo.startOffset;
-    if (TreeBuilder::CanUseFunctionCache &amp;&amp; m_functionCache &amp;&amp; functionLength &gt; minimumFunctionLengthToCache) {
</del><ins>+    int sourceLength = functionInfo.endOffset - functionInfo.startOffset;
+    if (TreeBuilder::CanUseFunctionCache &amp;&amp; m_functionCache &amp;&amp; sourceLength &gt; minimumSourceLengthToCache) {
</ins><span class="cx">         SourceProviderCacheItemCreationParameters parameters;
</span><span class="cx">         parameters.endFunctionOffset = functionInfo.endOffset;
</span><span class="cx">         parameters.functionNameStart = functionNameStart;
</span><span class="lines">@@ -2369,7 +2363,6 @@
</span><span class="cx">         parameters.lastTokenEndOffset = location.endOffset;
</span><span class="cx">         parameters.lastTokenLineStartOffset = location.lineStartOffset;
</span><span class="cx">         parameters.parameterCount = functionInfo.parameterCount;
</span><del>-        parameters.functionLength = functionInfo.functionLength;
</del><span class="cx">         parameters.constructorKind = constructorKind;
</span><span class="cx">         parameters.expectedSuperBinding = expectedSuperBinding;
</span><span class="cx">         if (functionBodyType == ArrowFunctionBodyExpression) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -1532,8 +1532,8 @@
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeProperty parseProperty(TreeBuilder&amp;, bool strict);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parsePropertyMethod(TreeBuilder&amp; context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeProperty parseGetterSetter(TreeBuilder&amp;, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, bool isClassProperty);
</span><del>-    template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&amp;, SyntaxChecker&amp;, const JSTokenLocation&amp;, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, unsigned, SourceParseMode);
-    template &lt;class TreeBuilder&gt; ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&amp;, TreeFormalParameterList, bool isArrowFunction, unsigned&amp;, unsigned&amp;);
</del><ins>+    template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&amp;, SyntaxChecker&amp;, const JSTokenLocation&amp;, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode);
+    template &lt;class TreeBuilder&gt; ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&amp;, TreeFormalParameterList, bool isArrowFunction, unsigned&amp;);
</ins><span class="cx">     enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parseVariableDeclarationList(TreeBuilder&amp;, int&amp; declarations, TreeDestructuringPattern&amp; lastPattern, TreeExpression&amp; lastInitializer, JSTextPosition&amp; identStart, JSTextPosition&amp; initStart, JSTextPosition&amp; initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool&amp; forLoopConstDoesNotHaveInitializer);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -187,7 +187,7 @@
</span><span class="cx">     ExpressionType createFunctionExpr(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { return FunctionExpr; }
</span><span class="cx">     ExpressionType createGeneratorFunctionBody(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, const Identifier&amp;) { return FunctionExpr; }
</span><span class="cx">     ExpressionType createAsyncFunctionBody(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { return FunctionExpr; }
</span><del>-    int createFunctionMetadata(const JSTokenLocation&amp;, const JSTokenLocation&amp;, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, int, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
</del><ins>+    int createFunctionMetadata(const JSTokenLocation&amp;, const JSTokenLocation&amp;, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
</ins><span class="cx">     ExpressionType createArrowFunctionExpr(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { return FunctionExpr; }
</span><span class="cx">     ExpressionType createMethodDefinition(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { return FunctionExpr; }
</span><span class="cx">     void setFunctionNameStart(int, int) { }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeFunctionExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -145,7 +145,6 @@
</span><span class="cx">     const Identifier&amp; ecmaName() { return m_unlinkedExecutable-&gt;ecmaName(); }
</span><span class="cx">     const Identifier&amp; inferredName() { return m_unlinkedExecutable-&gt;inferredName(); }
</span><span class="cx">     unsigned parameterCount() const { return m_unlinkedExecutable-&gt;parameterCount(); } // Excluding 'this'!
</span><del>-    unsigned functionLength() const { return m_unlinkedExecutable-&gt;functionLength(); }
</del><span class="cx">     SourceParseMode parseMode() const { return m_unlinkedExecutable-&gt;parseMode(); }
</span><span class="cx">     JSParserScriptMode scriptMode() const { return m_unlinkedExecutable-&gt;scriptMode(); }
</span><span class="cx">     const SourceCode&amp; classSource() const { return m_unlinkedExecutable-&gt;classSource(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (214028 => 214029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2017-03-16 04:49:47 UTC (rev 214028)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2017-03-16 05:12:53 UTC (rev 214029)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSFunction* function = create(vm, executable, globalObject);
</span><span class="cx">     function-&gt;putDirect(vm, vm.propertyNames-&gt;name, jsString(&amp;vm, executable-&gt;name().string()), ReadOnly | DontEnum);
</span><del>-    function-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(executable-&gt;functionLength()), ReadOnly | DontEnum);
</del><ins>+    function-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(executable-&gt;parameterCount()), ReadOnly | DontEnum);
</ins><span class="cx">     return function;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -112,7 +112,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSFunction* function = create(vm, executable, globalObject);
</span><span class="cx">     function-&gt;putDirect(vm, vm.propertyNames-&gt;name, jsString(&amp;vm, name), ReadOnly | DontEnum);
</span><del>-    function-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(executable-&gt;functionLength()), ReadOnly | DontEnum);
</del><ins>+    function-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(executable-&gt;parameterCount()), ReadOnly | DontEnum);
</ins><span class="cx">     return function;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -623,7 +623,7 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!hasReifiedLength());
</span><span class="cx">     ASSERT(!isHostFunction());
</span><del>-    JSValue initialValue = jsNumber(jsExecutable()-&gt;functionLength());
</del><ins>+    JSValue initialValue = jsNumber(jsExecutable()-&gt;parameterCount());
</ins><span class="cx">     unsigned initialAttributes = DontEnum | ReadOnly;
</span><span class="cx">     const Identifier&amp; identifier = vm.propertyNames-&gt;length;
</span><span class="cx">     putDirect(vm, identifier, initialValue, initialAttributes);
</span></span></pre>
</div>
</div>

</body>
</html>