Ignore:
Timestamp:
Jul 17, 2015, 11:48:30 AM (10 years ago)
Author:
[email protected]
Message:

Function parameters should be parsed in the same parser arena as the function body
https://bugs.webkit.org/show_bug.cgi?id=145995

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

This patch changes how functions are parsed in JSC. A function's
parameters are now parsed in the same arena as the function itself.
This allows us to arena allocate all destructuring AST nodes and
the FunctionParameters node. This will help make implementing ES6
default parameter values sane.

A source code that represents a function now includes the text of the function's
parameters. The starting offset is at the opening parenthesis of the parameter
list or at the starting character of the identifier for arrow functions that
have single arguments and don't start with parenthesis.

For example:

"function (param1, param2) { ... }"


| This offset used to be the starting offset of a function's SourceCode


| This is the new starting offset for a function's SourceCode.

This requires us to change how some offsets are calculated
and also requires us to report some different line numbers for internal
metrics that use a SourceCode's starting line and column numbers.

This patch also does a bit of cleanup with regards to how
functions are parsed in general (especially arrow functions).
It removes some unnecessary #ifdefs and the likes for arrow
to make things clearer and more deliberate.

  • API/JSScriptRef.cpp:

(parseScript):

  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createExecutableInternal):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::visitChildren):
(JSC::UnlinkedFunctionExecutable::parameterCount): Deleted.

  • bytecode/UnlinkedCodeBlock.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::DestructuringAssignmentNode::emitBytecode):
(JSC::assignDefaultValueIfUndefined):
(JSC::ArrayPatternNode::collectBoundIdentifiers):
(JSC::DestructuringPatternNode::~DestructuringPatternNode): Deleted.

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createClassExpr):
(JSC::ASTBuilder::createFunctionExpr):
(JSC::ASTBuilder::createFunctionBody):
(JSC::ASTBuilder::createArrowFunctionExpr):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createElementList):
(JSC::ASTBuilder::createFormalParameterList):
(JSC::ASTBuilder::appendParameter):
(JSC::ASTBuilder::createClause):
(JSC::ASTBuilder::createClauseList):
(JSC::ASTBuilder::createFuncDeclStatement):
(JSC::ASTBuilder::createForInLoop):
(JSC::ASTBuilder::createForOfLoop):
(JSC::ASTBuilder::isResolve):
(JSC::ASTBuilder::createDestructuringAssignment):
(JSC::ASTBuilder::createArrayPattern):
(JSC::ASTBuilder::appendArrayPatternSkipEntry):
(JSC::ASTBuilder::appendArrayPatternEntry):
(JSC::ASTBuilder::appendArrayPatternRestEntry):
(JSC::ASTBuilder::finishArrayPattern):
(JSC::ASTBuilder::createObjectPattern):
(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::createBindingLocation):
(JSC::ASTBuilder::setEndOffset):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::Lexer):
(JSC::Lexer<T>::nextTokenIsColon):
(JSC::Lexer<T>::setTokenPosition):
(JSC::Lexer<T>::lex):
(JSC::Lexer<T>::clear):

  • parser/Lexer.h:

(JSC::Lexer::setIsReparsingFunction):
(JSC::Lexer::isReparsingFunction):
(JSC::Lexer::lineNumber):
(JSC::Lexer::setIsReparsing): Deleted.
(JSC::Lexer::isReparsing): Deleted.

  • parser/NodeConstructors.h:

(JSC::TryNode::TryNode):
(JSC::FunctionParameters::FunctionParameters):
(JSC::FuncExprNode::FuncExprNode):
(JSC::FuncDeclNode::FuncDeclNode):
(JSC::ArrayPatternNode::ArrayPatternNode):
(JSC::ObjectPatternNode::ObjectPatternNode):
(JSC::BindingNode::BindingNode):
(JSC::DestructuringAssignmentNode::DestructuringAssignmentNode):
(JSC::ParameterNode::ParameterNode): Deleted.
(JSC::ArrayPatternNode::create): Deleted.
(JSC::ObjectPatternNode::create): Deleted.
(JSC::BindingNode::create): Deleted.

  • parser/Nodes.cpp:

(JSC::ProgramNode::ProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionBodyNode::FunctionBodyNode):
(JSC::FunctionBodyNode::finishParsing):
(JSC::FunctionNode::FunctionNode):
(JSC::FunctionNode::finishParsing):
(JSC::FunctionParameters::create): Deleted.
(JSC::FunctionParameters::FunctionParameters): Deleted.
(JSC::FunctionParameters::~FunctionParameters): Deleted.

  • parser/Nodes.h:

