<!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>[198927] trunk</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/198927">198927</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-03-31 16:01:29 -0700 (Thu, 31 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>parsing arrow function expressions slows down the parser by 8% lets recoup some loss
https://bugs.webkit.org/show_bug.cgi?id=155988

Reviewed by Benjamin Poulain.

Source/JavaScriptCore:

We used to eagerly check if we're parsing an arrow function.
We did this inside parseAssignmentExpression(), and it was
very costly. The reason it was costly is that arrow functions
might start with an identifier. This means anytime we saw an
identifier we would have to do a lookahead, and then most likely
backtrack because more often than not, we wouldn't see &quot;=&gt;&quot;
as the next token.

In this patch I implement a new approach. We just parse
the lhs of an assignment expression eagerly without doing any
lookahead. Retroactively, if we see that we might have started
with an arrow function, and we don't have a valid lhs or the
next token is a &quot;=&gt;&quot;, we try to parse as an arrow function.

Here are a few examples motivating why this is valid:

`x =&gt; x`
In this example:
- &quot;x&quot; is a valid arrow function starting point.
- &quot;x&quot; also happens to be a valid lhs
- because we see &quot;=&gt;&quot; as the next token, we parse as an arrow function and succeed.

`(x) =&gt; x`
In this example:
- &quot;(&quot; is a valid arrow function starting point.
- &quot;(x)&quot; also happens to be a valid lhs
- because we see &quot;=&gt;&quot; as the next token, we parse as an arrow function and succeed.

`({x = 30}) =&gt; x;`
In this example:
- &quot;(&quot; is a valid arrow function starting point.
- &quot;({x = 30})&quot; is NOT a valid lhs. Because of this, we try to parse it as an arrow function and succeed.

There is one interesting implementation detail where we might
parse something that is both a valid LHS but happens
to actually be the arrow function parameters. The valid LHS
parsing might declare such variables as &quot;uses&quot; which would cause
weird capture analysis. This patch also introduces a mechanism
to backtrack on used variable analysis.

This is a 3.5%-4.5% octane code load speedup.

* parser/Lexer.h:
(JSC::Lexer::sawError):
(JSC::Lexer::setSawError):
(JSC::Lexer::getErrorMessage):
(JSC::Lexer::setErrorMessage):
(JSC::Lexer::sourceURL):
(JSC::Lexer::sourceMappingURL):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::isArrowFunctionParameters):
(JSC::Parser&lt;LexerType&gt;::parseAssignmentExpression):
(JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
* parser/Parser.h:
(JSC::Scope::Scope):
(JSC::Scope::startSwitch):
(JSC::Scope::declareParameter):
(JSC::Scope::usedVariablesContains):
(JSC::Scope::useVariable):
(JSC::Scope::pushUsedVariableSet):
(JSC::Scope::currentUsedVariablesSize):
(JSC::Scope::revertToPreviousUsedVariables):
(JSC::Scope::setNeedsFullActivation):
(JSC::Scope::needsFullActivation):
(JSC::Scope::isArrowFunctionBoundary):
(JSC::Scope::setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded):
(JSC::Scope::collectFreeVariables):
(JSC::Scope::fillParametersForSourceProviderCache):
(JSC::Scope::restoreFromSourceProviderCache):
(JSC::Scope::setIsModule):

LayoutTests:

* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:
(catch):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsparsersyntaxcheckexpectedtxt">trunk/LayoutTests/js/parser-syntax-check-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsparsersyntaxcheckjs">trunk/LayoutTests/js/script-tests/parser-syntax-check.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserLexerh">trunk/Source/JavaScriptCore/parser/Lexer.h</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="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/LayoutTests/ChangeLog        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-03-31  Saam barati  &lt;sbarati@apple.com&gt;
+
+        parsing arrow function expressions slows down the parser by 8% lets recoup some loss
+        https://bugs.webkit.org/show_bug.cgi?id=155988
+
+        Reviewed by Benjamin Poulain.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+        (catch):
+
</ins><span class="cx"> 2016-03-31  Per Arne Vollan  &lt;peavo@outlook.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Skip INTL related tests.
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -1040,6 +1040,95 @@
</span><span class="cx"> PASS Invalid: &quot;function f() { 'use strict'; function foo(...yield) { } }&quot;
</span><span class="cx"> PASS Invalid: &quot;function foo(...if) { }&quot;
</span><span class="cx"> PASS Invalid: &quot;function f() { function foo(...if) { } }&quot;
</span><ins>+Arrow function
+PASS Valid:   &quot;var x = (x) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = (x) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = (x, y, z) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = (x, y, z) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = ({x}, [y], z) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = ({x}, [y], z) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = ({x = 30}, [y], z) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = ({x = 30}, [y], z) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = (x = 20) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = (x = 20) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = ([x] = 20, y) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = ([x] = 20, y) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = ([x = 20] = 20) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = ([x = 20] = 20) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = foo =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = foo =&gt; x; }&quot;
+PASS Valid:   &quot;var x = foo =&gt; x =&gt; x =&gt; x =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = foo =&gt; x =&gt; x =&gt; x =&gt; x; }&quot;
+PASS Valid:   &quot;var x = foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x;&quot;
+PASS Valid:   &quot;function f() { var x = foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x; }&quot;
+PASS Valid:   &quot;var x = foo =&gt; x =&gt; x =&gt; x =&gt; {x};&quot;
+PASS Valid:   &quot;function f() { var x = foo =&gt; x =&gt; x =&gt; x =&gt; {x}; }&quot;
+PASS Valid:   &quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {});&quot;
+PASS Valid:   &quot;function f() { var x = ([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {}); }&quot;
+PASS Invalid: &quot;var x = foo =&gt; x =&gt; x =&gt; {x} =&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x = foo =&gt; x =&gt; x =&gt; {x} =&gt; x; }&quot;
+PASS Invalid: &quot;var x = {x} = 20 =&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x = {x} = 20 =&gt; x; }&quot;
+PASS Invalid: &quot;var x = [x] = 20 =&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x = [x] = 20 =&gt; x; }&quot;
+PASS Invalid: &quot;var x = [x = 25] = 20 =&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x = [x = 25] = 20 =&gt; x; }&quot;
+PASS Invalid: &quot;var x = ([x = 25]) =&gt;;&quot;
+PASS Invalid: &quot;function f() { var x = ([x = 25]) =&gt;; }&quot;
+PASS Invalid: &quot;var x = ([x = 25]) =&gt; x =&gt;;&quot;
+PASS Invalid: &quot;function f() { var x = ([x = 25]) =&gt; x =&gt;; }&quot;
+PASS Invalid: &quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt;;&quot;
+PASS Invalid: &quot;function f() { var x = ([x = 25]) =&gt; x =&gt; x =&gt;; }&quot;
+PASS Invalid: &quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt; {;&quot;
+PASS Invalid: &quot;function f() { var x = ([x = 25]) =&gt; x =&gt; x =&gt; {; }&quot;
+PASS Invalid: &quot;var x ==&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x ==&gt; x; }&quot;
+PASS Invalid: &quot;var x = x ==&gt; x;&quot;
+PASS Invalid: &quot;function f() { var x = x ==&gt; x; }&quot;
+PASS Valid:   &quot;foo((x) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo((x) =&gt; x) }&quot;
+PASS Valid:   &quot;foo((x, y, z) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo((x, y, z) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(({x}, [y], z) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(({x}, [y], z) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(({x = 30}, [y], z) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(({x = 30}, [y], z) =&gt; x) }&quot;
+PASS Valid:   &quot;foo((x = 20) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo((x = 20) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(([x] = 20, y) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(([x] = 20, y) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(([x = 20] = 20) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(([x = 20] = 20) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(foo =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(foo =&gt; x) }&quot;
+PASS Valid:   &quot;foo(foo =&gt; x =&gt; x =&gt; x =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(foo =&gt; x =&gt; x =&gt; x =&gt; x) }&quot;
+PASS Valid:   &quot;foo(foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x)&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x) }&quot;
+PASS Valid:   &quot;foo(foo =&gt; x =&gt; x =&gt; x =&gt; {x})&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(foo =&gt; x =&gt; x =&gt; x =&gt; {x}) }&quot;
+PASS Valid:   &quot;foo(([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {}))&quot; with ReferenceError
+PASS Valid:   &quot;function f() { foo(([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {})) }&quot;
+PASS Invalid: &quot;foo(foo =&gt; x =&gt; x =&gt; {x} =&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo(foo =&gt; x =&gt; x =&gt; {x} =&gt; x) }&quot;
+PASS Invalid: &quot;foo({x} = 20 =&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo({x} = 20 =&gt; x) }&quot;
+PASS Invalid: &quot;foo([x] = 20 =&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo([x] = 20 =&gt; x) }&quot;
+PASS Invalid: &quot;foo([x = 25] = 20 =&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo([x = 25] = 20 =&gt; x) }&quot;
+PASS Invalid: &quot;foo(([x = 25]) =&gt;)&quot;
+PASS Invalid: &quot;function f() { foo(([x = 25]) =&gt;) }&quot;
+PASS Invalid: &quot;foo(([x = 25]) =&gt; x =&gt;)&quot;
+PASS Invalid: &quot;function f() { foo(([x = 25]) =&gt; x =&gt;) }&quot;
+PASS Invalid: &quot;foo(([x = 25]) =&gt; x =&gt; x =&gt;)&quot;
+PASS Invalid: &quot;function f() { foo(([x = 25]) =&gt; x =&gt; x =&gt;) }&quot;
+PASS Invalid: &quot;foo(([x = 25]) =&gt; x =&gt; x =&gt; {)&quot;
+PASS Invalid: &quot;function f() { foo(([x = 25]) =&gt; x =&gt; x =&gt; {) }&quot;
+PASS Invalid: &quot;foo(x ==&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo(x ==&gt; x) }&quot;
+PASS Invalid: &quot;foo(x = x ==&gt; x)&quot;
+PASS Invalid: &quot;function f() { foo(x = x ==&gt; x) }&quot;
</ins><span class="cx"> PASS e.line is 1
</span><span class="cx"> PASS foo is 'PASS'
</span><span class="cx"> PASS bar is 'PASS'
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -618,6 +618,51 @@
</span><span class="cx"> invalid(&quot;'use strict'; function foo(...yield) { }&quot;);
</span><span class="cx"> invalid(&quot;function foo(...if) { }&quot;);
</span><span class="cx"> 
</span><ins>+debug(&quot;Arrow function&quot;);
+valid(&quot;var x = (x) =&gt; x;&quot;);
+valid(&quot;var x = (x, y, z) =&gt; x;&quot;);
+valid(&quot;var x = ({x}, [y], z) =&gt; x;&quot;);
+valid(&quot;var x = ({x = 30}, [y], z) =&gt; x;&quot;);
+valid(&quot;var x = (x = 20) =&gt; x;&quot;);
+valid(&quot;var x = ([x] = 20, y) =&gt; x;&quot;);
+valid(&quot;var x = ([x = 20] = 20) =&gt; x;&quot;);
+valid(&quot;var x = foo =&gt; x;&quot;);
+valid(&quot;var x = foo =&gt; x =&gt; x =&gt; x =&gt; x;&quot;);
+valid(&quot;var x = foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x;&quot;);
+valid(&quot;var x = foo =&gt; x =&gt; x =&gt; x =&gt; {x};&quot;);
+valid(&quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {});&quot;);
+invalid(&quot;var x = foo =&gt; x =&gt; x =&gt; {x} =&gt; x;&quot;);
+invalid(&quot;var x = {x} = 20 =&gt; x;&quot;);
+invalid(&quot;var x = [x] = 20 =&gt; x;&quot;);
+invalid(&quot;var x = [x = 25] = 20 =&gt; x;&quot;);
+invalid(&quot;var x = ([x = 25]) =&gt;;&quot;);
+invalid(&quot;var x = ([x = 25]) =&gt; x =&gt;;&quot;);
+invalid(&quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt;;&quot;);
+invalid(&quot;var x = ([x = 25]) =&gt; x =&gt; x =&gt; {;&quot;);
+invalid(&quot;var x ==&gt; x;&quot;);
+invalid(&quot;var x = x ==&gt; x;&quot;);
+valid(&quot;foo((x) =&gt; x)&quot;);
+valid(&quot;foo((x, y, z) =&gt; x)&quot;);
+valid(&quot;foo(({x}, [y], z) =&gt; x)&quot;);
+valid(&quot;foo(({x = 30}, [y], z) =&gt; x)&quot;);
+valid(&quot;foo((x = 20) =&gt; x)&quot;);
+valid(&quot;foo(([x] = 20, y) =&gt; x)&quot;);
+valid(&quot;foo(([x = 20] = 20) =&gt; x)&quot;);
+valid(&quot;foo(foo =&gt; x)&quot;);
+valid(&quot;foo(foo =&gt; x =&gt; x =&gt; x =&gt; x)&quot;);
+valid(&quot;foo(foo =&gt; x =&gt; (x = 20) =&gt; (x = 20) =&gt; x)&quot;);
+valid(&quot;foo(foo =&gt; x =&gt; x =&gt; x =&gt; {x})&quot;);
+valid(&quot;foo(([x = 25]) =&gt; x =&gt; x =&gt; ({x} = {}))&quot;);
+invalid(&quot;foo(foo =&gt; x =&gt; x =&gt; {x} =&gt; x)&quot;);
+invalid(&quot;foo({x} = 20 =&gt; x)&quot;);
+invalid(&quot;foo([x] = 20 =&gt; x)&quot;);
+invalid(&quot;foo([x = 25] = 20 =&gt; x)&quot;);
+invalid(&quot;foo(([x = 25]) =&gt;)&quot;);
+invalid(&quot;foo(([x = 25]) =&gt; x =&gt;)&quot;);
+invalid(&quot;foo(([x = 25]) =&gt; x =&gt; x =&gt;)&quot;);
+invalid(&quot;foo(([x = 25]) =&gt; x =&gt; x =&gt; {)&quot;);
+invalid(&quot;foo(x ==&gt; x)&quot;);
+invalid(&quot;foo(x = x ==&gt; x)&quot;);
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> try { eval(&quot;a.b.c = {};&quot;); } catch(e1) { e=e1; shouldBe(&quot;e.line&quot;, &quot;1&quot;) }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -1,3 +1,81 @@
</span><ins>+2016-03-31  Saam barati  &lt;sbarati@apple.com&gt;
+
+        parsing arrow function expressions slows down the parser by 8% lets recoup some loss
+        https://bugs.webkit.org/show_bug.cgi?id=155988
+
+        Reviewed by Benjamin Poulain.
+
+        We used to eagerly check if we're parsing an arrow function.
+        We did this inside parseAssignmentExpression(), and it was
+        very costly. The reason it was costly is that arrow functions
+        might start with an identifier. This means anytime we saw an
+        identifier we would have to do a lookahead, and then most likely
+        backtrack because more often than not, we wouldn't see &quot;=&gt;&quot;
+        as the next token.
+
+        In this patch I implement a new approach. We just parse
+        the lhs of an assignment expression eagerly without doing any
+        lookahead. Retroactively, if we see that we might have started
+        with an arrow function, and we don't have a valid lhs or the
+        next token is a &quot;=&gt;&quot;, we try to parse as an arrow function.
+
+        Here are a few examples motivating why this is valid:
+
+        `x =&gt; x`
+        In this example:
+        - &quot;x&quot; is a valid arrow function starting point.
+        - &quot;x&quot; also happens to be a valid lhs
+        - because we see &quot;=&gt;&quot; as the next token, we parse as an arrow function and succeed.
+
+        `(x) =&gt; x`
+        In this example:
+        - &quot;(&quot; is a valid arrow function starting point.
+        - &quot;(x)&quot; also happens to be a valid lhs
+        - because we see &quot;=&gt;&quot; as the next token, we parse as an arrow function and succeed.
+
+        `({x = 30}) =&gt; x;`
+        In this example:
+        - &quot;(&quot; is a valid arrow function starting point.
+        - &quot;({x = 30})&quot; is NOT a valid lhs. Because of this, we try to parse it as an arrow function and succeed.
+
+        There is one interesting implementation detail where we might
+        parse something that is both a valid LHS but happens
+        to actually be the arrow function parameters. The valid LHS
+        parsing might declare such variables as &quot;uses&quot; which would cause 
+        weird capture analysis. This patch also introduces a mechanism
+        to backtrack on used variable analysis.
+
+        This is a 3.5%-4.5% octane code load speedup.
+
+        * parser/Lexer.h:
+        (JSC::Lexer::sawError):
+        (JSC::Lexer::setSawError):
+        (JSC::Lexer::getErrorMessage):
+        (JSC::Lexer::setErrorMessage):
+        (JSC::Lexer::sourceURL):
+        (JSC::Lexer::sourceMappingURL):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::isArrowFunctionParameters):
+        (JSC::Parser&lt;LexerType&gt;::parseAssignmentExpression):
+        (JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
+        * parser/Parser.h:
+        (JSC::Scope::Scope):
+        (JSC::Scope::startSwitch):
+        (JSC::Scope::declareParameter):
+        (JSC::Scope::usedVariablesContains):
+        (JSC::Scope::useVariable):
+        (JSC::Scope::pushUsedVariableSet):
+        (JSC::Scope::currentUsedVariablesSize):
+        (JSC::Scope::revertToPreviousUsedVariables):
+        (JSC::Scope::setNeedsFullActivation):
+        (JSC::Scope::needsFullActivation):
+        (JSC::Scope::isArrowFunctionBoundary):
+        (JSC::Scope::setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded):
+        (JSC::Scope::collectFreeVariables):
+        (JSC::Scope::fillParametersForSourceProviderCache):
+        (JSC::Scope::restoreFromSourceProviderCache):
+        (JSC::Scope::setIsModule):
+
</ins><span class="cx"> 2016-03-31  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fails to build in Linux / PowerPC due to different ucontext_t definition
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserLexerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Lexer.h (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Lexer.h        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/Source/JavaScriptCore/parser/Lexer.h        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -85,7 +85,9 @@
</span><span class="cx"> 
</span><span class="cx">     // Functions for use after parsing.
</span><span class="cx">     bool sawError() const { return m_error; }
</span><ins>+    void setSawError(bool sawError) { m_error = sawError; }
</ins><span class="cx">     String getErrorMessage() const { return m_lexErrorMessage; }
</span><ins>+    void setErrorMessage(const String&amp; errorMessage) { m_lexErrorMessage = errorMessage; }
</ins><span class="cx">     String sourceURL() const { return m_sourceURLDirective; }
</span><span class="cx">     String sourceMappingURL() const { return m_sourceMappingURLDirective; }
</span><span class="cx">     void clear();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -60,7 +60,6 @@
</span><span class="cx"> #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
</span><span class="cx"> #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
</span><span class="cx"> #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
</span><del>-#define restoreSavePointAndFail(savePoint, message) do { restoreSavePointWithError(savePoint, message); return 0; } while (0)
</del><span class="cx"> #define failDueToUnexpectedToken() do {\
</span><span class="cx">         logError(true);\
</span><span class="cx">     return 0;\
</span><span class="lines">@@ -359,17 +358,13 @@
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="cx"> bool Parser&lt;LexerType&gt;::isArrowFunctionParameters()
</span><span class="cx"> {
</span><del>-    bool isArrowFunction = false;
-
-    if (match(EOFTOK))
-        return false;
-    
</del><span class="cx">     bool isOpenParen = match(OPENPAREN);
</span><span class="cx">     bool isIdent = match(IDENT);
</span><span class="cx">     
</span><span class="cx">     if (!isOpenParen &amp;&amp; !isIdent)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    bool isArrowFunction = false;
</ins><span class="cx">     SavePoint saveArrowFunctionPoint = createSavePoint();
</span><span class="cx">         
</span><span class="cx">     if (isIdent) {
</span><span class="lines">@@ -2990,30 +2985,64 @@
</span><span class="cx">     int initialAssignmentCount = m_parserState.assignmentCount;
</span><span class="cx">     int initialNonLHSCount = m_parserState.nonLHSCount;
</span><span class="cx">     bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
</span><ins>+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    bool wasOpenParen = match(OPENPAREN);
+    bool isValidArrowFunctionStart = match(OPENPAREN) || match(IDENT);
</ins><span class="cx">     SavePoint savePoint = createSavePoint();
</span><ins>+    size_t usedVariablesSize;
+    if (wasOpenParen) {
+        usedVariablesSize = currentScope()-&gt;currentUsedVariablesSize();
+        currentScope()-&gt;pushUsedVariableSet();
+    }
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ES6_GENERATORS)
</span><span class="cx">     if (match(YIELD) &amp;&amp; !isYIELDMaskedAsIDENT(currentScope()-&gt;isGenerator()))
</span><span class="cx">         return parseYieldExpression(context);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    TreeExpression lhs = parseConditionalExpression(context);
+
</ins><span class="cx"> #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
</span><del>-    if (isArrowFunctionParameters())
-        return parseArrowFunctionExpression(context);
</del><ins>+    if (isValidArrowFunctionStart &amp;&amp; !match(EOFTOK)) {
+        bool isArrowFunctionToken = match(ARROWFUNCTION);
+        if (!lhs || isArrowFunctionToken) {
+            SavePoint errorRestorationSavePoint = createSavePointForError();
+            String oldErrorMessage = m_errorMessage;
+            String oldLexerErrorMessage = m_lexer-&gt;getErrorMessage();
+            bool hasLexerError = m_lexer-&gt;sawError();
+            restoreSavePoint(savePoint);
+            if (isArrowFunctionParameters()) {
+                if (wasOpenParen)
+                    currentScope()-&gt;revertToPreviousUsedVariables(usedVariablesSize);
+                return parseArrowFunctionExpression(context);
+            }
+            restoreSavePointWithError(errorRestorationSavePoint, oldErrorMessage);
+            m_lexer-&gt;setErrorMessage(oldLexerErrorMessage);
+            m_lexer-&gt;setSawError(hasLexerError);
+            if (isArrowFunctionToken)
+                failDueToUnexpectedToken();
+        }
+    }
+
</ins><span class="cx"> #endif
</span><del>-    
-    TreeExpression lhs = parseConditionalExpression(context);
</del><span class="cx"> 
</span><span class="cx">     if (!lhs &amp;&amp; (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern()))
</span><span class="cx">         propagateError();
</span><span class="cx"> 
</span><span class="cx">     if (maybeAssignmentPattern &amp;&amp; (!lhs || (context.isObjectOrArrayLiteral(lhs) &amp;&amp; match(EQUAL)))) {
</span><span class="cx">         String expressionError = m_errorMessage;
</span><ins>+        String oldLexerErrorMessage = m_lexer-&gt;getErrorMessage();
+        bool hasLexerError = m_lexer-&gt;sawError();
</ins><span class="cx">         SavePoint expressionErrorLocation = createSavePointForError();
</span><span class="cx">         restoreSavePoint(savePoint);
</span><span class="cx">         auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
</span><del>-        if (classifier.indicatesPossiblePattern() &amp;&amp; (!pattern || !match(EQUAL)))
-            restoreSavePointAndFail(expressionErrorLocation, expressionError);
</del><ins>+        if (classifier.indicatesPossiblePattern() &amp;&amp; (!pattern || !match(EQUAL))) {
+            restoreSavePointWithError(expressionErrorLocation, expressionError);
+            m_lexer-&gt;setErrorMessage(oldLexerErrorMessage);
+            m_lexer-&gt;setSawError(hasLexerError);
+            return 0;
+        }
</ins><span class="cx">         failIfFalse(pattern, &quot;Cannot parse assignment pattern&quot;);
</span><span class="cx">         consumeOrFail(EQUAL, &quot;Expected '=' following assignment pattern&quot;);
</span><span class="cx">         auto rhs = parseAssignmentExpression(context);
</span><span class="lines">@@ -3666,6 +3695,8 @@
</span><span class="cx">         const Identifier* ident = m_token.m_data.ident;
</span><span class="cx">         JSTokenLocation location(tokenLocation());
</span><span class="cx">         next();
</span><ins>+        if (UNLIKELY(match(ARROWFUNCTION)))
+            return 0;
</ins><span class="cx">         currentScope()-&gt;useVariable(ident, m_vm-&gt;propertyNames-&gt;eval == *ident);
</span><span class="cx">         m_parserState.lastIdentifier = ident;
</span><span class="cx">         return context.createResolve(location, *ident, start, lastTokenEndPosition());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (198926 => 198927)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2016-03-31 22:54:48 UTC (rev 198926)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2016-03-31 23:01:29 UTC (rev 198927)
</span><span class="lines">@@ -43,17 +43,7 @@
</span><span class="cx"> #include &lt;wtf/SmallPtrSet.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><del>-struct Scope;
-}
</del><span class="cx"> 
</span><del>-namespace WTF {
-template &lt;&gt; struct VectorTraits&lt;JSC::Scope&gt; : VectorTraitsBase&lt;/* is pod */ false, void&gt; {
-    static const bool canMoveWithMemcpy = true;
-};
-}
-
-namespace JSC {
-
</del><span class="cx"> class ExecState;
</span><span class="cx"> class FunctionMetadataNode;
</span><span class="cx"> class FunctionParameters;
</span><span class="lines">@@ -191,8 +181,46 @@
</span><span class="cx">         , m_switchDepth(0)
</span><span class="cx">         , m_innerArrowFunctionFeatures(0)
</span><span class="cx">     {
</span><ins>+        m_usedVariables.append(UniquedStringImplPtrSet());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Scope(Scope&amp;&amp; other)
+        : m_vm(other.m_vm)
+        , m_shadowsArguments(other.m_shadowsArguments)
+        , m_usesEval(other.m_usesEval)
+        , m_needsFullActivation(other.m_needsFullActivation)
+        , m_hasDirectSuper(other.m_hasDirectSuper)
+        , m_needsSuperBinding(other.m_needsSuperBinding)
+        , m_allowsVarDeclarations(other.m_allowsVarDeclarations)
+        , m_allowsLexicalDeclarations(other.m_allowsLexicalDeclarations)
+        , m_strictMode(other.m_strictMode)
+        , m_isFunction(other.m_isFunction)
+        , m_isGenerator(other.m_isGenerator)
+        , m_isGeneratorBoundary(other.m_isGeneratorBoundary)
+        , m_isArrowFunction(other.m_isArrowFunction)
+        , m_isArrowFunctionBoundary(other.m_isArrowFunctionBoundary)
+        , m_isLexicalScope(other.m_isLexicalScope)
+        , m_isFunctionBoundary(other.m_isFunctionBoundary)
+        , m_isValidStrictMode(other.m_isValidStrictMode)
+        , m_hasArguments(other.m_hasArguments)
+        , m_isEvalContext(other.m_isEvalContext)
+        , m_constructorKind(other.m_constructorKind)
+        , m_expectedSuperBinding(other.m_expectedSuperBinding)
+        , m_loopDepth(other.m_loopDepth)
+        , m_switchDepth(other.m_switchDepth)
+        , m_innerArrowFunctionFeatures(other.m_innerArrowFunctionFeatures)
+        , m_labels(WTFMove(other.m_labels))
+        , m_declaredParameters(WTFMove(other.m_declaredParameters))
+        , m_declaredVariables(WTFMove(other.m_declaredVariables))
+        , m_lexicalVariables(WTFMove(other.m_lexicalVariables))
+        , m_usedVariables(WTFMove(other.m_usedVariables))
+        , m_closedVariableCandidates(WTFMove(other.m_closedVariableCandidates))
+        , m_writtenVariables(WTFMove(other.m_writtenVariables))
+        , m_moduleScopeData(WTFMove(other.m_moduleScopeData))
+        , m_functionDeclarations(WTFMove(other.m_functionDeclarations))
+    {
+    }
+
</ins><span class="cx">     void startSwitch() { m_switchDepth++; }
</span><span class="cx">     void endSwitch() { m_switchDepth--; }
</span><span class="cx">     void startLoop() { m_loopDepth++; }
</span><span class="lines">@@ -462,13 +490,29 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool usedVariablesContains(UniquedStringImpl* impl) const { return m_usedVariables.contains(impl); }
</del><ins>+    bool usedVariablesContains(UniquedStringImpl* impl) const
+    { 
+        for (const UniquedStringImplPtrSet&amp; set : m_usedVariables) {
+            if (set.contains(impl))
+                return true;
+        }
+        return false;
+    }
</ins><span class="cx">     void useVariable(const Identifier* ident, bool isEval)
</span><span class="cx">     {
</span><ins>+        useVariable(ident-&gt;impl(), isEval);
+    }
+    void useVariable(UniquedStringImpl* impl, bool isEval)
+    {
</ins><span class="cx">         m_usesEval |= isEval;
</span><del>-        m_usedVariables.add(ident-&gt;impl());
</del><ins>+        m_usedVariables.last().add(impl);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void pushUsedVariableSet() { m_usedVariables.append(UniquedStringImplPtrSet()); }
+    size_t currentUsedVariablesSize() { return m_usedVariables.size(); }
+
+    void revertToPreviousUsedVariables(size_t size) { m_usedVariables.resize(size); }
+
</ins><span class="cx">     void setNeedsFullActivation() { m_needsFullActivation = true; }
</span><span class="cx">     bool needsFullActivation() const { return m_needsFullActivation; }
</span><span class="cx">     bool isArrowFunctionBoundary() { return m_isArrowFunctionBoundary; }
</span><span class="lines">@@ -504,7 +548,7 @@
</span><span class="cx">         if (m_usesEval)
</span><span class="cx">             setInnerArrowFunctionUsesEval();
</span><span class="cx">         
</span><del>-        if (m_usedVariables.contains(m_vm-&gt;propertyNames-&gt;arguments.impl()))
</del><ins>+        if (usedVariablesContains(m_vm-&gt;propertyNames-&gt;arguments.impl()))
</ins><span class="cx">             setInnerArrowFunctionUsesArguments();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -514,20 +558,23 @@
</span><span class="cx">             m_usesEval = true;
</span><span class="cx"> 
</span><span class="cx">         {
</span><del>-            for (UniquedStringImpl* impl : nestedScope-&gt;m_usedVariables) {
-                if (nestedScope-&gt;m_declaredVariables.contains(impl) || nestedScope-&gt;m_lexicalVariables.contains(impl))
-                    continue;
</del><ins>+            UniquedStringImplPtrSet&amp; destinationSet = m_usedVariables.last();
+            for (const UniquedStringImplPtrSet&amp; usedVariablesSet : nestedScope-&gt;m_usedVariables) {
+                for (UniquedStringImpl* impl : usedVariablesSet) {
+                    if (nestedScope-&gt;m_declaredVariables.contains(impl) || nestedScope-&gt;m_lexicalVariables.contains(impl))
+                        continue;
</ins><span class="cx"> 
</span><del>-                // &quot;arguments&quot; reference should be resolved at function boudary.
-                if (nestedScope-&gt;isFunctionBoundary() &amp;&amp; nestedScope-&gt;hasArguments() &amp;&amp; impl == m_vm-&gt;propertyNames-&gt;arguments.impl() &amp;&amp; !nestedScope-&gt;isArrowFunctionBoundary())
-                    continue;
</del><ins>+                    // &quot;arguments&quot; reference should be resolved at function boudary.
+                    if (nestedScope-&gt;isFunctionBoundary() &amp;&amp; nestedScope-&gt;hasArguments() &amp;&amp; impl == m_vm-&gt;propertyNames-&gt;arguments.impl() &amp;&amp; !nestedScope-&gt;isArrowFunctionBoundary())
+                        continue;
</ins><span class="cx"> 
</span><del>-                m_usedVariables.add(impl);
-                // We don't want a declared variable that is used in an inner scope to be thought of as captured if
-                // that inner scope is both a lexical scope and not a function. Only inner functions and &quot;catch&quot; 
-                // statements can cause variables to be captured.
-                if (shouldTrackClosedVariables &amp;&amp; (nestedScope-&gt;m_isFunctionBoundary || !nestedScope-&gt;m_isLexicalScope))
-                    m_closedVariableCandidates.add(impl);
</del><ins>+                    destinationSet.add(impl);
+                    // We don't want a declared variable that is used in an inner scope to be thought of as captured if
+                    // that inner scope is both a lexical scope and not a function. Only inner functions and &quot;catch&quot; 
+                    // statements can cause variables to be captured.
+                    if (shouldTrackClosedVariables &amp;&amp; (nestedScope-&gt;m_isFunctionBoundary || !nestedScope-&gt;m_isLexicalScope))
+                        m_closedVariableCandidates.add(impl);
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         // Propagate closed variable candidates downwards within the same function.
</span><span class="lines">@@ -602,7 +649,8 @@
</span><span class="cx">         parameters.needsFullActivation = m_needsFullActivation;
</span><span class="cx">         parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures;
</span><span class="cx">         copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables);
</span><del>-        copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables);
</del><ins>+        for (const UniquedStringImplPtrSet&amp; set : m_usedVariables)
+            copyCapturedVariablesToVector(set, parameters.usedVariables);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void restoreFromSourceProviderCache(const SourceProviderCacheItem* info)
</span><span class="lines">@@ -612,8 +660,9 @@
</span><span class="cx">         m_strictMode = info-&gt;strictMode;
</span><span class="cx">         m_innerArrowFunctionFeatures = info-&gt;innerArrowFunctionFeatures;
</span><span class="cx">         m_needsFullActivation = info-&gt;needsFullActivation;
</span><ins>+        UniquedStringImplPtrSet&amp; destSet = m_usedVariables.last();
</ins><span class="cx">         for (unsigned i = 0; i &lt; info-&gt;usedVariablesCount; ++i)
</span><del>-            m_usedVariables.add(info-&gt;usedVariables()[i]);
</del><ins>+            destSet.add(info-&gt;usedVariables()[i]);
</ins><span class="cx">         for (unsigned i = 0; i &lt; info-&gt;writtenVariablesCount; ++i)
</span><span class="cx">             m_writtenVariables.add(info-&gt;writtenVariables()[i]);
</span><span class="cx">     }
</span><span class="lines">@@ -657,9 +706,6 @@
</span><span class="cx">         m_moduleScopeData = ModuleScopeData::create();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // All the fields in Scope must be able to use memcpy as their
-    // move operation. If you add a field that violates this, make sure
-    // to remove this comment and update WTF::VectorTraits&lt;JSC::Scope&gt;.
</del><span class="cx">     const VM* m_vm;
</span><span class="cx">     bool m_shadowsArguments;
</span><span class="cx">     bool m_usesEval;
</span><span class="lines">@@ -690,7 +736,7 @@
</span><span class="cx">     UniquedStringImplPtrSet m_declaredParameters;
</span><span class="cx">     VariableEnvironment m_declaredVariables;
</span><span class="cx">     VariableEnvironment m_lexicalVariables;
</span><del>-    UniquedStringImplPtrSet m_usedVariables;
</del><ins>+    Vector&lt;UniquedStringImplPtrSet, 6&gt; m_usedVariables;
</ins><span class="cx">     IdentifierSet m_closedVariableCandidates;
</span><span class="cx">     UniquedStringImplPtrSet m_writtenVariables;
</span><span class="cx">     RefPtr&lt;ModuleScopeData&gt; m_moduleScopeData;
</span></span></pre>
</div>
</div>

</body>
</html>