<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[195484] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/195484">195484</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-01-22 14:52:42 -0800 (Fri, 22 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>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&lt;Save/Restore&gt;LexerState functions.
The old &lt;save/restore&gt;State() function is renamed to
internal&lt;Save/Restore&gt;ParserState().

* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::Parser):
(JSC::Parser&lt;LexerType&gt;::parseInner):
(JSC::Parser&lt;LexerType&gt;::isArrowFunctionParameters):
(JSC::Parser&lt;LexerType&gt;::parseSourceElements):
(JSC::Parser&lt;LexerType&gt;::declareRestOrNormalParameter):
(JSC::Parser&lt;LexerType&gt;::parseAssignmentElement):
(JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
(JSC::Parser&lt;LexerType&gt;::parseForStatement):
(JSC::Parser&lt;LexerType&gt;::parseStatement):
(JSC::Parser&lt;LexerType&gt;::parseFunctionParameters):
(JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
(JSC::Parser&lt;LexerType&gt;::parseClass):
(JSC::Parser&lt;LexerType&gt;::parseExpression):
(JSC::Parser&lt;LexerType&gt;::parseAssignmentExpression):
(JSC::Parser&lt;LexerType&gt;::parseYieldExpression):
(JSC::Parser&lt;LexerType&gt;::parseConditionalExpression):
(JSC::Parser&lt;LexerType&gt;::parseBinaryExpression):
(JSC::Parser&lt;LexerType&gt;::parseObjectLiteral):
(JSC::Parser&lt;LexerType&gt;::parseStrictObjectLiteral):
(JSC::Parser&lt;LexerType&gt;::parseArrayLiteral):
(JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
(JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
(JSC::Parser&lt;LexerType&gt;::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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
</ul>

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

</body>
</html>