Diff
Modified: releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-04-03 09:59:33 UTC (rev 214753)
@@ -1,5 +1,21 @@
2017-03-15 Yusuke Suzuki <utatane....@gmail.com>
+ [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 <utatane....@gmail.com>
+
[DFG] ToString operation should have fixup for primitives to say this node does not have side effects
https://bugs.webkit.org/show_bug.cgi?id=169544
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-inlining.js (0 => 214753)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-inlining.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-inlining.js 2017-04-03 09:59:33 UTC (rev 214753)
@@ -0,0 +1,24 @@
+(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 < 1e4; ++i) {
+ shouldBe(a(), 85);
+ shouldBe(a(33), 76);
+ shouldBe(a(33, 22), 55);
+}
+}());
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-non-inlining.js (0 => 214753)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-non-inlining.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/function-with-defaults-non-inlining.js 2017-04-03 09:59:33 UTC (rev 214753)
@@ -0,0 +1,25 @@
+(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 < 1e4; ++i) {
+ shouldBe(a(), 85);
+ shouldBe(a(33), 76);
+ shouldBe(a(33, 22), 55);
+}
+}());
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-04-03 09:59:33 UTC (rev 214753)
@@ -1,5 +1,73 @@
2017-03-15 Yusuke Suzuki <utatane....@gmail.com>
+ [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<LexerType>::isArrowFunctionParameters):
+ (JSC::Parser<LexerType>::parseGeneratorFunctionSourceElements):
+ (JSC::Parser<LexerType>::parseAsyncFunctionSourceElements):
+ (JSC::Parser<LexerType>::parseFormalParameters):
+ (JSC::Parser<LexerType>::parseFunctionBody):
+ (JSC::Parser<LexerType>::parseFunctionParameters):
+ (JSC::Parser<LexerType>::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 <utatane....@gmail.com>
+
[DFG] ToString operation should have fixup for primitives to say this node does not have side effects
https://bugs.webkit.org/show_bug.cgi?id=169544
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -88,7 +88,6 @@
, m_typeProfilingStartOffset(node->functionKeywordStart())
, m_typeProfilingEndOffset(node->startStartOffset() + node->source().length() - 1)
, m_parameterCount(node->parameterCount())
- , m_functionLength(node->functionLength())
, m_features(0)
, m_sourceParseMode(node->parseMode())
, m_isInStrictContext(node->isInStrictContext())
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -77,7 +77,6 @@
void setEcmaName(const Identifier& name) { m_ecmaName = name; }
const Identifier& inferredName() const { return m_inferredName; }
unsigned parameterCount() const { return m_parameterCount; }; // Excluding 'this'!
- unsigned functionLength() const { return m_functionLength; }
SourceParseMode parseMode() const { return static_cast<SourceParseMode>(m_sourceParseMode); };
const SourceCode& classSource() const { return m_classSource; };
@@ -159,7 +158,6 @@
unsigned m_typeProfilingStartOffset;
unsigned m_typeProfilingEndOffset;
unsigned m_parameterCount;
- unsigned m_functionLength;
CodeFeatures m_features;
SourceParseMode m_sourceParseMode;
unsigned m_isInStrictContext : 1;
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -254,15 +254,8 @@
// 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.
- bool isSimpleParameterList = true;
// If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope.
- for (size_t i = 0; i < parameters.size(); i++) {
- std::pair<DestructuringPatternNode*, ExpressionNode*> parameter = parameters.at(i);
- bool hasDefaultParameterValue = !!parameter.second;
- auto pattern = parameter.first;
- bool isSimpleParameter = !hasDefaultParameterValue && pattern->isBindingNode();
- isSimpleParameterList &= isSimpleParameter;
- }
+ bool isSimpleParameterList = parameters.isSimpleParameterList();
SourceParseMode parseMode = codeBlock->parseMode();
@@ -983,10 +976,12 @@
std::pair<DestructuringPatternNode*, ExpressionNode*> parameter = parameters.at(i);
if (parameter.first->isRestParameter())
continue;
- RefPtr<RegisterID> parameterValue = ®isterFor(virtualRegisterForArgument(1 + i));
- emitMove(temp.get(), parameterValue.get());
+ if ((i + 1) < m_parameters.size())
+ emitMove(temp.get(), &m_parameters[i + 1]);
+ else
+ emitGetArgument(temp.get(), i);
if (parameter.second) {
- RefPtr<RegisterID> condition = emitIsUndefined(newTemporary(), parameterValue.get());
+ RefPtr<RegisterID> condition = emitIsUndefined(newTemporary(), temp.get());
Ref<Label> skipDefaultParameterBecauseNotUndefined = newLabel();
emitJumpIfFalse(condition.get(), skipDefaultParameterBecauseNotUndefined.get());
emitNode(temp.get(), parameter.second);
@@ -1103,7 +1098,8 @@
RegisterID* BytecodeGenerator::initializeNextParameter()
{
VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters());
- RegisterID& parameter = registerFor(reg);
+ m_parameters.grow(m_parameters.size() + 1);
+ auto& parameter = registerFor(reg);
parameter.setIndex(reg.offset());
m_codeBlock->addParameter();
return ¶meter;
@@ -1113,14 +1109,23 @@
{
// Make sure the code block knows about all of our parameters, and make sure that parameters
// needing destructuring are noted.
- m_parameters.grow(parameters.size() + 1); // reserve space for "this"
m_thisRegister.setIndex(initializeNextParameter()->index()); // this
+
+ bool nonSimpleArguments = false;
for (unsigned i = 0; i < parameters.size(); ++i) {
- auto pattern = parameters.at(i).first;
+ auto parameter = parameters.at(i);
+ auto pattern = parameter.first;
if (pattern->isRestParameter()) {
RELEASE_ASSERT(!m_restParameter);
m_restParameter = static_cast<RestParameterNode*>(pattern);
- } else
+ nonSimpleArguments = true;
+ continue;
+ }
+ if (parameter.second) {
+ nonSimpleArguments = true;
+ continue;
+ }
+ if (!nonSimpleArguments)
initializeNextParameter();
}
}
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -639,7 +639,6 @@
RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property);
- RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -3463,13 +3463,13 @@
void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
if (generator.vm()->typeProfiler()) {
- for (size_t i = 0; i < m_parameters->size(); i++) {
- // Destructuring parameters are handled in destructuring nodes.
- if (!m_parameters->at(i).first->isBindingNode())
- continue;
- BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
- RegisterID reg(CallFrame::argumentOffset(i));
- generator.emitProfileType(®, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
+ // If the parameter list is non simple one, it is handled in bindValue's code.
+ if (m_parameters->isSimpleParameterList()) {
+ for (size_t i = 0; i < m_parameters->size(); i++) {
+ BindingNode* bindingNode = static_cast<BindingNode*>(m_parameters->at(i).first);
+ RegisterID reg(CallFrame::argumentOffset(i));
+ generator.emitProfileType(®, ProfileTypeBytecodeFunctionArgument, bindingNode->divotStart(), bindingNode->divotEnd());
+ }
}
}
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -1424,15 +1424,6 @@
return UINT_MAX;
}
- // 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<int>(executable->parameterCount()) + 1 > argumentCountIncludingThis) {
- if (verbose)
- dataLog(" Failing because of arity mismatch.\n");
- return UINT_MAX;
- }
-
// Do we have a code block, and does the code block's size match the heuristics/requirements for
// being an inline candidate? We might not have a code block (1) if code was thrown away,
// (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
@@ -1446,6 +1437,16 @@
dataLog(" Failing because no code block available.\n");
return UINT_MAX;
}
+
+ // 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->numParameters() > argumentCountIncludingThis) {
+ if (verbose)
+ dataLog(" Failing because of arity mismatch.\n");
+ return UINT_MAX;
+ }
+
CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
codeBlock, kind, callee.isClosureCall());
if (verbose) {
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/ASTBuilder.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/ASTBuilder.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/ASTBuilder.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -427,7 +427,7 @@
unsigned startColumn, unsigned endColumn, int functionKeywordStart,
int functionNameStart, int parametersStart, bool inStrictContext,
ConstructorKind constructorKind, SuperBinding superBinding,
- unsigned parameterCount, unsigned functionLength,
+ unsigned parameterCount,
SourceParseMode mode, bool isArrowFunctionBodyExpression)
{
return new (m_parserArena) FunctionMetadataNode(
@@ -434,7 +434,7 @@
m_parserArena, startLocation, endLocation, startColumn, endColumn,
functionKeywordStart, functionNameStart, parametersStart,
inStrictContext, constructorKind, superBinding,
- parameterCount, functionLength, mode, isArrowFunctionBodyExpression);
+ parameterCount, mode, isArrowFunctionBodyExpression);
}
ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -135,7 +135,7 @@
ParserArena&, const JSTokenLocation& startLocation,
const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext,
- ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, unsigned functionLength, SourceParseMode mode, bool isArrowFunctionBodyExpression)
+ ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
: Node(endLocation)
, m_startColumn(startColumn)
, m_endColumn(endColumn)
@@ -144,7 +144,6 @@
, m_parametersStart(parametersStart)
, m_startStartOffset(startLocation.startOffset)
, m_parameterCount(parameterCount)
- , m_functionLength(functionLength)
, m_parseMode(mode)
, m_isInStrictContext(isInStrictContext)
, m_superBinding(static_cast<unsigned>(superBinding))
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Nodes.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -1867,22 +1867,6 @@
ModuleNameNode* m_moduleName { nullptr };
};
- class FunctionParameters : public ParserArenaDeletable {
- public:
- FunctionParameters();
- ALWAYS_INLINE unsigned size() const { return m_patterns.size(); }
- ALWAYS_INLINE std::pair<DestructuringPatternNode*, ExpressionNode*> 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<std::pair<DestructuringPatternNode*, ExpressionNode*>, 3> m_patterns;
- };
-
class FunctionMetadataNode final : public Node, public ParserArenaDeletable {
public:
using ParserArenaDeletable::operator new;
@@ -1891,7 +1875,7 @@
ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end,
unsigned startColumn, unsigned endColumn, int functionKeywordStart,
int functionNameStart, int parametersStart, bool isInStrictContext,
- ConstructorKind, SuperBinding, unsigned parameterCount, unsigned functionLength,
+ ConstructorKind, SuperBinding, unsigned parameterCount,
SourceParseMode, bool isArrowFunctionBodyExpression);
void finishParsing(const SourceCode&, const Identifier&, FunctionMode);
@@ -1911,7 +1895,6 @@
unsigned startColumn() const { return m_startColumn; }
unsigned endColumn() const { return m_endColumn; }
unsigned parameterCount() const { return m_parameterCount; }
- unsigned functionLength() const { return m_functionLength; }
SourceParseMode parseMode() const { return m_parseMode; }
void setEndPosition(JSTextPosition);
@@ -1948,7 +1931,6 @@
SourceCode m_classSource;
int m_startStartOffset;
unsigned m_parameterCount;
- unsigned m_functionLength;
int m_lastLine;
SourceParseMode m_parseMode;
unsigned m_isInStrictContext : 1;
@@ -2228,6 +2210,36 @@
ExpressionNode* m_initializer;
};
+ class FunctionParameters : public ParserArenaDeletable {
+ public:
+ FunctionParameters();
+ ALWAYS_INLINE unsigned size() const { return m_patterns.size(); }
+ ALWAYS_INLINE std::pair<DestructuringPatternNode*, ExpressionNode*> 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 && pattern->isBindingNode();
+ m_isSimpleParameterList &= isSimpleParameter;
+
+ m_patterns.append(std::make_pair(pattern, defaultValue));
+ }
+ ALWAYS_INLINE bool isSimpleParameterList() const { return m_isSimpleParameterList; }
+
+ private:
+
+ Vector<std::pair<DestructuringPatternNode*, ExpressionNode*>, 3> m_patterns;
+ bool m_isSimpleParameterList { true };
+ };
+
class FuncDeclNode : public StatementNode {
public:
FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -286,9 +286,8 @@
fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
unsigned parametersCount = 0;
- unsigned functionLength = 0;
bool isArrowFunctionParameterList = true;
- isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount, functionLength) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
+ isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
propagateError();
popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
}
@@ -465,7 +464,7 @@
failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
}
- info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, SourceParseMode::GeneratorBodyMode, false);
+ info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
info.endLine = tokenLine();
info.endOffset = m_token.m_data.offset;
@@ -516,7 +515,7 @@
}
popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
}
- info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, innerParseMode, isArrowFunctionBodyExpression);
+ info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
info.endLine = tokenLine();
info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
@@ -1825,7 +1824,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount, unsigned& functionLength)
+template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount)
{
#define failIfDuplicateIfViolation() \
if (duplicateParameter) {\
@@ -1839,6 +1838,7 @@
bool hasDestructuringPattern = false;
bool isRestParameter = false;
const Identifier* duplicateParameter = nullptr;
+ unsigned restParameterStart = 0;
do {
TreeDestructuringPattern parameter = 0;
TreeExpression defaultValue = 0;
@@ -1851,7 +1851,7 @@
semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Can't use 'await' as a parameter name in an async function");
TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
propagateError();
- parameter = context.createRestParameter(destructuringPattern, parameterCount);
+ parameter = context.createRestParameter(destructuringPattern, restParameterStart);
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
@@ -1868,9 +1868,9 @@
currentScope()->setHasNonSimpleParameterList();
context.appendParameter(list, parameter, defaultValue);
if (!isRestParameter) {
- parameterCount++;
+ restParameterStart++;
if (!hasDefaultParameterValues)
- functionLength++;
+ parameterCount++;
}
} while (!isRestParameter && consume(COMMA));
@@ -1881,7 +1881,7 @@
template <typename LexerType>
template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
- ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, unsigned functionLength, SourceParseMode parseMode)
+ ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
{
bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
if (!isArrowFunctionBodyExpression) {
@@ -1889,7 +1889,7 @@
if (match(CLOSEBRACE)) {
unsigned endColumn = tokenColumn();
SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
- return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
+ return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
}
}
@@ -1908,7 +1908,7 @@
}
unsigned endColumn = tokenColumn();
SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
- return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
+ return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
}
static const char* stringForFunctionMode(SourceParseMode mode)
@@ -1962,16 +1962,14 @@
if (match(CLOSEPAREN)) {
functionInfo.parameterCount = 0;
- functionInfo.functionLength = 0;
} else {
bool isArrowFunction = true;
- failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+ failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
}
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
} else {
functionInfo.parameterCount = 1;
- functionInfo.functionLength = 1;
auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
failIfFalse(parameter, "Cannot parse parameter pattern");
context.appendParameter(parameterList, parameter, 0);
@@ -1989,7 +1987,6 @@
if (mode == SourceParseMode::GetterMode) {
consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
functionInfo.parameterCount = 0;
- functionInfo.functionLength = 0;
} else if (mode == SourceParseMode::SetterMode) {
failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
const Identifier* duplicateParameter = nullptr;
@@ -2003,17 +2000,15 @@
currentScope()->setHasNonSimpleParameterList();
}
context.appendParameter(parameterList, parameter, defaultValue);
- functionInfo.parameterCount = 1;
- functionInfo.functionLength = defaultValue ? 0 : 1;
+ functionInfo.parameterCount = defaultValue ? 0 : 1;
failIfTrue(match(COMMA), "setter functions must have one parameter");
consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
} else {
if (match(CLOSEPAREN)) {
functionInfo.parameterCount = 0;
- functionInfo.functionLength = 0;
} else {
bool isArrowFunction = false;
- failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+ failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
}
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
}
@@ -2115,11 +2110,10 @@
startLocation, endLocation, startColumn, bodyEndColumn,
functionKeywordStart, functionNameStart, parametersStart,
cachedInfo->strictMode, constructorKind, functionSuperBinding,
- cachedInfo->parameterCount, cachedInfo->functionLength,
+ cachedInfo->parameterCount,
mode, functionBodyType == ArrowFunctionBodyExpression);
functionInfo.endOffset = cachedInfo->endFunctionOffset;
functionInfo.parameterCount = cachedInfo->parameterCount;
- functionInfo.functionLength = cachedInfo->functionLength;
functionScope->restoreFromSourceProviderCache(cachedInfo);
popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
@@ -2287,7 +2281,7 @@
});
auto performParsingFunctionBody = [&] {
- return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, functionInfo.functionLength, mode);
+ return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
};
if (isGeneratorOrAsyncFunctionWrapperParseMode(mode)) {
@@ -2342,10 +2336,10 @@
// Any future reparsing can then skip the function.
// For arrow function is 8 = x=>x + 4 symbols;
// For ordinary function is 16 = function(){} + 4 symbols
- const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
+ const int minimumSourceLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
std::unique_ptr<SourceProviderCacheItem> newInfo;
- int functionLength = functionInfo.endOffset - functionInfo.startOffset;
- if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
+ int sourceLength = functionInfo.endOffset - functionInfo.startOffset;
+ if (TreeBuilder::CanUseFunctionCache && m_functionCache && sourceLength > minimumSourceLengthToCache) {
SourceProviderCacheItemCreationParameters parameters;
parameters.endFunctionOffset = functionInfo.endOffset;
parameters.functionNameStart = functionNameStart;
@@ -2354,7 +2348,6 @@
parameters.lastTokenEndOffset = location.endOffset;
parameters.lastTokenLineStartOffset = location.lineStartOffset;
parameters.parameterCount = functionInfo.parameterCount;
- parameters.functionLength = functionInfo.functionLength;
parameters.constructorKind = constructorKind;
parameters.expectedSuperBinding = expectedSuperBinding;
if (functionBodyType == ArrowFunctionBodyExpression) {
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/Parser.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -1532,8 +1532,8 @@
template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod);
template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, bool isClassProperty);
- template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, unsigned, SourceParseMode);
- template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, unsigned&, unsigned&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode);
+ template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, unsigned&);
enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer);
template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/SyntaxChecker.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/SyntaxChecker.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/parser/SyntaxChecker.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -187,7 +187,7 @@
ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
ExpressionType createGeneratorFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, const Identifier&) { return FunctionExpr; }
ExpressionType createAsyncFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
- int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, int, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
+ int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
ExpressionType createMethodDefinition(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
void setFunctionNameStart(int, int) { }
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/FunctionExecutable.h (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/FunctionExecutable.h 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/FunctionExecutable.h 2017-04-03 09:59:33 UTC (rev 214753)
@@ -145,7 +145,6 @@
const Identifier& ecmaName() { return m_unlinkedExecutable->ecmaName(); }
const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
unsigned parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
- unsigned functionLength() const { return m_unlinkedExecutable->functionLength(); }
SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
JSParserScriptMode scriptMode() const { return m_unlinkedExecutable->scriptMode(); }
const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); }
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSFunction.cpp (214752 => 214753)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSFunction.cpp 2017-04-03 08:15:27 UTC (rev 214752)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSFunction.cpp 2017-04-03 09:59:33 UTC (rev 214753)
@@ -104,7 +104,7 @@
{
JSFunction* function = create(vm, executable, globalObject);
function->putDirect(vm, vm.propertyNames->name, jsString(&vm, executable->name().string()), ReadOnly | DontEnum);
- function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->functionLength()), ReadOnly | DontEnum);
+ function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), ReadOnly | DontEnum);
return function;
}
@@ -112,7 +112,7 @@
{
JSFunction* function = create(vm, executable, globalObject);
function->putDirect(vm, vm.propertyNames->name, jsString(&vm, name), ReadOnly | DontEnum);
- function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->functionLength()), ReadOnly | DontEnum);
+ function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), ReadOnly | DontEnum);
return function;
}
@@ -623,7 +623,7 @@
ASSERT(!hasReifiedLength());
ASSERT(!isHostFunction());
- JSValue initialValue = jsNumber(jsExecutable()->functionLength());
+ JSValue initialValue = jsNumber(jsExecutable()->parameterCount());
unsigned initialAttributes = DontEnum | ReadOnly;
const Identifier& identifier = vm.propertyNames->length;
putDirect(vm, identifier, initialValue, initialAttributes);