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/Parser.h

    r186860 r186959  
    8282
    8383enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
    84 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    8584enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType };
    86 #else
    87 enum FunctionParseType { StandardFunctionParseType};
    88 #endif
     85enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock };
    8986enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
    90 enum FunctionParseMode {
    91     FunctionMode,
    92     GetterMode,
    93     SetterMode,
    94     MethodMode,
    95 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    96     ArrowFunctionMode
    97 #endif
    98 };
    9987enum DestructuringKind {
    10088    DestructureToVariables,
     
    538526public:
    539527    Parser(
    540         VM*, const SourceCode&, FunctionParameters*, const Identifier&,
    541         JSParserBuiltinMode, JSParserStrictMode, JSParserCodeType,
     528        VM*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, JSParserCodeType,
    542529        ConstructorKind defaultConstructorKind = ConstructorKind::None, ThisTDZMode = ThisTDZMode::CheckIfNeeded);
    543530    ~Parser();
    544531
    545532    template <class ParsedNode>
    546     std::unique_ptr<ParsedNode> parse(ParserError&);
     533    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, FunctionParseMode);
    547534
    548535    JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     
    740727
    741728    Parser();
    742     String parseInner();
     729    String parseInner(const Identifier&, FunctionParseMode);
    743730
    744731    void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&, VariableEnvironment&, CodeFeatures, int, const Vector<RefPtr<UniquedStringImpl>>&&);
     
    797784    }
    798785   
     786    ALWAYS_INLINE bool isEndOfArrowFunction()
     787    {
     788        return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator();
     789    }
     790   
     791    ALWAYS_INLINE bool isArrowFunctionParamters()
     792    {
    799793#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    800     ALWAYS_INLINE bool isEndOfArrowFunction()
    801     {
    802         return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator();
    803     }
    804    
    805     ALWAYS_INLINE bool isArrowFunctionParamters()
    806     {
    807794        bool isArrowFunction = false;
    808795       
     
    835822       
    836823        return isArrowFunction;
    837     }
     824#else
     825        return false;
    838826#endif
     827    }
    839828   
    840829    ALWAYS_INLINE unsigned tokenStart()
     
    947936    }
    948937
    949     template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode, FunctionParseType);
     938    template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
    950939    template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
    951940    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
     
    988977    template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
    989978    template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded);
    990     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionParseType);
    991     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
     979    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionBodyType, unsigned, FunctionParseMode);
     980    template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, unsigned&);
    992981    enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
    993982    template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType);
    994983    template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&);
    995 
    996 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    997     template <class TreeBuilder> TreeStatement parseArrowFunctionSingleExpressionBody(TreeBuilder&, FunctionParseType);
     984    template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&);
    998985    template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&);
    999 #endif
    1000 
    1001986    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, const Identifier&, int depth, JSToken, AssignmentContext);
    1002987    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
     
    10311016    }
    10321017   
    1033 
    1034 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    10351018    void setEndOfStatement()
    10361019    {
    10371020        m_lexer->setTokenPosition(&m_token);
    10381021    }
    1039 #endif
    10401022
    10411023    bool canRecurse()
     
    11091091    ParserArena m_parserArena;
    11101092    std::unique_ptr<LexerType> m_lexer;
     1093    FunctionParameters* m_parameters { nullptr };
    11111094   
    11121095    bool m_hasStackOverflow;
     
    11541137template <typename LexerType>
    11551138template <class ParsedNode>
    1156 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
     1139std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, FunctionParseMode parseMode)
    11571140{
    11581141    int errLine;
     
    11601143
    11611144    if (ParsedNode::scopeIsFunction)
    1162         m_lexer->setIsReparsing();
     1145        m_lexer->setIsReparsingFunction();
    11631146
    11641147    m_sourceElements = 0;
     
    11711154    unsigned startColumn = m_source->startColumn() - 1;
    11721155
    1173     String parseError = parseInner();
     1156    String parseError = parseInner(calleeName, parseMode);
    11741157
    11751158    int lineNumber = m_lexer->lineNumber();
     
    12011184                                    m_funcDeclarations,
    12021185                                    currentScope()->finalizeLexicalEnvironment(),
     1186                                    m_parameters,
    12031187                                    *m_source,
    12041188                                    m_features,
     
    12341218template <class ParsedNode>
    12351219std::unique_ptr<ParsedNode> parse(
    1236     VM* vm, const SourceCode& source, FunctionParameters* parameters,
     1220    VM* vm, const SourceCode& source,
    12371221    const Identifier& name, JSParserBuiltinMode builtinMode,
    12381222    JSParserStrictMode strictMode, JSParserCodeType codeType,
    1239     ParserError& error, JSTextPosition* positionBeforeLastNewline = 0,
    1240     ConstructorKind defaultConstructorKind = ConstructorKind::None, ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded)
     1223    ParserError& error, JSTextPosition* positionBeforeLastNewline = nullptr,
     1224    FunctionParseMode parseMode = NotAFunctionMode, ConstructorKind defaultConstructorKind = ConstructorKind::None,
     1225    ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded)
    12411226{
    12421227    SamplingRegion samplingRegion("Parsing");
     
    12441229    ASSERT(!source.provider()->source().isNull());
    12451230    if (source.provider()->source().is8Bit()) {
    1246         Parser<Lexer<LChar>> parser(vm, source, parameters, name, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
    1247         std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error);
     1231        Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
     1232        std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode);
    12481233        if (positionBeforeLastNewline)
    12491234            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     
    12571242    }
    12581243    ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string");
    1259     Parser<Lexer<UChar>> parser(vm, source, parameters, name, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
    1260     std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error);
     1244    Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
     1245    std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode);
    12611246    if (positionBeforeLastNewline)
    12621247        *positionBeforeLastNewline = parser.positionBeforeLastNewline();
Note: See TracChangeset for help on using the changeset viewer.