<!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>[163321] 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/163321">163321</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2014-02-03 12:39:38 -0800 (Mon, 03 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Simplified name scope creation for function expressions
https://bugs.webkit.org/show_bug.cgi?id=128031

Reviewed by Mark Lam.

Source/JavaScriptCore: 

3X speedup on js/regress/script-tests/function-with-eval.js.

We used to emit bytecode to push a name into local scope every
time a function that needed such a name executed. Now, we push the name
into scope once on the function object, and leave it there.

This is faster, and it also reduces the number of variable resolution
modes you have to worry about when thinking about bytecode and the
debugger.

This patch is slightly complicated by the fact that we don't know if
a function needs a name scope until we parse its body. So, there's some
glue code in here to delay filling in a function's scope until we parse
its body for the first time.

* bytecode/UnlinkedCodeBlock.cpp:
(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedFunctionExecutable::functionMode): Renamed
functionNameIsInScopeToggle to functionMode.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator): No need to emit convert_this
when debugging. The debugger will perform the conversion as needed.

(JSC::BytecodeGenerator::resolveCallee):
(JSC::BytecodeGenerator::addCallee): Simplified this code by removing
the &quot;my function needs a name scope, but didn't allocate one&quot; mode.

* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall): Pass a scope slot through to
CodeBlock generation, so we can add a function name scope if the parsed
function body requires one.

* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall): Ditto.

* parser/NodeConstructors.h:
(JSC::FuncExprNode::FuncExprNode):
(JSC::FuncDeclNode::FuncDeclNode):
* parser/Nodes.cpp:
(JSC::FunctionBodyNode::finishParsing):
* parser/Nodes.h:
(JSC::FunctionBodyNode::functionMode): Updated for rename.

* parser/ParserModes.h:
(JSC::functionNameIsInScope):
(JSC::functionNameScopeIsDynamic): Helper functions for reasoning about
how crazy JavaScript language semantics are.

* runtime/ArrayPrototype.cpp:
(JSC::isNumericCompareFunction):
(JSC::attemptFastSort): Updated for interface changes above.

* runtime/Executable.cpp:
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):
(JSC::FunctionExecutable::FunctionExecutable):
* runtime/Executable.h:
(JSC::ScriptExecutable::prepareForExecution):
(JSC::FunctionExecutable::functionMode):
* runtime/JSFunction.cpp:
(JSC::JSFunction::addNameScopeIfNeeded):
* runtime/JSFunction.h:
* runtime/JSNameScope.h:
(JSC::JSNameScope::create):
(JSC::JSNameScope::JSNameScope): Added machinery for pushing a function
name scope onto a function when we first discover that it's needed.

LayoutTests: 

Added a performance regression test.

