<!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>[192671] 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/192671">192671</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2015-11-19 18:37:47 -0800 (Thu, 19 Nov 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>[ES6] Add support for rest parameters
https://bugs.webkit.org/show_bug.cgi?id=38408
Reviewed by Geoffrey Garen.
Source/JavaScriptCore:
This patch implements rest parameters from the ES6 spec.
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-function-definitions
We implement the rest parameter as a new AST node. This AST node
lowers to "op_new_array X, op_copy_rest X". Note
that the op_copy_rest opcode does not have a result.
The bulk of this patch is implementing op_copy_rest.
This patch implements this in all four tiers in a straight forward way.
The opcode is implemented as a C call that will read the pertinent
arguments from the call frame and fill them into the array.
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/Instruction.h:
(JSC::Instruction::Instruction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::invalidateForInContextForLocal):
(JSC::BytecodeGenerator::emitRestParameter):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::AssignmentElementNode::toString):
(JSC::RestParameterNode::collectBoundIdentifiers):
(JSC::RestParameterNode::toString):
(JSC::RestParameterNode::bindValue):
(JSC::RestParameterNode::emit):
(JSC::SpreadExpressionNode::emitBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::setEpoch):
(JSC::DFG::Node::numberOfArgumentsToSkip):
(JSC::DFG::Node::dumpChildren):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
(JSC::DFG::SpeculativeJIT::compileCopyRest):
(JSC::DFG::SpeculativeJIT::compileNotifyWrite):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCreateClonedArguments):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest):
(JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_create_out_of_band_arguments):
(JSC::JIT::emit_op_copy_rest):
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createBindingLocation):
(JSC::ASTBuilder::createRestParameter):
(JSC::ASTBuilder::createAssignmentElement):
* parser/NodeConstructors.h:
(JSC::AssignmentElementNode::AssignmentElementNode):
(JSC::RestParameterNode::RestParameterNode):
(JSC::DestructuringAssignmentNode::DestructuringAssignmentNode):
* parser/Nodes.h:
(JSC::DestructuringPatternNode::isBindingNode):
(JSC::DestructuringPatternNode::isRestParameter):
(JSC::DestructuringPatternNode::emitDirectBinding):
(JSC::RestParameterNode::name):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::declareRestOrNormalParameter):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::parseFormalParameters):
* parser/Parser.h:
(JSC::Parser::strictMode):
(JSC::Parser::isValidStrictMode):
(JSC::Parser::declareParameter):
(JSC::Parser::breakIsValid):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::operatorStackPop):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* tests/es6.yaml:
* tests/stress/rest-parameter-and-default-arguments.js: Added.
(assert):
(shouldThrowTDZ):
(foo):
(baz):
(i.shouldThrowTDZ):
* tests/stress/rest-parameter-basics.js: Added.
(assert):
(foo):
(bar):
(capture):
(baz):
(jaz):
(kaz):
(raz):
(restLength):
(testArgumentsObject):
(strictModeLikeArgumentsObject):
* tests/stress/rest-parameter-inlined.js: Added.
(assert):
(bar):
(foo):
(baz):
(jaz):
LayoutTests:
* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:
(catch):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsparsersyntaxcheckexpectedtxt">trunk/LayoutTests/js/parser-syntax-check-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsparsersyntaxcheckjs">trunk/LayoutTests/js/script-tests/parser-syntax-check.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</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="#trunkSourceJavaScriptCorebytecodeInstructionh">trunk/Source/JavaScriptCore/bytecode/Instruction.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="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</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="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.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="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.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="#trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.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="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</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="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6yaml">trunk/Source/JavaScriptCore/tests/es6.yaml</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressrestparameteranddefaultargumentsjs">trunk/Source/JavaScriptCore/tests/stress/rest-parameter-and-default-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressrestparameterbasicsjs">trunk/Source/JavaScriptCore/tests/stress/rest-parameter-basics.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressrestparameterinlinedjs">trunk/Source/JavaScriptCore/tests/stress/rest-parameter-inlined.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/LayoutTests/ChangeLog        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-11-19 Saam barati <sbarati@apple.com>
+
+ [ES6] Add support for rest parameters
+ https://bugs.webkit.org/show_bug.cgi?id=38408
+
+ Reviewed by Geoffrey Garen.
+
+ * js/parser-syntax-check-expected.txt:
+ * js/script-tests/parser-syntax-check.js:
+ (catch):
+
</ins><span class="cx"> 2015-11-19 Ryan Haddad <ryanhaddad@apple.com>
</span><span class="cx">
</span><span class="cx"> Marking imported/w3c/html-templates/parsing-html-templates/creating-an-element-for-the-token/template-owner-document.html as flaky crasher
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -929,6 +929,49 @@
</span><span class="cx"> --"
</span><span class="cx"> PASS Invalid: "function f() { 1 %
</span><span class="cx"> -- }"
</span><ins>+Rest parameter
+PASS Valid: "function foo(...a) { }"
+PASS Valid: "function f() { function foo(...a) { } }"
+PASS Valid: "function foo(a, ...b) { }"
+PASS Valid: "function f() { function foo(a, ...b) { } }"
+PASS Valid: "function foo(a = 20, ...b) { }"
+PASS Valid: "function f() { function foo(a = 20, ...b) { } }"
+PASS Valid: "function foo(a, b, c, d, e, f, g, ...h) { }"
+PASS Valid: "function f() { function foo(a, b, c, d, e, f, g, ...h) { } }"
+PASS Invalid: "function foo(a, ...b, c) { }"
+PASS Invalid: "function f() { function foo(a, ...b, c) { } }"
+PASS Invalid: "function foo(a, ...b, ) { }"
+PASS Invalid: "function f() { function foo(a, ...b, ) { } }"
+PASS Invalid: "function foo(a, ...a) { }"
+PASS Invalid: "function f() { function foo(a, ...a) { } }"
+PASS Invalid: "function foo(...a, ...b) { }"
+PASS Invalid: "function f() { function foo(...a, ...b) { } }"
+PASS Invalid: "function foo(...b, ...b) { }"
+PASS Invalid: "function f() { function foo(...b, ...b) { } }"
+PASS Invalid: "function foo(...b ...b) { }"
+PASS Invalid: "function f() { function foo(...b ...b) { } }"
+PASS Invalid: "function foo(a, a, ...b) { }"
+PASS Invalid: "function f() { function foo(a, a, ...b) { } }"
+PASS Invalid: "function foo(...{b}) { }"
+PASS Invalid: "function f() { function foo(...{b}) { } }"
+PASS Invalid: "function foo(...[b]) { }"
+PASS Invalid: "function f() { function foo(...[b]) { } }"
+PASS Invalid: "function foo(...123) { }"
+PASS Invalid: "function f() { function foo(...123) { } }"
+PASS Invalid: "function foo(...123abc) { }"
+PASS Invalid: "function f() { function foo(...123abc) { } }"
+PASS Valid: "function foo(...abc123) { }"
+PASS Valid: "function f() { function foo(...abc123) { } }"
+PASS Valid: "function foo(...let) { }"
+PASS Valid: "function f() { function foo(...let) { } }"
+PASS Invalid: "'use strict'; function foo(...let) { }"
+PASS Invalid: "function f() { 'use strict'; function foo(...let) { } }"
+PASS Valid: "function foo(...yield) { }"
+PASS Valid: "function f() { function foo(...yield) { } }"
+PASS Invalid: "'use strict'; function foo(...yield) { }"
+PASS Invalid: "function f() { 'use strict'; function foo(...yield) { } }"
+PASS Invalid: "function foo(...if) { }"
+PASS Invalid: "function f() { function foo(...if) { } }"
</ins><span class="cx"> PASS e.line is 1
</span><span class="cx"> PASS foo is 'PASS'
</span><span class="cx"> PASS bar is 'PASS'
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -556,8 +556,31 @@
</span><span class="cx"> invalid("1 % \n++");
</span><span class="cx"> invalid("1 % \n--");
</span><span class="cx">
</span><ins>+debug("Rest parameter");
+valid("function foo(...a) { }");
+valid("function foo(a, ...b) { }");
+valid("function foo(a = 20, ...b) { }");
+valid("function foo(a, b, c, d, e, f, g, ...h) { }");
+invalid("function foo(a, ...b, c) { }")
+invalid("function foo(a, ...b, ) { }")
+invalid("function foo(a, ...a) { }");
+invalid("function foo(...a, ...b) { }");
+invalid("function foo(...b, ...b) { }");
+invalid("function foo(...b ...b) { }");
+invalid("function foo(a, a, ...b) { }");
+invalid("function foo(...{b}) { }");
+invalid("function foo(...[b]) { }");
+invalid("function foo(...123) { }");
+invalid("function foo(...123abc) { }");
+valid("function foo(...abc123) { }");
+valid("function foo(...let) { }");
+invalid("'use strict'; function foo(...let) { }");
+valid("function foo(...yield) { }");
+invalid("'use strict'; function foo(...yield) { }");
+invalid("function foo(...if) { }");
</ins><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> try { eval("a.b.c = {};"); } catch(e1) { e=e1; shouldBe("e.line", "1") }
</span><span class="cx"> foo = 'FAIL';
</span><span class="cx"> bar = 'PASS';
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1,3 +1,146 @@
</span><ins>+2015-11-19 Saam barati <sbarati@apple.com>
+
+ [ES6] Add support for rest parameters
+ https://bugs.webkit.org/show_bug.cgi?id=38408
+
+ Reviewed by Geoffrey Garen.
+
+ This patch implements rest parameters from the ES6 spec.
+ http://www.ecma-international.org/ecma-262/6.0/index.html#sec-function-definitions
+
+ We implement the rest parameter as a new AST node. This AST node
+ lowers to "op_new_array X, op_copy_rest X". Note
+ that the op_copy_rest opcode does not have a result.
+ The bulk of this patch is implementing op_copy_rest.
+ This patch implements this in all four tiers in a straight forward way.
+ The opcode is implemented as a C call that will read the pertinent
+ arguments from the call frame and fill them into the array.
+
+ * bytecode/BytecodeList.json:
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ (JSC::computeDefsForBytecodeOffset):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * bytecode/Instruction.h:
+ (JSC::Instruction::Instruction):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+ (JSC::BytecodeGenerator::invalidateForInContextForLocal):
+ (JSC::BytecodeGenerator::emitRestParameter):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::AssignmentElementNode::toString):
+ (JSC::RestParameterNode::collectBoundIdentifiers):
+ (JSC::RestParameterNode::toString):
+ (JSC::RestParameterNode::bindValue):
+ (JSC::RestParameterNode::emit):
+ (JSC::SpreadExpressionNode::emitBytecode):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::setEpoch):
+ (JSC::DFG::Node::numberOfArgumentsToSkip):
+ (JSC::DFG::Node::dumpChildren):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
+ (JSC::DFG::SpeculativeJIT::compileCopyRest):
+ (JSC::DFG::SpeculativeJIT::compileNotifyWrite):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLIntrinsicRepository.h:
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileCreateClonedArguments):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_create_out_of_band_arguments):
+ (JSC::JIT::emit_op_copy_rest):
+ * jit/JITOperations.h:
+ * llint/LowLevelInterpreter.asm:
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createBindingLocation):
+ (JSC::ASTBuilder::createRestParameter):
+ (JSC::ASTBuilder::createAssignmentElement):
+ * parser/NodeConstructors.h:
+ (JSC::AssignmentElementNode::AssignmentElementNode):
+ (JSC::RestParameterNode::RestParameterNode):
+ (JSC::DestructuringAssignmentNode::DestructuringAssignmentNode):
+ * parser/Nodes.h:
+ (JSC::DestructuringPatternNode::isBindingNode):
+ (JSC::DestructuringPatternNode::isRestParameter):
+ (JSC::DestructuringPatternNode::emitDirectBinding):
+ (JSC::RestParameterNode::name):
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseVariableDeclarationList):
+ (JSC::Parser<LexerType>::declareRestOrNormalParameter):
+ (JSC::Parser<LexerType>::createBindingPattern):
+ (JSC::Parser<LexerType>::parseFormalParameters):
+ * parser/Parser.h:
+ (JSC::Parser::strictMode):
+ (JSC::Parser::isValidStrictMode):
+ (JSC::Parser::declareParameter):
+ (JSC::Parser::breakIsValid):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::operatorStackPop):
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/CommonSlowPaths.h:
+ * tests/es6.yaml:
+ * tests/stress/rest-parameter-and-default-arguments.js: Added.
+ (assert):
+ (shouldThrowTDZ):
+ (foo):
+ (baz):
+ (i.shouldThrowTDZ):
+ * tests/stress/rest-parameter-basics.js: Added.
+ (assert):
+ (foo):
+ (bar):
+ (capture):
+ (baz):
+ (jaz):
+ (kaz):
+ (raz):
+ (restLength):
+ (testArgumentsObject):
+ (strictModeLikeArgumentsObject):
+ * tests/stress/rest-parameter-inlined.js: Added.
+ (assert):
+ (bar):
+ (foo):
+ (baz):
+ (jaz):
+
</ins><span class="cx"> 2015-11-19 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> B3 should have a story for Ext/Trunc strength reduction
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -128,7 +128,8 @@
</span><span class="cx"> { "name" : "op_enumerator_generic_pname", "length" : 4 },
</span><span class="cx"> { "name" : "op_to_index_string", "length" : 3 },
</span><span class="cx"> { "name" : "op_load_arrowfunction_this", "length" : 2 },
</span><del>- { "name" : "op_assert", "length" : 3 }
</del><ins>+ { "name" : "op_assert", "length" : 3 },
+ { "name" : "op_copy_rest", "length": 3 }
</ins><span class="cx"> ]
</span><span class="cx"> },
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -70,7 +70,8 @@
</span><span class="cx"> case op_jeq_null:
</span><span class="cx"> case op_jneq_null:
</span><span class="cx"> case op_dec:
</span><del>- case op_inc: {
</del><ins>+ case op_inc:
+ case op_copy_rest: {
</ins><span class="cx"> functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -247,6 +248,7 @@
</span><span class="cx"> OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
</span><span class="cx"> switch (opcodeID) {
</span><span class="cx"> // These don't define anything.
</span><ins>+ case op_copy_rest:
</ins><span class="cx"> case op_put_to_scope:
</span><span class="cx"> case op_end:
</span><span class="cx"> case op_profile_will_call:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -781,6 +781,14 @@
</span><span class="cx"> out.printf("%s", registerName(r0).data());
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ case op_copy_rest: {
+ int r0 = (++it)->u.operand;
+ printLocationAndOp(out, exec, location, it, "copy_rest");
+ out.printf("%s, ", registerName(r0).data());
+ unsigned argumentOffset = (++it)->u.unsignedValue;
+ out.printf("ArgumentsOffset: %u", argumentOffset);
+ break;
+ }
</ins><span class="cx"> case op_create_this: {
</span><span class="cx"> int r0 = (++it)->u.operand;
</span><span class="cx"> int r1 = (++it)->u.operand;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeInstructionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Instruction.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Instruction.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecode/Instruction.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -75,6 +75,13 @@
</span><span class="cx"> u.jsCell.clear();
</span><span class="cx"> u.operand = operand;
</span><span class="cx"> }
</span><ins>+ Instruction(unsigned unsignedValue)
+ {
+ // We have to initialize one of the pointer members to ensure that
+ // the entire struct is initialized in 64-bit.
+ u.jsCell.clear();
+ u.unsignedValue = unsignedValue;
+ }
</ins><span class="cx">
</span><span class="cx"> Instruction(PutByIdFlags flags)
</span><span class="cx"> {
</span><span class="lines">@@ -112,6 +119,7 @@
</span><span class="cx"> union {
</span><span class="cx"> Opcode opcode;
</span><span class="cx"> int operand;
</span><ins>+ unsigned unsignedValue;
</ins><span class="cx"> WriteBarrierBase<Structure> structure;
</span><span class="cx"> StructureID structureID;
</span><span class="cx"> WriteBarrierBase<SymbolTable> symbolTable;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -70,6 +70,9 @@
</span><span class="cx"> if (m_needToInitializeArguments)
</span><span class="cx"> initializeVariable(variable(propertyNames().arguments), m_argumentsRegister);
</span><span class="cx">
</span><ins>+ if (m_restParameter)
+ m_restParameter->emit(*this);
+
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> temp = newTemporary();
</span><span class="cx"> RefPtr<RegisterID> globalScope;
</span><span class="lines">@@ -272,8 +275,14 @@
</span><span class="cx"> // needing destructuring are noted.
</span><span class="cx"> m_parameters.grow(parameters.size() + 1); // reserve space for "this"
</span><span class="cx"> m_thisRegister.setIndex(initializeNextParameter()->index()); // this
</span><del>- for (unsigned i = 0; i < parameters.size(); ++i)
- initializeNextParameter();
</del><ins>+ for (unsigned i = 0; i < parameters.size(); ++i) {
+ auto pattern = parameters.at(i).first;
+ if (pattern->isRestParameter()) {
+ RELEASE_ASSERT(!m_restParameter);
+ m_restParameter = static_cast<RestParameterNode*>(pattern);
+ } else
+ initializeNextParameter();
+ }
</ins><span class="cx">
</span><span class="cx"> // Figure out some interesting facts about our arguments.
</span><span class="cx"> bool capturesAnyArgumentByName = false;
</span><span class="lines">@@ -307,7 +316,14 @@
</span><span class="cx"> m_argumentsRegister->ref();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (needsArguments && !codeBlock->isStrictMode() && !parameters.hasDefaultParameterValues()) {
</del><ins>+ // 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.
+ // FIXME: Take into account destructuring to make isSimpleParameterList false. https://bugs.webkit.org/show_bug.cgi?id=151450
+ bool isSimpleParameterList = !parameters.hasDefaultParameterValues() && !m_restParameter;
+ if (needsArguments && !codeBlock->isStrictMode() && isSimpleParameterList) {
</ins><span class="cx"> // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
</span><span class="cx"> // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
</span><span class="cx"> // activation.
</span><span class="lines">@@ -389,7 +405,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (needsArguments && (codeBlock->isStrictMode() || parameters.hasDefaultParameterValues())) {
</del><ins>+ if (needsArguments && (codeBlock->isStrictMode() || !isSimpleParameterList)) {
</ins><span class="cx"> // Allocate an out-of-bands arguments object.
</span><span class="cx"> emitOpcode(op_create_out_of_band_arguments);
</span><span class="cx"> instructions().append(m_argumentsRegister->index());
</span><span class="lines">@@ -707,6 +723,8 @@
</span><span class="cx"> RefPtr<RegisterID> temp = newTemporary();
</span><span class="cx"> for (unsigned i = 0; i < parameters.size(); i++) {
</span><span class="cx"> std::pair<DestructuringPatternNode*, ExpressionNode*> parameter = parameters.at(i);
</span><ins>+ if (parameter.first->isRestParameter())
+ continue;
</ins><span class="cx"> RefPtr<RegisterID> parameterValue = &registerFor(virtualRegisterForArgument(1 + i));
</span><span class="cx"> emitMove(temp.get(), parameterValue.get());
</span><span class="cx"> if (parameter.second) {
</span><span class="lines">@@ -764,7 +782,7 @@
</span><span class="cx"> // If we have default parameter values, we handle this case above.
</span><span class="cx"> for (unsigned i = 0; i < parameters.size(); i++) {
</span><span class="cx"> DestructuringPatternNode* pattern = parameters.at(i).first;
</span><del>- if (!pattern->isBindingNode()) {
</del><ins>+ if (!pattern->isBindingNode() && !pattern->isRestParameter()) {
</ins><span class="cx"> RefPtr<RegisterID> parameterValue = &registerFor(virtualRegisterForArgument(1 + i));
</span><span class="cx"> pattern->bindValue(*this, parameterValue.get());
</span><span class="cx"> }
</span><span class="lines">@@ -3813,4 +3831,15 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip)
+{
+ emitNewArray(result, nullptr, 0);
+
+ emitOpcode(op_copy_rest);
+ instructions().append(result->index());
+ instructions().append(numParametersToSkip);
+
+ return result;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -598,6 +598,8 @@
</span><span class="cx"> RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
</span><span class="cx"> void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
</span><span class="cx">
</span><ins>+ RegisterID* emitRestParameter(RegisterID* result, unsigned numParametersToSkip);
+
</ins><span class="cx"> bool emitReadOnlyExceptionIfNeeded(const Variable&);
</span><span class="cx">
</span><span class="cx"> // Start a try block. 'start' must have been emitted.
</span><span class="lines">@@ -828,6 +830,7 @@
</span><span class="cx"> enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
</span><span class="cx"> Vector<std::pair<FunctionMetadataNode*, FunctionVariableType>> m_functionsToInitialize;
</span><span class="cx"> bool m_needToInitializeArguments { false };
</span><ins>+ RestParameterNode* m_restParameter { nullptr };
</ins><span class="cx">
</span><span class="cx"> Vector<TryRange> m_tryRanges;
</span><span class="cx"> SegmentedVector<TryData, 8> m_tryData;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -3456,6 +3456,35 @@
</span><span class="cx"> builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
+{
+ identifiers.append(m_name);
+}
+void RestParameterNode::toString(StringBuilder& builder) const
+{
+ builder.append(m_name.string());
+}
+void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
+{
+ RELEASE_ASSERT_NOT_REACHED();
+}
+void RestParameterNode::emit(BytecodeGenerator& generator)
+{
+ Variable var = generator.variable(m_name);
+ if (RegisterID* local = var.local()) {
+ generator.emitRestParameter(local, m_numParametersToSkip);
+ generator.emitProfileType(local, var, m_divotStart, m_divotEnd);
+ return;
+ }
+
+ RefPtr<RegisterID> restParameterArray = generator.emitRestParameter(generator.newTemporary(), m_numParametersToSkip);
+ generator.emitProfileType(restParameterArray.get(), var, m_divotStart, m_divotEnd);
+ RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
+ generator.emitExpressionInfo(m_divotEnd, m_divotStart, m_divotEnd);
+ generator.emitPutToScope(scope.get(), var, restParameterArray.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
+}
+
+
</ins><span class="cx"> RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
</span><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -2508,6 +2508,9 @@
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case CopyRest:
+ break;
+
</ins><span class="cx"> case Check: {
</span><span class="cx"> // Simplify out checks that don't actually do checking.
</span><span class="cx"> for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -3330,6 +3330,13 @@
</span><span class="cx"> set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
</span><span class="cx"> NEXT_OPCODE(op_new_regexp);
</span><span class="cx"> }
</span><ins>+
+ case op_copy_rest: {
+ noticeArgumentsUse();
+ addToGraph(CopyRest,
+ OpInfo(currentInstruction[2].u.unsignedValue), get(VirtualRegister(currentInstruction[1].u.operand)));
+ NEXT_OPCODE(op_copy_rest);
+ }
</ins><span class="cx">
</span><span class="cx"> // === Bitwise operations ===
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -219,6 +219,7 @@
</span><span class="cx"> case op_create_lexical_environment:
</span><span class="cx"> case op_get_parent_scope:
</span><span class="cx"> case op_catch:
</span><ins>+ case op_copy_rest:
</ins><span class="cx"> return CanCompileAndInline;
</span><span class="cx">
</span><span class="cx"> case op_put_to_scope: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -983,6 +983,12 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case CopyRest: {
+ read(Stack);
+ write(Heap);
+ return;
+ }
+
</ins><span class="cx"> case NewObject:
</span><span class="cx"> case NewRegexp:
</span><span class="cx"> case NewStringObject:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -224,6 +224,7 @@
</span><span class="cx"> case GetStack:
</span><span class="cx"> case GetFromArguments:
</span><span class="cx"> case PutToArguments:
</span><ins>+ case CopyRest:
</ins><span class="cx"> return false;
</span><span class="cx">
</span><span class="cx"> case CreateActivation:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1368,6 +1368,11 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case CopyRest: {
+ fixEdge<KnownCellUse>(node->child1());
+ break;
+ }
+
</ins><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
</span><span class="cx"> case SetArgument:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -2158,7 +2158,13 @@
</span><span class="cx"> {
</span><span class="cx"> m_misc.epoch = epoch.toUnsigned();
</span><span class="cx"> }
</span><del>-
</del><ins>+
+ unsigned numberOfArgumentsToSkip()
+ {
+ ASSERT(op() == CopyRest);
+ return static_cast<unsigned>(m_opInfo);
+ }
+
</ins><span class="cx"> void dumpChildren(PrintStream& out)
</span><span class="cx"> {
</span><span class="cx"> if (!child1())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -262,6 +262,7 @@
</span><span class="cx"> macro(NewArrayBuffer, NodeResultJS) \
</span><span class="cx"> macro(NewTypedArray, NodeResultJS | NodeMustGenerate) \
</span><span class="cx"> macro(NewRegexp, NodeResultJS) \
</span><ins>+ macro(CopyRest, NodeMustGenerate) \
</ins><span class="cx"> \
</span><span class="cx"> /* Support for allocation sinking. */\
</span><span class="cx"> macro(PhantomNewObject, NodeResultJS | NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -818,6 +818,16 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned numberOfArguments)
+{
+ RELEASE_ASSERT(numberOfArguments > numberOfParamsToSkip); // We should only call this from JIT code when this condition is true.
+ JSArray* array = jsCast<JSArray*>(arrayAsCell);
+ unsigned arraySize = numberOfArguments - numberOfParamsToSkip;
+ array->setLength(exec, arraySize);
+ for (unsigned i = 0; i < arraySize; i++)
+ array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
+}
+
</ins><span class="cx"> size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
</span><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment*);
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
</span><ins>+void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned argumentsCount);
</ins><span class="cx"> double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationObjectIsFunction(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -676,6 +676,7 @@
</span><span class="cx"> case ZombieHint:
</span><span class="cx"> case ExitOK:
</span><span class="cx"> case LoadVarargs:
</span><ins>+ case CopyRest:
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> // This gets ignored because it only pretends to produce a value.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -322,6 +322,7 @@
</span><span class="cx"> case PhantomClonedArguments:
</span><span class="cx"> case GetMyArgumentByVal:
</span><span class="cx"> case ForwardVarargs:
</span><ins>+ case CopyRest:
</ins><span class="cx"> return true;
</span><span class="cx">
</span><span class="cx"> case BottomValue:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -5344,6 +5344,34 @@
</span><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void SpeculativeJIT::compileCopyRest(Node* node)
+{
+ ASSERT(node->op() == CopyRest);
+
+ SpeculateCellOperand array(this, node->child1());
+ GPRReg arrayGPR = array.gpr();
+
+ GPRTemporary argumentsLength(this);
+ GPRReg argumentsLengthGPR = argumentsLength.gpr();
+
+ GPRTemporary argumentsStart(this);
+ GPRReg argumentsStartGPR = argumentsStart.gpr();
+
+ emitGetLength(node->origin.semantic, argumentsLengthGPR);
+ CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::LessThanOrEqual, argumentsLengthGPR, TrustedImm32(node->numberOfArgumentsToSkip()));
+
+ emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
+ silentSpillAllRegisters(argumentsLengthGPR, argumentsStartGPR);
+ // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:number of arguments
+ callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, TrustedImm32(node->numberOfArgumentsToSkip()), argumentsLengthGPR);
+ silentFillAllRegisters(argumentsLengthGPR);
+ m_jit.exceptionCheck();
+
+ done.link(&m_jit);
+
+ noResult(node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileNotifyWrite(Node* node)
</span><span class="cx"> {
</span><span class="cx"> WatchpointSet* set = node->watchpointSet();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1221,6 +1221,12 @@
</span><span class="cx"> return appendCall(operation);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4);
+ return appendCall(operation);
+ }
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> JITCompiler::Call callOperation(J_JITOperation_E operation, GPRReg result)
</span><span class="cx"> {
</span><span class="lines">@@ -2238,6 +2244,7 @@
</span><span class="cx"> void compilePutToArguments(Node*);
</span><span class="cx"> void compileCreateScopedArguments(Node*);
</span><span class="cx"> void compileCreateClonedArguments(Node*);
</span><ins>+ void compileCopyRest(Node*);
</ins><span class="cx"> void compileNotifyWrite(Node*);
</span><span class="cx"> bool compileRegExpExec(Node*);
</span><span class="cx"> void compileIsObjectOrNull(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -4438,6 +4438,11 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case CopyRest: {
+ compileCopyRest(node);
+ break;
+ }
+
</ins><span class="cx"> case NewFunction:
</span><span class="cx"> case NewArrowFunction:
</span><span class="cx"> compileNewFunction(node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -4427,6 +4427,10 @@
</span><span class="cx"> compileCreateClonedArguments(node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ case CopyRest: {
+ compileCopyRest(node);
+ break;
+ }
</ins><span class="cx">
</span><span class="cx"> case NewFunction:
</span><span class="cx"> case NewArrowFunction:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -210,6 +210,7 @@
</span><span class="cx"> case PutGetterSetterById:
</span><span class="cx"> case PutGetterByVal:
</span><span class="cx"> case PutSetterByVal:
</span><ins>+ case CopyRest:
</ins><span class="cx"> // These are OK.
</span><span class="cx"> break;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -130,6 +130,7 @@
</span><span class="cx"> macro(Z_JITOperation_EGC, functionType(int32, intPtr, intPtr, intPtr)) \
</span><span class="cx"> macro(Z_JITOperation_EJZ, functionType(int32, intPtr, int64, int32)) \
</span><span class="cx"> macro(Z_JITOperation_ESJss, functionType(int32, intPtr, intPtr, int64)) \
</span><ins>+ macro(V_JITOperation_ECRUiUi, functionType(voidType, intPtr, intPtr, intPtr, int32, int32))
</ins><span class="cx">
</span><span class="cx"> class IntrinsicRepository : public CommonValues {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -967,6 +967,9 @@
</span><span class="cx"> case CheckWatchdogTimer:
</span><span class="cx"> compileCheckWatchdogTimer();
</span><span class="cx"> break;
</span><ins>+ case CopyRest:
+ compileCopyRest();
+ break;
</ins><span class="cx">
</span><span class="cx"> case PhantomLocal:
</span><span class="cx"> case LoopHint:
</span><span class="lines">@@ -3636,6 +3639,28 @@
</span><span class="cx">
</span><span class="cx"> setJSValue(result);
</span><span class="cx"> }
</span><ins>+
+ void compileCopyRest()
+ {
+ LBasicBlock doCopyRest = FTL_NEW_BLOCK(m_out, ("CopyRest C call"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("FillRestParameter continuation"));
+
+ LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
+ LValue numberOfArguments = getArgumentsLength().value;
+
+ m_out.branch(
+ m_out.above(numberOfArguments, numberOfArgumentsToSkip),
+ unsure(doCopyRest), unsure(continuation));
+
+ LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
+ // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:number of arguments
+ vmCall(
+ m_out.voidType,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()),
+ getArgumentsStart(), numberOfArgumentsToSkip, numberOfArguments);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ }
</ins><span class="cx">
</span><span class="cx"> void compileNewObject()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -211,6 +211,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_out_of_band_arguments)
</span><ins>+ DEFINE_OP(op_copy_rest)
</ins><span class="cx"> DEFINE_OP(op_check_tdz)
</span><span class="cx"> DEFINE_OP(op_assert)
</span><span class="cx"> DEFINE_OP(op_debug)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -490,6 +490,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_out_of_band_arguments(Instruction*);
</span><ins>+ void emit_op_copy_rest(Instruction*);
</ins><span class="cx"> void emit_op_check_tdz(Instruction*);
</span><span class="cx"> void emit_op_assert(Instruction*);
</span><span class="cx"> void emit_op_debug(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1399,6 +1399,12 @@
</span><span class="cx"> slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JIT::emit_op_copy_rest(Instruction* currentInstruction)
+{
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);
+ slowPathCall.call();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx">
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -92,6 +92,7 @@
</span><span class="cx"> Vm: VM*
</span><span class="cx"> Ws: WatchpointSet*
</span><span class="cx"> Z: int32_t
</span><ins>+ Ui: uint32_t
</ins><span class="cx"> */
</span><span class="cx">
</span><span class="cx"> typedef CallFrame* JIT_OPERATION (*F_JITOperation_EFJZZ)(ExecState*, CallFrame*, EncodedJSValue, int32_t, int32_t);
</span><span class="lines">@@ -219,6 +220,7 @@
</span><span class="cx"> typedef void JIT_OPERATION (*V_JITOperation_EVm)(ExecState*, VM*);
</span><span class="cx"> typedef void JIT_OPERATION (*V_JITOperation_J)(EncodedJSValue);
</span><span class="cx"> typedef void JIT_OPERATION (*V_JITOperation_Z)(int32_t);
</span><ins>+typedef void JIT_OPERATION (*V_JITOperation_ECRUiUi)(ExecState*, JSCell*, Register*, uint32_t, uint32_t);
</ins><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_EC)(ExecState*, JSCell*);
</span><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_ECli)(ExecState*, CallLinkInfo*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1675,6 +1675,12 @@
</span><span class="cx"> callSlowPath(_slow_path_to_index_string)
</span><span class="cx"> dispatch(3)
</span><span class="cx">
</span><ins>+_llint_op_copy_rest:
+ traceExecution()
+ callSlowPath(_slow_path_copy_rest)
+ dispatch(3)
+
+
</ins><span class="cx"> # Lastly, make sure that we can link even though we don't support all opcodes.
</span><span class="cx"> # These opcodes should never arise when using LLInt or either JIT. We assert
</span><span class="cx"> # as much.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -857,6 +857,11 @@
</span><span class="cx"> return new (m_parserArena) BindingNode(boundProperty, start, end, context);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ RestParameterNode* createRestParameter(const Identifier& name, size_t numParametersToSkip, const JSTextPosition& start, const JSTextPosition& end)
+ {
+ return new (m_parserArena) RestParameterNode(name, numParametersToSkip, start, end);
+ }
+
</ins><span class="cx"> AssignmentElement createAssignmentElement(const Expression& assignmentTarget, const JSTextPosition& start, const JSTextPosition& end)
</span><span class="cx"> {
</span><span class="cx"> return new (m_parserArena) AssignmentElementNode(assignmentTarget, start, end);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1029,6 +1029,15 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ inline RestParameterNode::RestParameterNode(const Identifier& name, unsigned numParametersToSkip, const JSTextPosition& start, const JSTextPosition& end)
+ : DestructuringPatternNode()
+ , m_name(name)
+ , m_numParametersToSkip(numParametersToSkip)
+ , m_divotStart(start)
+ , m_divotEnd(end)
+ {
+ }
+
</ins><span class="cx"> inline DestructuringAssignmentNode::DestructuringAssignmentNode(const JSTokenLocation& location, DestructuringPatternNode* bindings, ExpressionNode* initializer)
</span><span class="cx"> : ExpressionNode(location)
</span><span class="cx"> , m_bindings(bindings)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1973,6 +1973,7 @@
</span><span class="cx"> virtual void toString(StringBuilder&) const = 0;
</span><span class="cx">
</span><span class="cx"> virtual bool isBindingNode() const { return false; }
</span><ins>+ virtual bool isRestParameter() const { return false; }
</ins><span class="cx"> virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID*, ExpressionNode*) { return 0; }
</span><span class="cx">
</span><span class="cx"> protected:
</span><span class="lines">@@ -2053,6 +2054,27 @@
</span><span class="cx"> AssignmentContext m_bindingContext;
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+ class RestParameterNode : public DestructuringPatternNode {
+ public:
+ RestParameterNode(const Identifier& boundProperty, unsigned numParametersToSkip, const JSTextPosition& start, const JSTextPosition& end);
+
+ bool isRestParameter() const override { return true; }
+
+ void emit(BytecodeGenerator&);
+
+ const Identifier& name() const { return m_name; }
+
+ private:
+ virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
+ virtual void bindValue(BytecodeGenerator&, RegisterID*) const override;
+ virtual void toString(StringBuilder&) const override;
+
+ const Identifier& m_name;
+ unsigned m_numParametersToSkip;
+ JSTextPosition m_divotStart; // "f" in "...foo"
+ JSTextPosition m_divotEnd;
+ };
+
</ins><span class="cx"> class AssignmentElementNode : public DestructuringPatternNode {
</span><span class="cx"> public:
</span><span class="cx"> AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition& start, const JSTextPosition& end);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -669,6 +669,30 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <typename LexerType>
</span><ins>+bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
+{
+ DeclarationResultMask declarationResult = declareParameter(&name);
+ if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
+ semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
+ if (m_lastFunctionName && name == *m_lastFunctionName)
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
+ semanticFailureDueToKeyword("parameter name");
+ if (hasDeclaredParameter(name))
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
+ }
+ if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
+ // It's not always an error to define a duplicate parameter.
+ // It's only an error when there are default parameter values or destructuring parameters.
+ // We note this value now so we can check it later.
+ if (duplicateIdentifier)
+ *duplicateIdentifier = &name;
+ }
+
+ return true;
+}
+
+template <typename LexerType>
</ins><span class="cx"> template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!name.isNull());
</span><span class="lines">@@ -687,23 +711,8 @@
</span><span class="cx"> failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
</span><span class="cx"> }
</span><span class="cx"> } else if (kind == DestructureToParameters) {
</span><del>- DeclarationResultMask declarationResult = declareParameter(&name);
- if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
- semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
- if (m_lastFunctionName && name == *m_lastFunctionName)
- semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
- semanticFailureDueToKeyword("parameter name");
- if (hasDeclaredParameter(name))
- semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
- semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
- }
- if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
- // It's not always an error to define a duplicate parameter.
- // It's only an error when there are default parameter values or destructuring parameters.
- // We note this value now so we can check it later.
- if (duplicateIdentifier)
- *duplicateIdentifier = &name;
- }
</del><ins>+ declareRestOrNormalParameter(name, duplicateIdentifier);
+ propagateError();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (exportType == ExportType::Exported) {
</span><span class="lines">@@ -1536,32 +1545,45 @@
</span><span class="cx"> template <typename LexerType>
</span><span class="cx"> template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount)
</span><span class="cx"> {
</span><del>-#define failFromDuplicate() \
</del><ins>+#define failIfDuplicateIfViolation() \
</ins><span class="cx"> if (duplicateParameter) {\
</span><span class="cx"> semanticFailIfTrue(defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
</span><span class="cx"> semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
</span><ins>+ semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ bool hasDestructuringPattern = false;
+ bool isRestParameter = false;
</ins><span class="cx"> const Identifier* duplicateParameter = nullptr;
</span><del>- bool hasDestructuringPattern = false;
- auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
- failIfFalse(parameter, "Cannot parse parameter pattern");
- auto defaultValue = parseDefaultValueForDestructuringPattern(context);
- propagateError();
- failFromDuplicate();
- context.appendParameter(list, parameter, defaultValue);
- parameterCount++;
- while (consume(COMMA)) {
- parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
</del><ins>+ do {
+ TreeDestructuringPattern parameter = 0;
+ TreeExpression defaultValue = 0;
+
+ if (match(DOTDOTDOT)) {
+ next();
+ failIfFalse(matchSpecIdentifier(), "Rest parameter '...' should be followed by a variable identifier");
+ declareRestOrNormalParameter(*m_token.m_data.ident, &duplicateParameter);
+ propagateError();
+ JSTextPosition identifierStart = tokenStartPosition();
+ JSTextPosition identifierEnd = tokenEndPosition();
+ parameter = context.createRestParameter(*m_token.m_data.ident, parameterCount, identifierStart, identifierEnd);
+ next();
+ failIfTrue(match(COMMA), "Rest parameter should be the last parameter in a function declaration"); // Let's have a good error message for this common case.
+ isRestParameter = true;
+ } else
+ parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
</ins><span class="cx"> failIfFalse(parameter, "Cannot parse parameter pattern");
</span><del>- defaultValue = parseDefaultValueForDestructuringPattern(context);
</del><ins>+ if (!isRestParameter)
+ defaultValue = parseDefaultValueForDestructuringPattern(context);
</ins><span class="cx"> propagateError();
</span><del>- failFromDuplicate();
</del><ins>+ failIfDuplicateIfViolation();
</ins><span class="cx"> context.appendParameter(list, parameter, defaultValue);
</span><del>- parameterCount++;
- }
</del><ins>+ if (!isRestParameter)
+ parameterCount++;
+ } while (!isRestParameter && consume(COMMA));
+
</ins><span class="cx"> return true;
</span><del>-#undef failFromDuplicate
</del><ins>+#undef failIfDuplicateIfViolation
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <typename LexerType>
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1073,6 +1073,8 @@
</span><span class="cx"> bool strictMode() { return currentScope()->strictMode(); }
</span><span class="cx"> bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
</span><span class="cx"> DeclarationResultMask declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
</span><ins>+ bool declareRestOrNormalParameter(const Identifier&, const Identifier**);
+
</ins><span class="cx"> bool breakIsValid()
</span><span class="cx"> {
</span><span class="cx"> ScopeRef current = currentScope();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx"> FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr,
</span><span class="cx"> NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
</span><span class="cx"> ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr,
</span><del>- DeleteExpr, ArrayLiteralExpr, BindingDestructuring,
</del><ins>+ DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter,
</ins><span class="cx"> ArrayDestructuring, ObjectDestructuring, SourceElementsResult,
</span><span class="cx"> FunctionBodyResult, SpreadExpr, ArgumentsResult,
</span><span class="cx"> PropertyListResult, ArgumentsListResult, ElementsListResult,
</span><span class="lines">@@ -135,6 +135,7 @@
</span><span class="cx"> typedef int DestructuringPattern;
</span><span class="cx"> typedef DestructuringPattern ArrayPattern;
</span><span class="cx"> typedef DestructuringPattern ObjectPattern;
</span><ins>+ typedef DestructuringPattern RestPattern;
</ins><span class="cx">
</span><span class="cx"> static const bool CreatesAST = false;
</span><span class="cx"> static const bool NeedsFreeVariableInfo = false;
</span><span class="lines">@@ -346,6 +347,10 @@
</span><span class="cx"> {
</span><span class="cx"> return BindingDestructuring;
</span><span class="cx"> }
</span><ins>+ RestPattern createRestParameter(const Identifier&, size_t, const JSTextPosition&, const JSTextPosition&)
+ {
+ return RestParameter;
+ }
</ins><span class="cx"> DestructuringPattern createAssignmentElement(const Expression&, const JSTextPosition&, const JSTextPosition&)
</span><span class="cx"> {
</span><span class="cx"> return BindingDestructuring;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -701,4 +701,20 @@
</span><span class="cx"> RETURN(resolvedScope);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+SLOW_PATH_DECL(slow_path_copy_rest)
+{
+ BEGIN();
+ unsigned numParamsToSkip = pc[2].u.unsignedValue;
+ unsigned numArgumentsToFunction = exec->argumentCount();
+ if (numArgumentsToFunction <= numParamsToSkip)
+ END();
+
+ JSArray* array = jsCast<JSArray*>(OP(1).jsValue());
+ unsigned arraySize = numArgumentsToFunction - numParamsToSkip;
+ array->setLength(exec, arraySize);
+ for (unsigned i = 0; i < arraySize; i++)
+ array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
+ END();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -293,6 +293,7 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
</span><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_copy_rest);
</ins><span class="cx">
</span><span class="cx"> } // namespace JSC
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6yaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/es6.yaml (192670 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6.yaml        2015-11-20 01:28:30 UTC (rev 192670)
+++ trunk/Source/JavaScriptCore/tests/es6.yaml        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -1089,15 +1089,15 @@
</span><span class="cx"> - path: es6/RegExp_y_and_u_flags_y_flag_lastIndex.js
</span><span class="cx"> cmd: runES6 :fail
</span><span class="cx"> - path: es6/rest_parameters_arguments_object_interaction.js
</span><del>- cmd: runES6 :fail
</del><ins>+ cmd: runES6 :normal
</ins><span class="cx"> - path: es6/rest_parameters_basic_functionality.js
</span><del>- cmd: runES6 :fail
</del><ins>+ cmd: runES6 :normal
</ins><span class="cx"> - path: es6/rest_parameters_cant_be_used_in_setters.js
</span><del>- cmd: runES6 :fail
</del><ins>+ cmd: runES6 :normal
</ins><span class="cx"> - path: es6/rest_parameters_function_length_property.js
</span><del>- cmd: runES6 :fail
</del><ins>+ cmd: runES6 :normal
</ins><span class="cx"> - path: es6/rest_parameters_new_Function_support.js
</span><del>- cmd: runES6 :fail
</del><ins>+ cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Set_iterator_closing.js
</span><span class="cx"> cmd: runES6 :fail
</span><span class="cx"> - path: es6/Set_Set[Symbol.species].js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressrestparameteranddefaultargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/rest-parameter-and-default-arguments.js (0 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/rest-parameter-and-default-arguments.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/rest-parameter-and-default-arguments.js        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+noInline(assert);
+
+function shouldThrowTDZ(func) {
+ var hasThrown = false;
+ try {
+ func();
+ } catch(e) {
+ if (e.name.indexOf("ReferenceError") !== -1)
+ hasThrown = true;
+ }
+ assert(hasThrown);
+}
+noInline(shouldThrowTDZ);
+
+function foo(a = function() { return c; }, b = a(), ...c) {
+ return a();
+}
+noInline(foo);
+
+function baz(a = function() { return b; }, ...b) {
+ return a();
+}
+
+for (let i = 0; i < 1000; i++) {
+ shouldThrowTDZ(function() { foo(undefined, undefined, 10, 20); });
+ let o = {x: 20};
+ let result = baz(undefined, 10, o, "baz");
+ assert(result.length === 3);
+ assert(result[0] === 10);
+ assert(result[1] === o);
+ assert(result[2] === "baz");
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressrestparameterbasicsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/rest-parameter-basics.js (0 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/rest-parameter-basics.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/rest-parameter-basics.js        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -0,0 +1,103 @@
</span><ins>+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+noInline(assert);
+
+function foo(a, ...b) {
+ return b;
+}
+noInline(foo);
+
+function bar(a, ...b) {
+ return a + b[0];
+}
+noInline(bar);
+
+function baz(a, ...b) {
+ function capture() { return b; }
+ assert(b[0] === capture()[0]);
+ return a + b[0];
+}
+noInline(baz);
+
+function jaz(a, ...b) {
+ function capture() { return a + b[0]; }
+ assert(capture() === a + b[0]);
+ return a + b[0];
+}
+noInline(jaz);
+
+function kaz(a = 10, ...b) {
+ return a + b[0]
+}
+noInline(kaz);
+
+function raz(a = 10, ...b) {
+ function capture() { return a + b[0]; }
+ assert(capture() === a + b[0]);
+ return a + b[0];
+}
+noInline(raz);
+
+function restLength(a, ...b) {
+ return b.length;
+}
+noInline(restLength);
+
+function testArgumentsObject(...args) {
+ assert(args.length === arguments.length);
+ for (let i = 0; i < args.length; i++)
+ assert(args[i] === arguments[i]);
+}
+noInline(testArgumentsObject);
+
+function strictModeLikeArgumentsObject(a, ...args) {
+ assert(arguments[0] === a);
+ a = "a";
+ assert(arguments[0] !== a);
+ assert(arguments[0] === 20);
+ assert(arguments.length === 2);
+ assert(args.length === 1);
+ assert(arguments[1] === args[0]);
+ arguments[1] = "b";
+ assert(args[0] !== "b");
+}
+noInline(strictModeLikeArgumentsObject);
+
+for (let i = 0; i < 10000; i++) {
+ let a1 = foo(10, 20);
+ assert(a1 instanceof Array);
+ assert(a1.length === 1);
+ assert(a1[0] === 20);
+
+ let a2 = foo(10);
+ assert(a2 instanceof Array);
+ assert(a2.length === 0);
+
+ let a3 = bar(10, 20);
+ assert(a3 === 30);
+
+ let a4 = baz(10, 20);
+ assert(a4 === 30);
+
+ let a5 = jaz("hello", "world");
+ assert(a5 === "helloworld");
+
+ let a6 = kaz(undefined, 40);
+ assert(a6 === 50);
+
+ let a7 = kaz(undefined, 40);
+ assert(a7 === 50);
+
+ assert(restLength() === 0);
+ assert(restLength(1) === 0);
+ assert(restLength(1, 1) === 1);
+ assert(restLength(1, 1, 1) === 2);
+ assert(restLength(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) === 20);
+
+ let obj = {foo: 40};
+ testArgumentsObject("hello", obj, 100, 12.34, "world", obj, [1, 2, 3]);
+
+ strictModeLikeArgumentsObject(20, 30);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressrestparameterinlinedjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/rest-parameter-inlined.js (0 => 192671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/rest-parameter-inlined.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/rest-parameter-inlined.js        2015-11-20 02:37:47 UTC (rev 192671)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+noInline(assert);
+
+function bar(...rest) {
+ return rest;
+}
+
+function foo(a, b, c) {
+ return bar(a, b, c);
+}
+noInline(foo);
+
+for (let i = 0; i < 10000; i++) {
+ let result = foo(10, 20, 30);
+ assert(result.length === 3);
+ assert(result[0] === 10);
+ assert(result[1] === 20);
+ assert(result[2] === 30);
+}
+
+function baz(...rest) {
+ return rest;
+}
+function jaz(a, b, c) {
+ return baz.apply(null, Array.prototype.slice.call(arguments));
+}
+noInline(jaz);
+
+for (let i = 0; i < 50000; i++) {
+ let result = jaz(10, 20, 30);
+ assert(result.length === 3);
+ assert(result[0] === 10);
+ assert(result[1] === 20);
+ assert(result[2] === 30);
+}
</ins></span></pre>
</div>
</div>
</body>
</html>