Title: [195484] trunk/Source/_javascript_Core
Revision
195484
Author
[email protected]
Date
2016-01-22 14:52:42 -0800 (Fri, 22 Jan 2016)

Log Message

Current implementation of Parser::createSavePoint is a foot gun
https://bugs.webkit.org/show_bug.cgi?id=153293

Reviewed by Oliver Hunt.

The previous use of SavePoint (up until this patch)
really meant that we're saving the LexerState. This
was so poorly named that it was being misused all over
our parser. For example, anything that parsed an
AssignmentExpression between saving/restoring really
wanted to save both Lexer state and Parser state.

This patch changes SavePoint to mean save all the
state. The old SavePoint is renamed to LexerState with
corresponding internal<Save/Restore>LexerState functions.
The old <save/restore>State() function is renamed to
internal<Save/Restore>ParserState().

* parser/Parser.cpp:
(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::isArrowFunctionParameters):
(JSC::Parser<LexerType>::parseSourceElements):
(JSC::Parser<LexerType>::declareRestOrNormalParameter):
(JSC::Parser<LexerType>::parseAssignmentElement):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseForStatement):
(JSC::Parser<LexerType>::parseStatement):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseExpression):
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parseYieldExpression):
(JSC::Parser<LexerType>::parseConditionalExpression):
(JSC::Parser<LexerType>::parseBinaryExpression):
(JSC::Parser<LexerType>::parseObjectLiteral):
(JSC::Parser<LexerType>::parseStrictObjectLiteral):
(JSC::Parser<LexerType>::parseArrayLiteral):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::parseUnaryExpression):
* parser/Parser.h:
(JSC::Parser::hasError):
(JSC::Parser::internalSaveParserState):
(JSC::Parser::restoreParserState):
(JSC::Parser::internalSaveLexerState):
(JSC::Parser::restoreLexerState):
(JSC::Parser::createSavePointForError):
(JSC::Parser::createSavePoint):
(JSC::Parser::restoreSavePointWithError):
(JSC::Parser::restoreSavePoint):
(JSC::Parser::saveState): Deleted.
(JSC::Parser::restoreState): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (195483 => 195484)


--- trunk/Source/_javascript_Core/ChangeLog	2016-01-22 22:50:41 UTC (rev 195483)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-01-22 22:52:42 UTC (rev 195484)
@@ -1,3 +1,60 @@
+2016-01-22  Saam barati  <[email protected]>
+
+        Current implementation of Parser::createSavePoint is a foot gun
+        https://bugs.webkit.org/show_bug.cgi?id=153293
+
+        Reviewed by Oliver Hunt.
+
+        The previous use of SavePoint (up until this patch)
+        really meant that we're saving the LexerState. This
+        was so poorly named that it was being misused all over
+        our parser. For example, anything that parsed an
+        AssignmentExpression between saving/restoring really
+        wanted to save both Lexer state and Parser state.
+
+        This patch changes SavePoint to mean save all the
+        state. The old SavePoint is renamed to LexerState with
+        corresponding internal<Save/Restore>LexerState functions.
+        The old <save/restore>State() function is renamed to
+        internal<Save/Restore>ParserState().
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::Parser):
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::isArrowFunctionParameters):
+        (JSC::Parser<LexerType>::parseSourceElements):
+        (JSC::Parser<LexerType>::declareRestOrNormalParameter):
+        (JSC::Parser<LexerType>::parseAssignmentElement):
+        (JSC::Parser<LexerType>::parseDestructuringPattern):
+        (JSC::Parser<LexerType>::parseForStatement):
+        (JSC::Parser<LexerType>::parseStatement):
+        (JSC::Parser<LexerType>::parseFunctionParameters):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parseExpression):
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        (JSC::Parser<LexerType>::parseYieldExpression):
+        (JSC::Parser<LexerType>::parseConditionalExpression):
+        (JSC::Parser<LexerType>::parseBinaryExpression):
+        (JSC::Parser<LexerType>::parseObjectLiteral):
+        (JSC::Parser<LexerType>::parseStrictObjectLiteral):
+        (JSC::Parser<LexerType>::parseArrayLiteral):
+        (JSC::Parser<LexerType>::parsePrimaryExpression):
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        (JSC::Parser<LexerType>::parseUnaryExpression):
+        * parser/Parser.h:
+        (JSC::Parser::hasError):
+        (JSC::Parser::internalSaveParserState):
+        (JSC::Parser::restoreParserState):
+        (JSC::Parser::internalSaveLexerState):
+        (JSC::Parser::restoreLexerState):
+        (JSC::Parser::createSavePointForError):
+        (JSC::Parser::createSavePoint):
+        (JSC::Parser::restoreSavePointWithError):
+        (JSC::Parser::restoreSavePoint):
+        (JSC::Parser::saveState): Deleted.
+        (JSC::Parser::restoreState): Deleted.
+
 2016-01-22  Keith Miller  <[email protected]>
 
         Unreviewed. fnormal => normal.

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (195483 => 195484)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-01-22 22:50:41 UTC (rev 195483)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-01-22 22:52:42 UTC (rev 195484)
@@ -200,14 +200,8 @@
     , m_source(&source)
     , m_hasStackOverflow(false)
     , m_allowsIn(true)