* js/regress/function-with-eval-expected.txt: Added.
* js/regress/function-with-eval.html: Added.
* js/regress/script-tests/function-with-eval.js: Added.
(foo):
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodescpp">trunk/Source/JavaScriptCore/parser/Nodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserModesh">trunk/Source/JavaScriptCore/parser/ParserModes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayPrototypecpp">trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutablecpp">trunk/Source/JavaScriptCore/runtime/Executable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableh">trunk/Source/JavaScriptCore/runtime/Executable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctionh">trunk/Source/JavaScriptCore/runtime/JSFunction.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSNameScopeh">trunk/Source/JavaScriptCore/runtime/JSNameScope.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressfunctionwithevalexpectedtxt">trunk/LayoutTests/js/regress/function-with-eval-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressfunctionwithevalhtml">trunk/LayoutTests/js/regress/function-with-eval.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsfunctionwithevaljs">trunk/LayoutTests/js/regress/script-tests/function-with-eval.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/LayoutTests/ChangeLog        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2014-01-31  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        Simplified name scope creation for function expressions
+        https://bugs.webkit.org/show_bug.cgi?id=128031
+
+        Reviewed by Mark Lam.
+
+        Added a performance regression test.
+
+        * js/regress/function-with-eval-expected.txt: Added.
+        * js/regress/function-with-eval.html: Added.
+        * js/regress/script-tests/function-with-eval.js: Added.
+        (foo):
+        (bar):
+
</ins><span class="cx"> 2014-02-03  Chris Fleizach  &lt;cfleizach@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AX: WebKit should support @headers/@id for complex accessible web tables
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressfunctionwithevalexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/function-with-eval-expected.txt (0 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/function-with-eval-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/function-with-eval-expected.txt        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/function-with-eval
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressfunctionwithevalhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/function-with-eval.html (0 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/function-with-eval.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/function-with-eval.html        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/function-with-eval.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsfunctionwithevaljs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/function-with-eval.js (0 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/function-with-eval.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/function-with-eval.js        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+var foo = function foo(unlikely) {
+    if (unlikely)
+        return eval(&quot;0&quot;);
+    return 1;
+}
+
+noInline(foo);
+
+function bar() {
+    var result = 0;
+    for (var i = 0; i &lt; 1000000; ++i)
+        result += foo(false);
+    return result;
+}
+
+var result = bar();
+if (result != 1000000)
+    throw &quot;Error: bad result: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -1,3 +1,84 @@
</span><ins>+2014-01-31  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        Simplified name scope creation for function expressions
+        https://bugs.webkit.org/show_bug.cgi?id=128031
+
+        Reviewed by Mark Lam.
+
+        3X speedup on js/regress/script-tests/function-with-eval.js.
+
+        We used to emit bytecode to push a name into local scope every
+        time a function that needed such a name executed. Now, we push the name
+        into scope once on the function object, and leave it there.
+
+        This is faster, and it also reduces the number of variable resolution
+        modes you have to worry about when thinking about bytecode and the
+        debugger.
+
+        This patch is slightly complicated by the fact that we don't know if
+        a function needs a name scope until we parse its body. So, there's some
+        glue code in here to delay filling in a function's scope until we parse
+        its body for the first time.
+
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::generateFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedFunctionExecutable::functionMode): Renamed
+        functionNameIsInScopeToggle to functionMode.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator): No need to emit convert_this
+        when debugging. The debugger will perform the conversion as needed.
+
+        (JSC::BytecodeGenerator::resolveCallee):
+        (JSC::BytecodeGenerator::addCallee): Simplified this code by removing
+        the &quot;my function needs a name scope, but didn't allocate one&quot; mode.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall): Pass a scope slot through to
+        CodeBlock generation, so we can add a function name scope if the parsed
+        function body requires one.
+
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setUpCall): Ditto.
+
+        * parser/NodeConstructors.h:
+        (JSC::FuncExprNode::FuncExprNode):
+        (JSC::FuncDeclNode::FuncDeclNode):
+        * parser/Nodes.cpp:
+        (JSC::FunctionBodyNode::finishParsing):
+        * parser/Nodes.h:
+        (JSC::FunctionBodyNode::functionMode): Updated for rename.
+
+        * parser/ParserModes.h:
+        (JSC::functionNameIsInScope):
+        (JSC::functionNameScopeIsDynamic): Helper functions for reasoning about
+        how crazy JavaScript language semantics are.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::isNumericCompareFunction):
+        (JSC::attemptFastSort): Updated for interface changes above.
+
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        (JSC::FunctionExecutable::FunctionExecutable):
+        * runtime/Executable.h:
+        (JSC::ScriptExecutable::prepareForExecution):
+        (JSC::FunctionExecutable::functionMode):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::addNameScopeIfNeeded):
+        * runtime/JSFunction.h:
+        * runtime/JSNameScope.h:
+        (JSC::JSNameScope::create):
+        (JSC::JSNameScope::JSNameScope): Added machinery for pushing a function
+        name scope onto a function when we first discover that it's needed.
+
</ins><span class="cx"> 2014-01-25  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Stop using Unicode.h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (executable-&gt;forceUsesArguments())
</span><span class="cx">         body-&gt;setUsesArguments();
</span><del>-    body-&gt;finishParsing(executable-&gt;parameters(), executable-&gt;name(), executable-&gt;functionNameIsInScopeToggle());
</del><ins>+    body-&gt;finishParsing(executable-&gt;parameters(), executable-&gt;name(), executable-&gt;functionMode());
</ins><span class="cx">     executable-&gt;recordParse(body-&gt;features(), body-&gt;hasCapturedVariables());
</span><span class="cx">     
</span><span class="cx">     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&amp;vm, FunctionCode, ExecutableInfo(body-&gt;needsActivation(), body-&gt;usesEval(), body-&gt;isStrictMode(), kind == CodeForConstruct));
</span><span class="lines">@@ -100,7 +100,7 @@
</span><span class="cx">     , m_startOffset(node-&gt;source().startOffset() - source.startOffset())
</span><span class="cx">     , m_sourceLength(node-&gt;source().length())
</span><span class="cx">     , m_features(node-&gt;features())
</span><del>-    , m_functionNameIsInScopeToggle(node-&gt;functionNameIsInScopeToggle())
</del><ins>+    , m_functionMode(node-&gt;functionMode())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">     }
</span><span class="cx">     size_t parameterCount() const;
</span><span class="cx">     bool isInStrictContext() const { return m_isInStrictContext; }
</span><del>-    FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
</del><ins>+    FunctionMode functionMode() const { return m_functionMode; }
</ins><span class="cx"> 
</span><span class="cx">     unsigned firstLineOffset() const { return m_firstLineOffset; }
</span><span class="cx">     unsigned lineCount() const { return m_lineCount; }
</span><span class="lines">@@ -169,7 +169,7 @@
</span><span class="cx"> 
</span><span class="cx">     CodeFeatures m_features;
</span><span class="cx"> 
</span><del>-    FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
</del><ins>+    FunctionMode m_functionMode;
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     void finishCreation(VM&amp; vm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -383,7 +383,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (isConstructor()) {
</span><span class="cx">         emitCreateThis(&amp;m_thisRegister);
</span><del>-    } else if (functionBody-&gt;usesThis() || codeBlock-&gt;usesEval() || m_shouldEmitDebugHooks) {
</del><ins>+    } else if (functionBody-&gt;usesThis() || codeBlock-&gt;usesEval()) {
</ins><span class="cx">         m_codeBlock-&gt;addPropertyAccessInstruction(instructions().size());
</span><span class="cx">         emitOpcode(op_to_this);
</span><span class="cx">         instructions().append(kill(&amp;m_thisRegister));
</span><span class="lines">@@ -456,32 +456,24 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
</span><span class="cx"> {
</span><del>-    if (functionBodyNode-&gt;ident().isNull() || !functionBodyNode-&gt;functionNameIsInScope())
</del><ins>+    if (!functionNameIsInScope(functionBodyNode-&gt;ident(), functionBodyNode-&gt;functionMode()))
</ins><span class="cx">         return 0;
</span><span class="cx"> 
</span><ins>+    if (functionNameScopeIsDynamic(m_codeBlock-&gt;usesEval(), m_codeBlock-&gt;isStrictMode()))
+        return 0;
+
</ins><span class="cx">     m_calleeRegister.setIndex(JSStack::Callee);
</span><ins>+    if (functionBodyNode-&gt;captures(functionBodyNode-&gt;ident()))
+        return emitMove(addVar(), IsCaptured, &amp;m_calleeRegister);
</ins><span class="cx"> 
</span><del>-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if (m_codeBlock-&gt;usesEval() &amp;&amp; !m_codeBlock-&gt;isStrictMode())
-        emitPushFunctionNameScope(functionBodyNode-&gt;ident(), &amp;m_calleeRegister, ReadOnly | DontDelete);
-
-    if (!functionBodyNode-&gt;captures(functionBodyNode-&gt;ident()))
-        return &amp;m_calleeRegister;
-
-    // Move the callee into the captured section of the stack.
-    return emitMove(addVar(), IsCaptured, &amp;m_calleeRegister);
</del><ins>+    return &amp;m_calleeRegister;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
</span><span class="cx"> {
</span><del>-    if (functionBodyNode-&gt;ident().isNull() || !functionBodyNode-&gt;functionNameIsInScope())
</del><ins>+    if (!calleeRegister)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if (m_codeBlock-&gt;usesEval() &amp;&amp; !m_codeBlock-&gt;isStrictMode())
-        return;
-
-    ASSERT(calleeRegister);
</del><span class="cx">     symbolTable().add(functionBodyNode-&gt;ident().impl(), SymbolTableEntry(calleeRegister-&gt;index(), ReadOnly));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -875,7 +875,7 @@
</span><span class="cx">     if (JSObject* error = program-&gt;initializeGlobalProperties(vm, callFrame, scope))
</span><span class="cx">         return checkedReturn(callFrame-&gt;vm().throwException(callFrame, error));
</span><span class="cx"> 
</span><del>-    if (JSObject* error = program-&gt;prepareForExecution(callFrame, scope, CodeForCall))
</del><ins>+    if (JSObject* error = program-&gt;prepareForExecution(callFrame, nullptr, &amp;scope, CodeForCall))
</ins><span class="cx">         return checkedReturn(callFrame-&gt;vm().throwException(callFrame, error));
</span><span class="cx"> 
</span><span class="cx">     ProgramCodeBlock* codeBlock = program-&gt;codeBlock();
</span><span class="lines">@@ -932,7 +932,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (isJSCall) {
</span><span class="cx">         // Compile the callee:
</span><del>-        JSObject* compileError = callData.js.functionExecutable-&gt;prepareForExecution(callFrame, scope, CodeForCall);
</del><ins>+        JSObject* compileError = callData.js.functionExecutable-&gt;prepareForExecution(callFrame, jsCast&lt;JSFunction*&gt;(function), &amp;scope, CodeForCall);
</ins><span class="cx">         if (UNLIKELY(!!compileError)) {
</span><span class="cx">             return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
</span><span class="cx">         }
</span><span class="lines">@@ -1000,7 +1000,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (isJSConstruct) {
</span><span class="cx">         // Compile the callee:
</span><del>-        JSObject* compileError = constructData.js.functionExecutable-&gt;prepareForExecution(callFrame, scope, CodeForConstruct);
</del><ins>+        JSObject* compileError = constructData.js.functionExecutable-&gt;prepareForExecution(callFrame, jsCast&lt;JSFunction*&gt;(constructor), &amp;scope, CodeForConstruct);
</ins><span class="cx">         if (UNLIKELY(!!compileError)) {
</span><span class="cx">             return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
</span><span class="cx">         }
</span><span class="lines">@@ -1053,7 +1053,7 @@
</span><span class="cx">         return CallFrameClosure();
</span><span class="cx"> 
</span><span class="cx">     // Compile the callee:
</span><del>-    JSObject* error = functionExecutable-&gt;prepareForExecution(callFrame, scope, CodeForCall);
</del><ins>+    JSObject* error = functionExecutable-&gt;prepareForExecution(callFrame, function, &amp;scope, CodeForCall);
</ins><span class="cx">     if (error) {
</span><span class="cx">         callFrame-&gt;vm().throwException(callFrame, error);
</span><span class="cx">         return CallFrameClosure();
</span><span class="lines">@@ -1134,7 +1134,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSObject* compileError = eval-&gt;prepareForExecution(callFrame, scope, CodeForCall);
</del><ins>+    JSObject* compileError = eval-&gt;prepareForExecution(callFrame, nullptr, &amp;scope, CodeForCall);
</ins><span class="cx">     if (UNLIKELY(!!compileError))
</span><span class="cx">         return checkedReturn(callFrame-&gt;vm().throwException(callFrame, compileError));
</span><span class="cx">     EvalCodeBlock* codeBlock = eval-&gt;codeBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -693,7 +693,8 @@
</span><span class="cx">         return reinterpret_cast&lt;char*&gt;(handleHostCall(execCallee, calleeAsValue, kind));
</span><span class="cx"> 
</span><span class="cx">     JSFunction* callee = jsCast&lt;JSFunction*&gt;(calleeAsFunctionCell);
</span><del>-    execCallee-&gt;setScope(callee-&gt;scopeUnchecked());
</del><ins>+    JSScope* scope = callee-&gt;scopeUnchecked();
+    execCallee-&gt;setScope(scope);
</ins><span class="cx">     ExecutableBase* executable = callee-&gt;executable();
</span><span class="cx"> 
</span><span class="cx">     MacroAssemblerCodePtr codePtr;
</span><span class="lines">@@ -703,7 +704,8 @@
</span><span class="cx">         codePtr = executable-&gt;entrypointFor(*vm, kind, MustCheckArity, registers);
</span><span class="cx">     else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><del>-        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee-&gt;scope(), kind);
</del><ins>+        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee, &amp;scope, kind);
+        execCallee-&gt;setScope(scope);
</ins><span class="cx">         if (error) {
</span><span class="cx">             throwStackOverflowError(exec);
</span><span class="cx">             return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span><span class="lines">@@ -757,11 +759,13 @@
</span><span class="cx">         return reinterpret_cast&lt;char*&gt;(handleHostCall(execCallee, calleeAsValue, kind));
</span><span class="cx">     
</span><span class="cx">     JSFunction* function = jsCast&lt;JSFunction*&gt;(calleeAsFunctionCell);
</span><del>-    execCallee-&gt;setScope(function-&gt;scopeUnchecked());
</del><ins>+    JSScope* scope = function-&gt;scopeUnchecked();
+    execCallee-&gt;setScope(scope);
</ins><span class="cx">     ExecutableBase* executable = function-&gt;executable();
</span><span class="cx">     if (UNLIKELY(!executable-&gt;hasJITCodeFor(kind))) {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><del>-        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, function-&gt;scope(), kind);
</del><ins>+        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, function, &amp;scope, kind);
+        execCallee-&gt;setScope(scope);
</ins><span class="cx">         if (error) {
</span><span class="cx">             exec-&gt;vm().throwException(execCallee, error);
</span><span class="cx">             return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -1081,7 +1081,8 @@
</span><span class="cx">         codePtr = executable-&gt;entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
</span><span class="cx">     else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><del>-        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee-&gt;scope(), kind);
</del><ins>+        JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee, &amp;scope, kind);
+        execCallee-&gt;setScope(scope);
</ins><span class="cx">         if (error)
</span><span class="cx">             LLINT_CALL_THROW(execCallee-&gt;callerFrame(), error);
</span><span class="cx">         codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -769,14 +769,14 @@
</span><span class="cx">         : ExpressionNode(location)
</span><span class="cx">         , m_body(body)
</span><span class="cx">     {
</span><del>-        m_body-&gt;finishParsing(source, parameter, ident, FunctionNameIsInScope);
</del><ins>+        m_body-&gt;finishParsing(source, parameter, ident, FunctionExpression);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline FuncDeclNode::FuncDeclNode(const JSTokenLocation&amp; location, const Identifier&amp; ident, FunctionBodyNode* body, const SourceCode&amp; source, ParameterNode* parameter)
</span><span class="cx">         : StatementNode(location)
</span><span class="cx">         , m_body(body)
</span><span class="cx">     {
</span><del>-        m_body-&gt;finishParsing(source, parameter, ident, FunctionNameIsNotInScope);
</del><ins>+        m_body-&gt;finishParsing(source, parameter, ident, FunctionDeclaration);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline CaseClauseNode::CaseClauseNode(ExpressionNode* expr, SourceElements* statements)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/parser/Nodes.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -195,18 +195,18 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FunctionBodyNode::finishParsing(const SourceCode&amp; source, ParameterNode* firstParameter, const Identifier&amp; ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle)
</del><ins>+void FunctionBodyNode::finishParsing(const SourceCode&amp; source, ParameterNode* firstParameter, const Identifier&amp; ident, enum FunctionMode functionMode)
</ins><span class="cx"> {
</span><span class="cx">     setSource(source);
</span><del>-    finishParsing(FunctionParameters::create(firstParameter), ident, functionNameIsInScopeToggle);
</del><ins>+    finishParsing(FunctionParameters::create(firstParameter), ident, functionMode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FunctionBodyNode::finishParsing(PassRefPtr&lt;FunctionParameters&gt; parameters, const Identifier&amp; ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle)
</del><ins>+void FunctionBodyNode::finishParsing(PassRefPtr&lt;FunctionParameters&gt; parameters, const Identifier&amp; ident, enum FunctionMode functionMode)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!source().isNull());
</span><span class="cx">     m_parameters = parameters;
</span><span class="cx">     m_ident = ident;
</span><del>-    m_functionNameIsInScopeToggle = functionNameIsInScopeToggle;
</del><ins>+    m_functionMode = functionMode;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -1532,15 +1532,14 @@
</span><span class="cx"> 
</span><span class="cx">         virtual void emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="cx"> 
</span><del>-        void finishParsing(const SourceCode&amp;, ParameterNode*, const Identifier&amp;, FunctionNameIsInScopeToggle);
-        void finishParsing(PassRefPtr&lt;FunctionParameters&gt;, const Identifier&amp;, FunctionNameIsInScopeToggle);
</del><ins>+        void finishParsing(const SourceCode&amp;, ParameterNode*, const Identifier&amp;, FunctionMode);
+        void finishParsing(PassRefPtr&lt;FunctionParameters&gt;, const Identifier&amp;, FunctionMode);
</ins><span class="cx">         
</span><span class="cx">         const Identifier&amp; ident() { return m_ident; }
</span><span class="cx">         void setInferredName(const Identifier&amp; inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; }
</span><span class="cx">         const Identifier&amp; inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
</span><span class="cx"> 
</span><del>-        bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; }
-        FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; }
</del><ins>+        FunctionMode functionMode() { return m_functionMode; }
</ins><span class="cx"> 
</span><span class="cx">         void setFunctionNameStart(int functionNameStart) { m_functionNameStart = functionNameStart; }
</span><span class="cx">         int functionNameStart() const { return m_functionNameStart; }
</span><span class="lines">@@ -1557,7 +1556,7 @@
</span><span class="cx"> 
</span><span class="cx">         Identifier m_ident;
</span><span class="cx">         Identifier m_inferredName;
</span><del>-        FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
</del><ins>+        FunctionMode m_functionMode;
</ins><span class="cx">         RefPtr&lt;FunctionParameters&gt; m_parameters;
</span><span class="cx">         int m_functionNameStart;
</span><span class="cx">         unsigned m_startColumn;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserModesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ParserModes.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ParserModes.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/parser/ParserModes.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -27,6 +27,8 @@
</span><span class="cx"> #ifndef ParserModes_h
</span><span class="cx"> #define ParserModes_h
</span><span class="cx"> 
</span><ins>+#include &quot;Identifier.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> enum JSParserStrictness { JSParseNormal, JSParseStrict };
</span><span class="lines">@@ -35,8 +37,33 @@
</span><span class="cx"> enum ProfilerMode { ProfilerOff, ProfilerOn };
</span><span class="cx"> enum DebuggerMode { DebuggerOff, DebuggerOn };
</span><span class="cx"> 
</span><del>-enum FunctionNameIsInScopeToggle { FunctionNameIsNotInScope, FunctionNameIsInScope };
</del><ins>+enum FunctionMode { FunctionExpression, FunctionDeclaration };
</ins><span class="cx"> 
</span><ins>+inline bool functionNameIsInScope(const Identifier&amp; name, FunctionMode functionMode)
+{
+    if (name.isNull())
+        return false;
+
+    if (functionMode != FunctionExpression)
+        return false;
+
+    return true;
+}
+
+inline bool functionNameScopeIsDynamic(bool usesEval, bool isStrictMode)
+{
+    // If non-strict eval is in play, a function gets a separate object in the scope chain for its name.
+    // This enables eval to declare and then delete a name that shadows the function's name.
+
+    if (!usesEval)
+        return false;
+
+    if (isStrictMode)
+        return false;
+
+    return true;
+}
+
</ins><span class="cx"> typedef unsigned CodeFeatures;
</span><span class="cx"> 
</span><span class="cx"> const CodeFeatures NoFeatures = 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -75,14 +75,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData&amp; callData)
</del><ins>+static inline bool isNumericCompareFunction(ExecState* exec, JSValue function, CallType callType, const CallData&amp; callData)
</ins><span class="cx"> {
</span><span class="cx">     if (callType != CallTypeJS)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     FunctionExecutable* executable = callData.js.functionExecutable;
</span><ins>+    JSScope* scope = callData.js.scope;
</ins><span class="cx"> 
</span><del>-    JSObject* error = executable-&gt;prepareForExecution(exec, callData.js.scope, CodeForCall);
</del><ins>+    JSObject* error = executable-&gt;prepareForExecution(exec, jsCast&lt;JSFunction*&gt;(function), &amp;scope, CodeForCall);
</ins><span class="cx">     if (error)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="lines">@@ -614,7 +615,7 @@
</span><span class="cx">         || shouldUseSlowPut(thisObj-&gt;structure()-&gt;indexingType()))
</span><span class="cx">         return false;
</span><span class="cx">     
</span><del>-    if (isNumericCompareFunction(exec, callType, callData))
</del><ins>+    if (isNumericCompareFunction(exec, function, callType, callData))
</ins><span class="cx">         asArray(thisObj)-&gt;sortNumeric(exec, function, callType, callData);
</span><span class="cx">     else if (callType != CallTypeNone)
</span><span class="cx">         asArray(thisObj)-&gt;sort(exec, function, callType, callData);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/Executable.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -180,9 +180,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;CodeBlock&gt; ScriptExecutable::newCodeBlockFor(
</span><del>-    CodeSpecializationKind kind, JSScope* scope, JSObject*&amp; exception)
</del><ins>+    CodeSpecializationKind kind, JSFunction* function, JSScope** scope, JSObject*&amp; exception)
</ins><span class="cx"> {
</span><del>-    VM* vm = scope-&gt;vm();
</del><ins>+    VM* vm = (*scope)-&gt;vm();
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(vm-&gt;heap.isDeferred());
</span><span class="cx">     ASSERT(startColumn() != UINT_MAX);
</span><span class="lines">@@ -192,8 +192,9 @@
</span><span class="cx">         EvalExecutable* executable = jsCast&lt;EvalExecutable*&gt;(this);
</span><span class="cx">         RELEASE_ASSERT(kind == CodeForCall);
</span><span class="cx">         RELEASE_ASSERT(!executable-&gt;m_evalCodeBlock);
</span><ins>+        RELEASE_ASSERT(!function);
</ins><span class="cx">         return adoptRef(new EvalCodeBlock(
</span><del>-            executable, executable-&gt;m_unlinkedEvalCodeBlock.get(), scope,
</del><ins>+            executable, executable-&gt;m_unlinkedEvalCodeBlock.get(), *scope,
</ins><span class="cx">             executable-&gt;source().provider()));
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -201,15 +202,17 @@
</span><span class="cx">         ProgramExecutable* executable = jsCast&lt;ProgramExecutable*&gt;(this);
</span><span class="cx">         RELEASE_ASSERT(kind == CodeForCall);
</span><span class="cx">         RELEASE_ASSERT(!executable-&gt;m_programCodeBlock);
</span><ins>+        RELEASE_ASSERT(!function);
</ins><span class="cx">         return adoptRef(new ProgramCodeBlock(
</span><del>-            executable, executable-&gt;m_unlinkedProgramCodeBlock.get(), scope,
</del><ins>+            executable, executable-&gt;m_unlinkedProgramCodeBlock.get(), *scope,
</ins><span class="cx">             executable-&gt;source().provider(), executable-&gt;source().startColumn()));
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
</span><ins>+    RELEASE_ASSERT(function);
</ins><span class="cx">     FunctionExecutable* executable = jsCast&lt;FunctionExecutable*&gt;(this);
</span><span class="cx">     RELEASE_ASSERT(!executable-&gt;codeBlockFor(kind));
</span><del>-    JSGlobalObject* globalObject = scope-&gt;globalObject();
</del><ins>+    JSGlobalObject* globalObject = (*scope)-&gt;globalObject();
</ins><span class="cx">     ParserError error;
</span><span class="cx">     DebuggerMode debuggerMode = globalObject-&gt;hasDebugger() ? DebuggerOn : DebuggerOff;
</span><span class="cx">     ProfilerMode profilerMode = globalObject-&gt;hasProfiler() ? ProfilerOn : ProfilerOff;
</span><span class="lines">@@ -223,13 +226,21 @@
</span><span class="cx">             error.toErrorObject(globalObject, executable-&gt;m_source));
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><ins>+
+    // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
+    // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
+    if (!executable-&gt;m_didParseForTheFirstTime) {
+        executable-&gt;m_didParseForTheFirstTime = true;
+        function-&gt;addNameScopeIfNeeded(*vm);
+        *scope = function-&gt;scope();
+    }
</ins><span class="cx">     
</span><span class="cx">     SourceProvider* provider = executable-&gt;source().provider();
</span><span class="cx">     unsigned sourceOffset = executable-&gt;source().startOffset();
</span><span class="cx">     unsigned startColumn = executable-&gt;source().startColumn();
</span><span class="cx"> 
</span><span class="cx">     return adoptRef(new FunctionCodeBlock(
</span><del>-        executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
</del><ins>+        executable, unlinkedCodeBlock, *scope, provider, sourceOffset, startColumn));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;CodeBlock&gt; ScriptExecutable::newReplacementCodeBlockFor(
</span><span class="lines">@@ -291,13 +302,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSObject* ScriptExecutable::prepareForExecutionImpl(
</span><del>-    ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
</del><ins>+    ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><span class="cx">     
</span><span class="cx">     JSObject* exception = 0;
</span><del>-    RefPtr&lt;CodeBlock&gt; codeBlock = newCodeBlockFor(kind, scope, exception);
</del><ins>+    RefPtr&lt;CodeBlock&gt; codeBlock = newCodeBlockFor(kind, function, scope, exception);
</ins><span class="cx">     if (!codeBlock) {
</span><span class="cx">         RELEASE_ASSERT(exception);
</span><span class="cx">         return exception;
</span><span class="lines">@@ -376,6 +387,7 @@
</span><span class="cx">     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable-&gt;isInStrictContext())
</span><span class="cx">     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
</span><span class="cx">     , m_bodyIncludesBraces(bodyIncludesBraces)
</span><ins>+    , m_didParseForTheFirstTime(false)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!source.isNull());
</span><span class="cx">     ASSERT(source.length());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/Executable.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -419,18 +419,18 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void installCode(CodeBlock*);
</span><del>-    PassRefPtr&lt;CodeBlock&gt; newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*&amp; exception);
</del><ins>+    PassRefPtr&lt;CodeBlock&gt; newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope**, JSObject*&amp; exception);
</ins><span class="cx">     PassRefPtr&lt;CodeBlock&gt; newReplacementCodeBlockFor(CodeSpecializationKind);
</span><span class="cx">     
</span><del>-    JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
</del><ins>+    JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
</ins><span class="cx">     {
</span><span class="cx">         if (hasJITCodeFor(kind))
</span><span class="cx">             return 0;
</span><del>-        return prepareForExecutionImpl(exec, scope, kind);
</del><ins>+        return prepareForExecutionImpl(exec, function, scope, kind);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    JSObject* prepareForExecutionImpl(ExecState*, JSScope*, CodeSpecializationKind);
</del><ins>+    JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope**, CodeSpecializationKind);
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     void finishCreation(VM&amp; vm)
</span><span class="lines">@@ -629,6 +629,7 @@
</span><span class="cx">         return baselineCodeBlockFor(kind);
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    FunctionMode functionMode() { return m_unlinkedExecutable-&gt;functionMode(); }
</ins><span class="cx">     const Identifier&amp; name() { return m_unlinkedExecutable-&gt;name(); }
</span><span class="cx">     const Identifier&amp; inferredName() { return m_unlinkedExecutable-&gt;inferredName(); }
</span><span class="cx">     JSString* nameValue() const { return m_unlinkedExecutable-&gt;nameValue(); }
</span><span class="lines">@@ -673,6 +674,7 @@
</span><span class="cx">     RefPtr&lt;FunctionCodeBlock&gt; m_codeBlockForCall;
</span><span class="cx">     RefPtr&lt;FunctionCodeBlock&gt; m_codeBlockForConstruct;
</span><span class="cx">     bool m_bodyIncludesBraces;
</span><ins>+    bool m_didParseForTheFirstTime;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSBoundFunction.h&quot; 
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><ins>+#include &quot;JSNameScope.h&quot; 
</ins><span class="cx"> #include &quot;JSNotAnObject.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><span class="lines">@@ -109,6 +110,16 @@
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSFunction::addNameScopeIfNeeded(VM&amp; vm)
+{
+    FunctionExecutable* executable = jsCast&lt;FunctionExecutable*&gt;(m_executable.get());
+    if (!functionNameIsInScope(executable-&gt;name(), executable-&gt;functionMode()))
+        return;
+    if (!functionNameScopeIsDynamic(executable-&gt;usesEval(), executable-&gt;isStrictMode()))
+        return;
+    m_scope.set(vm, this, JSNameScope::create(vm, m_scope-&gt;globalObject(), executable-&gt;name(), this, ReadOnly | DontDelete, m_scope.get()));
+}
+
</ins><span class="cx"> ObjectAllocationProfile* JSFunction::createAllocationProfile(ExecState* exec, size_t inlineCapacity)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -93,6 +93,7 @@
</span><span class="cx">             ASSERT(!isHostFunctionNonInline());
</span><span class="cx">             m_scope.set(vm, this, scope);
</span><span class="cx">         }
</span><ins>+        void addNameScopeIfNeeded(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx">         ExecutableBase* executable() const { return m_executable.get(); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSNameScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSNameScope.h (163320 => 163321)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSNameScope.h        2014-02-03 20:34:39 UTC (rev 163320)
+++ trunk/Source/JavaScriptCore/runtime/JSNameScope.h        2014-02-03 20:39:38 UTC (rev 163321)
</span><span class="lines">@@ -39,15 +39,14 @@
</span><span class="cx">     static JSNameScope* create(ExecState* exec, const Identifier&amp; identifier, JSValue value, unsigned attributes)
</span><span class="cx">     {
</span><span class="cx">         VM&amp; vm = exec-&gt;vm();
</span><del>-        JSNameScope* scopeObject = new (NotNull, allocateCell&lt;JSNameScope&gt;(vm.heap)) JSNameScope(exec, exec-&gt;scope());
</del><ins>+        JSNameScope* scopeObject = new (NotNull, allocateCell&lt;JSNameScope&gt;(vm.heap)) JSNameScope(vm, exec-&gt;lexicalGlobalObject(), exec-&gt;scope());
</ins><span class="cx">         scopeObject-&gt;finishCreation(vm, identifier, value, attributes);
</span><span class="cx">         return scopeObject;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static JSNameScope* create(ExecState* exec, const Identifier&amp; identifier, JSValue value, unsigned attributes, JSScope* next)
</del><ins>+    static JSNameScope* create(VM&amp; vm, JSGlobalObject* globalObject, const Identifier&amp; identifier, JSValue value, unsigned attributes, JSScope* next)
</ins><span class="cx">     {
</span><del>-        VM&amp; vm = exec-&gt;vm();
-        JSNameScope* scopeObject = new (NotNull, allocateCell&lt;JSNameScope&gt;(vm.heap)) JSNameScope(exec, next);
</del><ins>+        JSNameScope* scopeObject = new (NotNull, allocateCell&lt;JSNameScope&gt;(vm.heap)) JSNameScope(vm, globalObject, next);
</ins><span class="cx">         scopeObject-&gt;finishCreation(vm, identifier, value, attributes);
</span><span class="cx">         return scopeObject;
</span><span class="cx">     }
</span><span class="lines">@@ -72,10 +71,10 @@
</span><span class="cx">     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | Base::StructureFlags;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    JSNameScope(ExecState* exec, JSScope* next)
</del><ins>+    JSNameScope(VM&amp; vm, JSGlobalObject* globalObject, JSScope* next)
</ins><span class="cx">         : Base(
</span><del>-            exec-&gt;vm(),
-            exec-&gt;lexicalGlobalObject()-&gt;nameScopeStructure(),
</del><ins>+            vm,
+            globalObject-&gt;nameScopeStructure(),
</ins><span class="cx">             reinterpret_cast&lt;Register*&gt;(&amp;m_registerStore + 1),
</span><span class="cx">             next
</span><span class="cx">         )
</span></span></pre>
</div>
</div>

</body>
</html>