(JSC::ProgramNode::startColumn):
(JSC::ProgramNode::endColumn):
(JSC::EvalNode::startColumn):
(JSC::EvalNode::endColumn):
(JSC::FunctionParameters::size):
(JSC::FunctionParameters::at):
(JSC::FunctionParameters::append):
(JSC::FuncExprNode::body):
(JSC::DestructuringPatternNode::~DestructuringPatternNode):
(JSC::DestructuringPatternNode::isBindingNode):
(JSC::DestructuringPatternNode::emitDirectBinding):
(JSC::ArrayPatternNode::appendIndex):
(JSC::ObjectPatternNode::appendEntry):
(JSC::BindingNode::boundProperty):
(JSC::BindingNode::divotStart):
(JSC::BindingNode::divotEnd):
(JSC::DestructuringAssignmentNode::bindings):
(JSC::FuncDeclNode::body):
(JSC::ParameterNode::pattern): Deleted.
(JSC::ParameterNode::nextParam): Deleted.
(JSC::FunctionParameters::patterns): Deleted.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::~Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::allowAutomaticSemicolon):
(JSC::Parser<LexerType>::parseSourceElements):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements):
(JSC::Parser<LexerType>::tryParseDestructuringPatternExpression):
(JSC::Parser<LexerType>::parseSwitchClauses):
(JSC::Parser<LexerType>::parseSwitchDefaultClause):
(JSC::Parser<LexerType>::parseBlockStatement):
(JSC::Parser<LexerType>::parseStatement):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::Parser<LexerType>::parseFunctionBody):
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::parseArrowFunctionExpression):
(JSC::operatorString):
(JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody): Deleted.

  • parser/Parser.h:

(JSC::Parser::positionBeforeLastNewline):
(JSC::Parser::locationBeforeLastToken):
(JSC::Parser::findCachedFunctionInfo):
(JSC::Parser::isofToken):
(JSC::Parser::isEndOfArrowFunction):
(JSC::Parser::isArrowFunctionParamters):
(JSC::Parser::tokenStart):
(JSC::Parser::isLETMaskedAsIDENT):
(JSC::Parser::autoSemiColon):
(JSC::Parser::setEndOfStatement):
(JSC::Parser::canRecurse):
(JSC::Parser<LexerType>::parse):
(JSC::parse):

  • parser/ParserFunctionInfo.h:
  • parser/ParserModes.h:

(JSC::functionNameIsInScope):

  • parser/SourceCode.h:

(JSC::makeSource):
(JSC::SourceCode::subExpression):
(JSC::SourceCode::subArrowExpression): Deleted.

  • parser/SourceProviderCache.h:

(JSC::SourceProviderCache::get):

  • parser/SourceProviderCacheItem.h:

(JSC::SourceProviderCacheItem::endFunctionToken):
(JSC::SourceProviderCacheItem::usedVariables):
(JSC::SourceProviderCacheItem::writtenVariables):
(JSC::SourceProviderCacheItem::SourceProviderCacheItem):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::SyntaxChecker):
(JSC::SyntaxChecker::createClassExpr):
(JSC::SyntaxChecker::createFunctionExpr):
(JSC::SyntaxChecker::createFunctionBody):
(JSC::SyntaxChecker::createArrowFunctionExpr):
(JSC::SyntaxChecker::setFunctionNameStart):
(JSC::SyntaxChecker::createArguments):
(JSC::SyntaxChecker::createPropertyList):
(JSC::SyntaxChecker::createElementList):
(JSC::SyntaxChecker::createFormalParameterList):
(JSC::SyntaxChecker::appendParameter):
(JSC::SyntaxChecker::createClause):
(JSC::SyntaxChecker::createClauseList):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):

  • runtime/Completion.cpp:

(JSC::checkSyntax):

  • runtime/Executable.cpp:

(JSC::ProgramExecutable::checkSyntax):

  • tests/controlFlowProfiler/conditional-expression.js:

(testConditionalFunctionCall):