-    , m_assignmentCount(0)
-    , m_nonLHSCount(0)
     , m_syntaxAlreadyValidated(source.provider()->isValid())
     , m_statementDepth(0)
-    , m_nonTrivialExpressionCount(0)
-    , m_functionParsePhase(FunctionParsePhase::Body)
-    , m_lastIdentifier(0)
-    , m_lastFunctionName(nullptr)
     , m_sourceElements(0)
     , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
     , m_superBinding(superBinding)
@@ -245,7 +239,7 @@
     ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
     ScopeRef scope = currentScope();
     scope->setIsLexicalScope();
-    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Body);
+    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
 
     bool isArrowFunctionBodyExpression = false;
     if (m_lexer->isReparsingFunction()) {
@@ -403,7 +397,7 @@
             // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
             AutoPopScopeRef fakeScope(this, pushScope());
             fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
-                
+
             unsigned parametersCount = 0;
             isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
                 
@@ -441,10 +435,10 @@
                     setStrictMode();
                     hasSetStrict = true;
                     if (!isValidStrictMode()) {
-                        if (m_lastFunctionName) {
-                            if (m_vm->propertyNames->arguments == *m_lastFunctionName)
+                        if (m_parserState.lastFunctionName) {
+                            if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
                                 semanticFail("Cannot name a function 'arguments' in strict mode");
-                            if (m_vm->propertyNames->eval == *m_lastFunctionName)
+                            if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
                                 semanticFail("Cannot name a function 'eval' in strict mode");
                         }
                         if (hasDeclaredVariable(m_vm->propertyNames->arguments))
@@ -770,7 +764,7 @@
     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)
+        if (m_parserState.lastFunctionName && name == *m_parserState.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))
@@ -900,9 +894,9 @@
 
     semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
 
-    if (strictMode() && m_lastIdentifier && context.isResolve(element)) {
-        bool isEvalOrArguments = m_vm->propertyNames->eval == *m_lastIdentifier || m_vm->propertyNames->arguments == *m_lastIdentifier;
-        failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
+    if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
+        bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
+        failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
     }
 
     return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
@@ -931,7 +925,7 @@
 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
 {
     failIfStackOverflow();
-    int nonLHSCount = m_nonLHSCount;
+    int nonLHSCount = m_parserState.nonLHSCount;
     TreeDestructuringPattern pattern;
     switch (m_token.m_type) {
     case OPENBRACKET: {
@@ -1086,7 +1080,7 @@
         break;
     }
     }
-    m_nonLHSCount = nonLHSCount;
+    m_parserState.nonLHSCount = nonLHSCount;
     return pattern;
 }
 
@@ -1108,7 +1102,7 @@
     int startLine = tokenLine();
     next();
     handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
-    int nonLHSCount = m_nonLHSCount;
+    int nonLHSCount = m_parserState.nonLHSCount;
     int declarations = 0;
     JSTextPosition declsStart;
     JSTextPosition declsEnd;
@@ -1260,7 +1254,7 @@
     
     // For-in and For-of loop
 enumerationLoop:
-    failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
+    failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
     bool isOfEnumeration = false;
     if (!consume(INTOKEN)) {
         failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
@@ -1684,11 +1678,11 @@
         directive = m_token.m_data.ident;
         if (directiveLiteralLength)
             *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
-        nonTrivialExpressionCount = m_nonTrivialExpressionCount;
+        nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
         FALLTHROUGH;
     default:
         TreeStatement exprStatement = parseExpressionStatement(context);
-        if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
+        if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
             directive = 0;
         result = exprStatement;
         break;
@@ -1802,7 +1796,7 @@
     TreeFormalParameterList parameterList = context.createFormalParameterList();
     functionInfo.parameters = parameterList;
     functionInfo.startOffset = parametersStart;
-    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Parameters);
+    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
     
     if (mode == SourceParseMode::ArrowFunctionMode) {
         if (!match(IDENT) && !match(OPENPAREN)) {
@@ -1899,10 +1893,10 @@
     bool upperScopeIsGenerator = currentScope()->isGenerator();
     AutoPopScopeRef functionScope(this, pushScope());
     functionScope->setSourceParseMode(mode);
-    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Body);
+    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
     int functionNameStart = m_token.m_location.startOffset;
-    const Identifier* lastFunctionName = m_lastFunctionName;
-    m_lastFunctionName = nullptr;
+    const Identifier* lastFunctionName = m_parserState.lastFunctionName;
+    m_parserState.lastFunctionName = nullptr;
     int parametersStart;
     JSTokenLocation startLocation;
     int startColumn;
@@ -1949,7 +1943,7 @@
 
         if (matchSpecIdentifier(upperScopeIsGenerator)) {
             functionInfo.name = m_token.m_data.ident;
-            m_lastFunctionName = functionInfo.name;
+            m_parserState.lastFunctionName = functionInfo.name;
             next();
             if (!nameIsInContainingScope)
                 failIfTrueIfStrict(functionScope->declareVariable(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
@@ -2039,8 +2033,8 @@
         return true;
     }
     
-    m_lastFunctionName = lastFunctionName;
-    ParserState oldState = saveState();
+    m_parserState.lastFunctionName = lastFunctionName;
+    ParserState oldState = internalSaveParserState();
 
     auto performParsingFunctionBody = [&] {
         return parseFunctionBody(context, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
@@ -2063,7 +2057,7 @@
     } else
         functionInfo.body = performParsingFunctionBody();
     
-    restoreState(oldState);
+    restoreParserState(oldState);
     failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
     context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
     if (functionScope->strictMode() && functionInfo.name) {
@@ -2230,7 +2224,7 @@
         // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
         bool isStaticMethod = false;
         if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
-            auto savePoint = createSavePoint();
+            SavePoint savePoint = createSavePoint();
             next();
             if (match(OPENPAREN)) {
                 // Reparse "static()" as a method named "static".
@@ -2915,8 +2909,8 @@
     if (!match(COMMA))
         return node;
     next();
-    m_nonTrivialExpressionCount++;
-    m_nonLHSCount++;
+    m_parserState.nonTrivialExpressionCount++;
+    m_parserState.nonLHSCount++;
     TreeExpression right = parseAssignmentExpression(context);
     failIfFalse(right, "Cannot parse _expression_ in a comma _expression_");
     context.setEndOffset(right, m_lastTokenEndPosition.offset);
@@ -2956,8 +2950,8 @@
     failIfStackOverflow();
     JSTextPosition start = tokenStartPosition();
     JSTokenLocation location(tokenLocation());
-    int initialAssignmentCount = m_assignmentCount;
-    int initialNonLHSCount = m_nonLHSCount;
+    int initialAssignmentCount = m_parserState.assignmentCount;
+    int initialNonLHSCount = m_parserState.nonLHSCount;
     bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
     SavePoint savePoint = createSavePoint();
 
@@ -2992,7 +2986,7 @@
     }
 
     failIfFalse(lhs, "Cannot parse _expression_");
-    if (initialNonLHSCount != m_nonLHSCount) {
+    if (initialNonLHSCount != m_parserState.nonLHSCount) {
         if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
             semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
 
@@ -3019,21 +3013,21 @@
         default:
             goto end;
         }
-        m_nonTrivialExpressionCount++;
+        m_parserState.nonTrivialExpressionCount++;
         hadAssignment = true;
-        context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
+        context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
         start = tokenStartPosition();
-        m_assignmentCount++;
+        m_parserState.assignmentCount++;
         next(TreeBuilder::DontBuildStrings);
-        if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
-            failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
-            failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
-            declareWrite(m_lastIdentifier);
-            m_lastIdentifier = 0;
+        if (strictMode() && m_parserState.lastIdentifier && context.isResolve(lhs)) {
+            failIfTrueIfStrict(m_vm->propertyNames->eval == *m_parserState.lastIdentifier, "Cannot modify 'eval' in strict mode");
+            failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_parserState.lastIdentifier, "Cannot modify 'arguments' in strict mode");
+            declareWrite(m_parserState.lastIdentifier);
+            m_parserState.lastIdentifier = 0;
         }
         lhs = parseAssignmentExpression(context);
         failIfFalse(lhs, "Cannot parse the right hand side of an assignment _expression_");
-        if (initialNonLHSCount != m_nonLHSCount) {
+        if (initialNonLHSCount != m_parserState.nonLHSCount) {
             if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
                 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
             break;
@@ -3041,13 +3035,13 @@
     }
 end:
     if (hadAssignment)
-        m_nonLHSCount++;
+        m_parserState.nonLHSCount++;
     
     if (!TreeBuilder::CreatesAST)
         return lhs;
     
     while (assignmentStack)
-        lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
+        lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_parserState.assignmentCount, lastTokenEndPosition());
     
     return lhs;
 }
@@ -3064,7 +3058,7 @@
     failIfFalse(currentScope()->isGenerator(), "Cannot use yield _expression_ out of generator");
 
     // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
-    failIfTrue(m_functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield _expression_ within parameters");
+    failIfTrue(m_parserState.functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield _expression_ within parameters");
 
     JSTokenLocation location(tokenLocation());
     JSTextPosition divotStart = tokenStartPosition();
@@ -3093,8 +3087,8 @@
     failIfFalse(cond, "Cannot parse _expression_");
     if (!match(QUESTION))
         return cond;
-    m_nonTrivialExpressionCount++;
-    m_nonLHSCount++;
+    m_parserState.nonTrivialExpressionCount++;
+    m_parserState.nonLHSCount++;
     next(TreeBuilder::DontBuildStrings);
     TreeExpression lhs = parseAssignmentExpression(context);
     failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
@@ -3129,16 +3123,16 @@
     JSTokenLocation location(tokenLocation());
     while (true) {
         JSTextPosition exprStart = tokenStartPosition();
-        int initialAssignments = m_assignmentCount;
+        int initialAssignments = m_parserState.assignmentCount;
         TreeExpression current = parseUnaryExpression(context);
         failIfFalse(current, "Cannot parse _expression_");
         
-        context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
+        context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_parserState.assignmentCount);
         int precedence = isBinaryOperator(m_token.m_type);
         if (!precedence)
             break;
-        m_nonTrivialExpressionCount++;
-        m_nonLHSCount++;
+        m_parserState.nonTrivialExpressionCount++;
+        m_parserState.nonLHSCount++;
         int operatorToken = m_token.m_type;
         next(TreeBuilder::DontBuildStrings);
         
@@ -3342,10 +3336,10 @@
 template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
 {
-    auto savePoint = createSavePoint();
+    SavePoint savePoint = createSavePoint();
     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
 
-    int oldNonLHSCount = m_nonLHSCount;
+    int oldNonLHSCount = m_parserState.nonLHSCount;
 
     JSTokenLocation location(tokenLocation());    
     if (match(CLOSEBRACE)) {
@@ -3390,7 +3384,7 @@
     location = tokenLocation();
     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
     
-    m_nonLHSCount = oldNonLHSCount;
+    m_parserState.nonLHSCount = oldNonLHSCount;
     
     return context.createObjectLiteral(location, propertyList);
 }
@@ -3400,7 +3394,7 @@
 {
     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
     
-    int oldNonLHSCount = m_nonLHSCount;
+    int oldNonLHSCount = m_parserState.nonLHSCount;
 
     JSTokenLocation location(tokenLocation());
     if (match(CLOSEBRACE)) {
@@ -3436,7 +3430,7 @@
     location = tokenLocation();
     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
 
-    m_nonLHSCount = oldNonLHSCount;
+    m_parserState.nonLHSCount = oldNonLHSCount;
 
     return context.createObjectLiteral(location, propertyList);
 }
@@ -3446,7 +3440,7 @@
 {
     consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
     
-    int oldNonLHSCount = m_nonLHSCount;
+    int oldNonLHSCount = m_parserState.nonLHSCount;
     
     int elisions = 0;
     while (match(COMMA)) {
@@ -3510,7 +3504,7 @@
         semanticFail("The '...' operator should come before a target _expression_");
     }
     
-    m_nonLHSCount = oldNonLHSCount;
+    m_parserState.nonLHSCount = oldNonLHSCount;
     
     return context.createArray(location, elementList);
 }
@@ -3612,9 +3606,9 @@
         return parseArrayLiteral(context);
     case OPENPAREN: {
         next();
-        int oldNonLHSCount = m_nonLHSCount;
+        int oldNonLHSCount = m_parserState.nonLHSCount;
         TreeExpression result = parseExpression(context);
-        m_nonLHSCount = oldNonLHSCount;
+        m_parserState.nonLHSCount = oldNonLHSCount;
         handleProductionOrFail(CLOSEPAREN, ")", "end", "compound _expression_");
         return result;
     }
@@ -3630,7 +3624,7 @@
         JSTokenLocation location(tokenLocation());
         next();
         currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
-        m_lastIdentifier = ident;
+        m_parserState.lastIdentifier = ident;
         return context.createResolve(location, ident, start);
     }
     case STRING: {
@@ -3797,21 +3791,21 @@
         location = tokenLocation();
         switch (m_token.m_type) {
         case OPENBRACKET: {
-            m_nonTrivialExpressionCount++;
+            m_parserState.nonTrivialExpressionCount++;
             JSTextPosition expressionEnd = lastTokenEndPosition();
             next();
-            int nonLHSCount = m_nonLHSCount;
-            int initialAssignments = m_assignmentCount;
+            int nonLHSCount = m_parserState.nonLHSCount;
+            int initialAssignments = m_parserState.assignmentCount;
             TreeExpression property = parseExpression(context);
             failIfFalse(property, "Cannot parse subscript _expression_");
-            base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
+            base = context.createBracketAccess(location, base, property, initialAssignments != m_parserState.assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
             handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript _expression_");
-            m_nonLHSCount = nonLHSCount;
+            m_parserState.nonLHSCount = nonLHSCount;
             break;
         }
         case OPENPAREN: {
-            m_nonTrivialExpressionCount++;
-            int nonLHSCount = m_nonLHSCount;
+            m_parserState.nonTrivialExpressionCount++;
+            int nonLHSCount = m_parserState.nonLHSCount;
             if (newCount) {
                 newCount--;
                 JSTextPosition expressionEnd = lastTokenEndPosition();
@@ -3826,11 +3820,11 @@
                     currentFunctionScope()->setHasDirectSuper();
                 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
             }
-            m_nonLHSCount = nonLHSCount;
+            m_parserState.nonLHSCount = nonLHSCount;
             break;
         }
         case DOT: {
-            m_nonTrivialExpressionCount++;
+            m_parserState.nonTrivialExpressionCount++;
             JSTextPosition expressionEnd = lastTokenEndPosition();
             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
             matchOrFail(IDENT, "Expected a property name after '.'");
@@ -3842,11 +3836,11 @@
         case TEMPLATE: {
             semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
             JSTextPosition expressionEnd = lastTokenEndPosition();
-            int nonLHSCount = m_nonLHSCount;
+            int nonLHSCount = m_parserState.nonLHSCount;
             typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
             failIfFalse(templateLiteral, "Cannot parse template literal");
             base = context.createTaggedTemplate(location, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
-            m_nonLHSCount = nonLHSCount;
+            m_parserState.nonLHSCount = nonLHSCount;
             break;
         }
 #endif
@@ -3936,10 +3930,10 @@
             }
         }
         lastOperator = m_token.m_type;
-        m_nonLHSCount++;
+        m_parserState.nonLHSCount++;
         context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
         next();
-        m_nonTrivialExpressionCount++;
+        m_parserState.nonTrivialExpressionCount++;
     }
     JSTextPosition subExprStart = tokenStartPosition();
     ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
@@ -3953,26 +3947,26 @@
     bool isEvalOrArguments = false;
     if (strictMode() && !m_syntaxAlreadyValidated) {
         if (context.isResolve(expr))
-            isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
+            isEvalOrArguments = *m_parserState.lastIdentifier == m_vm->propertyNames->eval || *m_parserState.lastIdentifier == m_vm->propertyNames->arguments;
     }
-    failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
+    failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
     switch (m_token.m_type) {
     case PLUSPLUS:
-        m_nonTrivialExpressionCount++;
-        m_nonLHSCount++;
+        m_parserState.nonTrivialExpressionCount++;
+        m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
-        m_assignmentCount++;
-        failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
+        m_parserState.assignmentCount++;
+        failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference _expression_");
         lastOperator = PLUSPLUS;
         next();
         break;
     case MINUSMINUS:
-        m_nonTrivialExpressionCount++;
-        m_nonLHSCount++;
+        m_parserState.nonTrivialExpressionCount++;
+        m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
-        m_assignmentCount++;
-        failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
+        m_parserState.assignmentCount++;
+        failIfTrueIfStrict(isEvalOrArguments, "'", m_parserState.lastIdentifier->impl(), "' cannot be modified in strict mode");
         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference _expression_");
         lastOperator = PLUSPLUS;
         next();
@@ -4005,12 +3999,12 @@
         case PLUSPLUS:
         case AUTOPLUSPLUS:
             expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
-            m_assignmentCount++;
+            m_parserState.assignmentCount++;
             break;
         case MINUSMINUS:
         case AUTOMINUSMINUS:
             expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
-            m_assignmentCount++;
+            m_parserState.assignmentCount++;
             break;
         case TYPEOF:
             expr = context.makeTypeOfNode(location, expr);
@@ -4019,7 +4013,7 @@
             expr = context.createVoid(location, expr);
             break;
         case DELETETOKEN:
-            failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
+            failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_parserState.lastIdentifier->impl(), "' in strict mode");
             expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
             break;
         default:

Modified: trunk/Source/_javascript_Core/parser/Parser.h (195483 => 195484)


--- trunk/Source/_javascript_Core/parser/Parser.h	2016-01-22 22:50:41 UTC (rev 195483)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2016-01-22 22:52:42 UTC (rev 195484)
@@ -1269,23 +1269,70 @@
         return !m_errorMessage.isNull();
     }
 
-    struct SavePoint {
+    enum class FunctionParsePhase { Parameters, Body };
+    struct ParserState {
+        int assignmentCount { 0 };
+        int nonLHSCount { 0 };
+        int nonTrivialExpressionCount { 0 };
+        FunctionParsePhase functionParsePhase { FunctionParsePhase::Body };
+        const Identifier* lastIdentifier { nullptr };
+        const Identifier* lastFunctionName { nullptr };
+    };
+
+    // If you're using this directly, you probably should be using
+    // createSavePoint() instead.
+    ALWAYS_INLINE ParserState internalSaveParserState()
+    {
+        return m_parserState;
+    }
+
+    ALWAYS_INLINE void restoreParserState(const ParserState& state)
+    {
+        m_parserState = state;
+    }
+
+    struct LexerState {
         int startOffset;
         unsigned oldLineStartOffset;
         unsigned oldLastLineNumber;
         unsigned oldLineNumber;
     };
-    
-    ALWAYS_INLINE SavePoint createSavePointForError()
+
+    // If you're using this directly, you probably should be using
+    // createSavePoint() instead.
+    // i.e, if you parse any kind of AssignmentExpression between
+    // saving/restoring, you should definitely not be using this directly.
+    ALWAYS_INLINE LexerState internalSaveLexerState()
     {
-        SavePoint result;
+        LexerState result;
         result.startOffset = m_token.m_location.startOffset;
         result.oldLineStartOffset = m_token.m_location.lineStartOffset;
         result.oldLastLineNumber = m_lexer->lastLineNumber();
         result.oldLineNumber = m_lexer->lineNumber();
         return result;
     }
+
+    ALWAYS_INLINE void restoreLexerState(const LexerState& lexerState)
+    {
+        m_lexer->setOffset(lexerState.startOffset, lexerState.oldLineStartOffset);
+        next();
+        m_lexer->setLastLineNumber(lexerState.oldLastLineNumber);
+        m_lexer->setLineNumber(lexerState.oldLineNumber);
+    }
+
+    struct SavePoint {
+        ParserState parserState;
+        LexerState lexerState;
+    };
     
+    ALWAYS_INLINE SavePoint createSavePointForError()
+    {
+        SavePoint result;
+        result.parserState = internalSaveParserState();
+        result.lexerState = internalSaveLexerState();
+        return result;
+    }
+    
     ALWAYS_INLINE SavePoint createSavePoint()
     {
         ASSERT(!hasError());
@@ -1295,10 +1342,8 @@
     ALWAYS_INLINE void restoreSavePointWithError(const SavePoint& savePoint, const String& message)
     {
         m_errorMessage = message;
-        m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset);
-        next();
-        m_lexer->setLastLineNumber(savePoint.oldLastLineNumber);
-        m_lexer->setLineNumber(savePoint.oldLineNumber);
+        restoreLexerState(savePoint.lexerState);
+        restoreParserState(savePoint.parserState);
     }
 
     ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
@@ -1306,51 +1351,21 @@
         restoreSavePointWithError(savePoint, String());
     }
 
-    enum class FunctionParsePhase { Parameters, Body };
-    struct ParserState {
-        int assignmentCount;
-        int nonLHSCount;
-        int nonTrivialExpressionCount;
-        FunctionParsePhase functionParsePhase;
-    };
-
-    ALWAYS_INLINE ParserState saveState()
-    {
-        ParserState result;
-        result.assignmentCount = m_assignmentCount;
-        result.nonLHSCount = m_nonLHSCount;
-        result.nonTrivialExpressionCount = m_nonTrivialExpressionCount;
-        result.functionParsePhase = m_functionParsePhase;
-        return result;
-    }
-
-    ALWAYS_INLINE void restoreState(const ParserState& state)
-    {
-        m_assignmentCount = state.assignmentCount;
-        m_nonLHSCount = state.nonLHSCount;
-        m_nonTrivialExpressionCount = state.nonTrivialExpressionCount;
-        m_functionParsePhase = state.functionParsePhase;
-    }
-
     VM* m_vm;
     const SourceCode* m_source;
     ParserArena m_parserArena;
     std::unique_ptr<LexerType> m_lexer;
     FunctionParameters* m_parameters { nullptr };
+
+    ParserState m_parserState;
     
     bool m_hasStackOverflow;
     String m_errorMessage;
     JSToken m_token;
     bool m_allowsIn;
     JSTextPosition m_lastTokenEndPosition;
-    int m_assignmentCount;
-    int m_nonLHSCount;
     bool m_syntaxAlreadyValidated;
     int m_statementDepth;
-    int m_nonTrivialExpressionCount;
-    FunctionParsePhase m_functionParsePhase;
-    const Identifier* m_lastIdentifier;
-    const Identifier* m_lastFunctionName;
     RefPtr<SourceProviderCache> m_functionCache;
     SourceElements* m_sourceElements;
     bool m_parsingBuiltin;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to