LayoutTests:

  • fast/profiler/anonymous-event-handler-expected.txt:
  • fast/profiler/anonymous-function-called-from-different-contexts-expected.txt:
  • fast/profiler/anonymous-function-calls-built-in-functions-expected.txt:
  • fast/profiler/anonymous-function-calls-eval-expected.txt:
  • fast/profiler/anonymous-functions-with-display-names-expected.txt:
  • fast/profiler/apply-expected.txt:
  • fast/profiler/built-in-function-calls-anonymous-expected.txt:
  • fast/profiler/built-in-function-calls-user-defined-function-expected.txt:
  • fast/profiler/call-expected.txt:
  • fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt:
  • fast/profiler/compare-multiple-profiles-expected.txt:
  • fast/profiler/constructor-expected.txt:
  • fast/profiler/dead-time-expected.txt:
  • fast/profiler/document-dot-write-expected.txt:
  • fast/profiler/event-handler-expected.txt:
  • fast/profiler/execution-context-and-eval-on-same-line-expected.txt:
  • fast/profiler/inline-event-handler-expected.txt:
  • fast/profiler/many-calls-in-the-same-scope-expected.txt:
  • fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt:
  • fast/profiler/multiple-and-different-scoped-function-calls-expected.txt:
  • fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt:
  • fast/profiler/multiple-frames-expected.txt:
  • fast/profiler/named-functions-with-display-names-expected.txt:
  • fast/profiler/nested-anonymous-functon-expected.txt:
  • fast/profiler/nested-start-and-stop-profiler-expected.txt:
  • fast/profiler/one-execution-context-expected.txt:
  • fast/profiler/profile-calls-in-included-file-expected.txt:
  • fast/profiler/profile-with-no-title-expected.txt:
  • fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt:
  • fast/profiler/profiling-from-a-nested-location-expected.txt:
  • fast/profiler/simple-event-call-expected.txt:
  • fast/profiler/simple-no-level-change-expected.txt:
  • fast/profiler/start-and-stop-profiler-multiple-times-expected.txt:
  • fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt:
  • fast/profiler/stop-profiling-after-setTimeout-expected.txt:
  • fast/profiler/stop-then-function-call-expected.txt:
  • fast/profiler/two-execution-contexts-expected.txt:
  • fast/profiler/user-defined-function-calls-built-in-functions-expected.txt:
  • fast/profiler/window-dot-eval-expected.txt:
  • js/dom/script-start-end-locations-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r186860 r186959  
    118118// ------------------------------ ProgramNode -----------------------------
    119119
    120 ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     120ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants)
    121121    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants)
    122122    , m_startColumn(startColumn)
     
    132132// ------------------------------ EvalNode -----------------------------
    133133
    134 EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     134EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants)
    135135    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants)
    136136    , m_endColumn(endColumn)
     
    140140// ------------------------------ FunctionBodyNode -----------------------------
    141141
    142 Ref<FunctionParameters> FunctionParameters::create(ParameterNode* firstParameter)
    143 {
    144     unsigned parameterCount = 0;
    145     for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
    146         ++parameterCount;
    147 
    148     size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(DestructuringPatternNode*) * parameterCount;
    149     void* slot = fastMalloc(objectSize);
    150     return adoptRef(*new (slot) FunctionParameters(firstParameter, parameterCount));
    151 }
    152 
    153 FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size)
    154     : m_size(size)
    155 {
    156     unsigned i = 0;
    157     for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) {
    158         auto pattern = parameter->pattern();
    159         pattern->ref();
    160         patterns()[i++] = pattern;
    161     }
    162 }
    163 
    164 FunctionParameters::~FunctionParameters()
    165 {
    166     for (unsigned i = 0; i < m_size; ++i)
    167         patterns()[i]->deref();
    168 }
    169 
    170142FunctionBodyNode::FunctionBodyNode(
    171143    ParserArena&, const JSTokenLocation& startLocation,
    172144    const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
    173     int functionKeywordStart, int functionNameStart, int parametersStart,
    174     bool isInStrictContext, ConstructorKind constructorKind)
     145    int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext,
     146    ConstructorKind constructorKind, unsigned parameterCount, FunctionParseMode mode)
    175147        : StatementNode(endLocation)
    176148        , m_startColumn(startColumn)
     
    180152        , m_parametersStart(parametersStart)
    181153        , m_startStartOffset(startLocation.startOffset)
     154        , m_parameterCount(parameterCount)
     155        , m_parseMode(mode)
    182156        , m_isInStrictContext(isInStrictContext)
    183157        , m_constructorKind(static_cast<unsigned>(constructorKind))
     
    186160}
    187161
    188 void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, enum FunctionMode functionMode)
     162void FunctionBodyNode::finishParsing(const SourceCode& source, const Identifier& ident, enum FunctionMode functionMode)
    189163{
    190164    m_source = source;
    191     m_parameters = FunctionParameters::create(firstParameter);
    192165    m_ident = ident;
    193166    m_functionMode = functionMode;
     
    202175// ------------------------------ FunctionNode -----------------------------
    203176
    204 FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
     177FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
    205178    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, funcStack, lexicalVariables, features, numConstants)
     179    , m_parameters(parameters)
    206180    , m_startColumn(startColumn)
    207181    , m_endColumn(endColumn)
     
    209183}
    210184
    211 void FunctionNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident, enum FunctionMode functionMode)
     185void FunctionNode::finishParsing(const Identifier& ident, enum FunctionMode functionMode)
    212186{
    213187    ASSERT(!source().isNull());
    214     m_parameters = parameters;
    215188    m_ident = ident;
    216189    m_functionMode = functionMode;
Note: See TracChangeset for help on using the changeset viewer.