<!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>[203364] 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/203364">203364</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-07-18 12:32:34 -0700 (Mon, 18 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>DFG and FTL should support op_call_eval
https://bugs.webkit.org/show_bug.cgi?id=159786

Reviewed by Saam Barati.
Source/JavaScriptCore:

        
This adds support for op_call_eval in DFG and FTL by brute force:
        
- There is now a CallEval() node type, which compiles exactly the same way that we do in
  baseline.
        
- We teach the DFG and bytecode liveness that the scope register and 'this' are read by
  CallEval()/op_call_eval.
        
We can compile eval quite well, except that right now we cannot inline functions that use
eval. It would be nice to do that, but the payoff is probably smaller. &quot;Don't inline users
of eval&quot; may even be an OK inlining heuristic. Not inlining users of eval allows me to
reuse the baseline implementation, which is really great. Otherwise, I'd have to get rid
of things like the rogue reads of scope register and 'this'.
        
The goal here is to produce speed-ups for code that has functions that do both eval and
some computational stuff. Obviously, we're not producing any benefit for the eval itself.
But now the other stuff in a function that uses eval will get to participate in
optimization.
        
This is a huge speed-up on microbenchmarks.

* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printCallOp):
(JSC::CodeBlock::dumpBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::setLocal):
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::flush):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::needsScopeRegister):
(JSC::DFG::Graph::needsFlushedThis):
* dfg/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGMayExit.cpp:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
* dfg/DFGNodeType.h:
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStackLayoutPhase.cpp:
(JSC::DFG::StackLayoutPhase::run):
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
(JSC::FTL::DFG::LowerDFGToB3::compileCallEval):
(JSC::FTL::DFG::LowerDFGToB3::compileLoadVarargs):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::emitDumbVirtualCall):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitTypeOf):
* jit/JITCall.cpp:
(JSC::JIT::compileCallEvalSlowCase):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileCallEvalSlowCase):
* jit/JITOperations.cpp:
* tests/stress/exit-then-eval.js: Added.
(foo):
* tests/stress/force-exit-then-eval-dfg.js: Added.
(foo):
* tests/stress/force-exit-then-eval.js: Added.
(foo):

LayoutTests:


* js/regress/eval-compute-expected.txt: Added.
* js/regress/eval-compute.html: Added.
* js/regress/eval-not-eval-compute-args-expected.txt: Added.
* js/regress/eval-not-eval-compute-args.html: Added.
* js/regress/eval-not-eval-compute-expected.txt: Added.
* js/regress/eval-not-eval-compute.html: Added.
* js/regress/script-tests/eval-compute.js: Added.
(foo):
* js/regress/script-tests/eval-not-eval-compute-args.js: Added.
(foo):
(i.result.foo):
* js/regress/script-tests/eval-not-eval-compute.js: Added.
(foo):
(i.result.foo):</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="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationcpp">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationh">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMayExitcpp">trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStackLayoutPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWatchpointCollectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressevalcomputeexpectedtxt">trunk/LayoutTests/js/regress/eval-compute-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressevalcomputehtml">trunk/LayoutTests/js/regress/eval-compute.html</a></li>
<li><a href="#trunkLayoutTestsjsregressevalnotevalcomputeargsexpectedtxt">trunk/LayoutTests/js/regress/eval-not-eval-compute-args-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressevalnotevalcomputeargshtml">trunk/LayoutTests/js/regress/eval-not-eval-compute-args.html</a></li>
<li><a href="#trunkLayoutTestsjsregressevalnotevalcomputeexpectedtxt">trunk/LayoutTests/js/regress/eval-not-eval-compute-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressevalnotevalcomputehtml">trunk/LayoutTests/js/regress/eval-not-eval-compute.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsevalcomputejs">trunk/LayoutTests/js/regress/script-tests/eval-compute.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsevalnotevalcomputeargsjs">trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute-args.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsevalnotevalcomputejs">trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexitthenevaljs">trunk/Source/JavaScriptCore/tests/stress/exit-then-eval.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressforceexitthenevaldfgjs">trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval-dfg.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressforceexitthenevaljs">trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/LayoutTests/ChangeLog        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2016-07-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG and FTL should support op_call_eval
+        https://bugs.webkit.org/show_bug.cgi?id=159786
+
+        Reviewed by Saam Barati.
+
+        * js/regress/eval-compute-expected.txt: Added.
+        * js/regress/eval-compute.html: Added.
+        * js/regress/eval-not-eval-compute-args-expected.txt: Added.
+        * js/regress/eval-not-eval-compute-args.html: Added.
+        * js/regress/eval-not-eval-compute-expected.txt: Added.
+        * js/regress/eval-not-eval-compute.html: Added.
+        * js/regress/script-tests/eval-compute.js: Added.
+        (foo):
+        * js/regress/script-tests/eval-not-eval-compute-args.js: Added.
+        (foo):
+        (i.result.foo):
+        * js/regress/script-tests/eval-not-eval-compute.js: Added.
+        (foo):
+        (i.result.foo):
+
</ins><span class="cx"> 2016-07-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DFG should really support jneq_ptr
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressevalcomputeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-compute-expected.txt (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-compute-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-compute-expected.txt        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/eval-compute
+
+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="trunkLayoutTestsjsregressevalcomputehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-compute.html (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-compute.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-compute.html        2016-07-18 19:32:34 UTC (rev 203364)
</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/eval-compute.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="trunkLayoutTestsjsregressevalnotevalcomputeargsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-not-eval-compute-args-expected.txt (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-not-eval-compute-args-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-not-eval-compute-args-expected.txt        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/eval-not-eval-compute-args
+
+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="trunkLayoutTestsjsregressevalnotevalcomputeargshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-not-eval-compute-args.html (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-not-eval-compute-args.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-not-eval-compute-args.html        2016-07-18 19:32:34 UTC (rev 203364)
</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/eval-not-eval-compute-args.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="trunkLayoutTestsjsregressevalnotevalcomputeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-not-eval-compute-expected.txt (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-not-eval-compute-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-not-eval-compute-expected.txt        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/eval-not-eval-compute
+
+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="trunkLayoutTestsjsregressevalnotevalcomputehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/eval-not-eval-compute.html (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/eval-not-eval-compute.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/eval-not-eval-compute.html        2016-07-18 19:32:34 UTC (rev 203364)
</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/eval-not-eval-compute.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="trunkLayoutTestsjsregressscripttestsevalcomputejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/eval-compute.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/eval-compute.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/eval-compute.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(string) {
+    var x = 42;
+    var result = eval(string);
+    for (var i = 0; i &lt; 100000; ++i)
+        result++;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 200; ++i) {
+    var result = foo(&quot;x + &quot; + i);
+    if (result != 42 + i + 100000)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsevalnotevalcomputeargsjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute-args.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute-args.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute-args.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(eval, a, b, c) {
+    var x = 42;
+    var result = eval(a, b, c);
+    for (var i = 0; i &lt; 100000; ++i)
+        result++;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 200; ++i) {
+    var result = foo(function(a, b, c) { return a + b + c; }, 42, i, 0);
+    if (result != 42 + i + 100000)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsevalnotevalcomputejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/eval-not-eval-compute.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(eval, string) {
+    var x = 42;
+    var result = eval(string);
+    for (var i = 0; i &lt; 100000; ++i)
+        result++;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 200; ++i) {
+    var result = foo(function() { return 42 + i; }, &quot;x + &quot; + i);
+    if (result != 42 + i + 100000)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1,3 +1,101 @@
</span><ins>+2016-07-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG and FTL should support op_call_eval
+        https://bugs.webkit.org/show_bug.cgi?id=159786
+
+        Reviewed by Saam Barati.
+        
+        This adds support for op_call_eval in DFG and FTL by brute force:
+        
+        - There is now a CallEval() node type, which compiles exactly the same way that we do in
+          baseline.
+        
+        - We teach the DFG and bytecode liveness that the scope register and 'this' are read by
+          CallEval()/op_call_eval.
+        
+        We can compile eval quite well, except that right now we cannot inline functions that use
+        eval. It would be nice to do that, but the payoff is probably smaller. &quot;Don't inline users
+        of eval&quot; may even be an OK inlining heuristic. Not inlining users of eval allows me to
+        reuse the baseline implementation, which is really great. Otherwise, I'd have to get rid
+        of things like the rogue reads of scope register and 'this'.
+        
+        The goal here is to produce speed-ups for code that has functions that do both eval and
+        some computational stuff. Obviously, we're not producing any benefit for the eval itself.
+        But now the other stuff in a function that uses eval will get to participate in
+        optimization.
+        
+        This is a huge speed-up on microbenchmarks.
+
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printCallOp):
+        (JSC::CodeBlock::dumpBytecode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::setLocal):
+        (JSC::DFG::ByteCodeParser::setArgument):
+        (JSC::DFG::ByteCodeParser::flush):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::needsScopeRegister):
+        (JSC::DFG::Graph::needsFlushedThis):
+        * dfg/DFGHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGHeapLocation.h:
+        * dfg/DFGMayExit.cpp:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasHeapPrediction):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRExitCompiler.cpp:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStackLayoutPhase.cpp:
+        (JSC::DFG::StackLayoutPhase::run):
+        * dfg/DFGWatchpointCollectionPhase.cpp:
+        (JSC::DFG::WatchpointCollectionPhase::handle):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallEval):
+        (JSC::FTL::DFG::LowerDFGToB3::compileLoadVarargs):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
+        (JSC::AssemblyHelpers::emitDumbVirtualCall):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::emitTypeOf):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileCallEvalSlowCase):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileCallEvalSlowCase):
+        * jit/JITOperations.cpp:
+        * tests/stress/exit-then-eval.js: Added.
+        (foo):
+        * tests/stress/force-exit-then-eval-dfg.js: Added.
+        (foo):
+        * tests/stress/force-exit-then-eval.js: Added.
+        (foo):
+
</ins><span class="cx"> 2016-07-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DFG should really support jneq_ptr
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -282,6 +282,8 @@
</span><span class="cx">         int lastArg = registerOffset + CallFrame::thisArgumentOffset();
</span><span class="cx">         for (int i = 0; i &lt; argCount; i++)
</span><span class="cx">             functor(codeBlock, instruction, opcodeID, lastArg + i);
</span><ins>+        if (opcodeID == op_call_eval)
+            functor(codeBlock, instruction, opcodeID, codeBlock-&gt;scopeRegister().offset());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     case op_save: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -529,7 +529,8 @@
</span><span class="cx">     int argCount = (++it)-&gt;u.operand;
</span><span class="cx">     int registerOffset = (++it)-&gt;u.operand;
</span><span class="cx">     printLocationAndOp(out, exec, location, it, op);
</span><del>-    out.printf(&quot;%s, %s, %d, %d&quot;, registerName(dst).data(), registerName(func).data(), argCount, registerOffset);
</del><ins>+    out.print(registerName(dst), &quot;, &quot;, registerName(func), &quot;, &quot;, argCount, &quot;, &quot;, registerOffset);
+    out.print(&quot; (this at &quot;, virtualRegisterForArgument(0, -registerOffset), &quot;)&quot;);
</ins><span class="cx">     if (cacheDumpMode == DumpCaches) {
</span><span class="cx">         LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
</span><span class="cx">         if (callLinkInfo-&gt;lastSeenCallee) {
</span><span class="lines">@@ -609,6 +610,7 @@
</span><span class="cx">         static_cast&lt;unsigned long&gt;(instructions().size()),
</span><span class="cx">         static_cast&lt;unsigned long&gt;(instructions().size() * sizeof(Instruction)),
</span><span class="cx">         m_numParameters, m_numCalleeLocals, m_numVars);
</span><ins>+    out.print(&quot;; scope at &quot;, scopeRegister());
</ins><span class="cx">     out.printf(&quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     StubInfoMap stubInfos;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -2801,7 +2801,6 @@
</span><span class="cx">         forNode(node).setType(m_graph, SpecObject);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-    case VarInjectionWatchpoint:
</del><span class="cx">     case PutGlobalVariable:
</span><span class="cx">     case NotifyWrite:
</span><span class="cx">         break;
</span><span class="lines">@@ -2847,6 +2846,7 @@
</span><span class="cx">     case ConstructVarargs:
</span><span class="cx">     case ConstructForwardVarargs:
</span><span class="cx">     case TailCallForwardVarargsInlinedCaller:
</span><ins>+    case CallEval:
</ins><span class="cx">         clobberWorld(node-&gt;origin.semantic, clobberLimit);
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -455,7 +455,7 @@
</span><span class="cx">             ArgumentPosition* argumentPosition = findArgumentPositionForLocal(operand);
</span><span class="cx">             if (argumentPosition)
</span><span class="cx">                 flushDirect(operand, argumentPosition);
</span><del>-            else if (m_hasDebuggerEnabled &amp;&amp; operand == m_codeBlock-&gt;scopeRegister())
</del><ins>+            else if (m_graph.needsScopeRegister() &amp;&amp; operand == m_codeBlock-&gt;scopeRegister())
</ins><span class="cx">                 flush(operand);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -511,10 +511,12 @@
</span><span class="cx"> 
</span><span class="cx">         // Always flush arguments, except for 'this'. If 'this' is created by us,
</span><span class="cx">         // then make sure that it's never unboxed.
</span><del>-        if (argument) {
</del><ins>+        if (argument || m_graph.needsFlushedThis()) {
</ins><span class="cx">             if (setMode != ImmediateNakedSet)
</span><span class="cx">                 flushDirect(operand);
</span><del>-        } else if (m_codeBlock-&gt;specializationKind() == CodeForConstruct)
</del><ins>+        }
+        
+        if (!argument &amp;&amp; m_codeBlock-&gt;specializationKind() == CodeForConstruct)
</ins><span class="cx">             variableAccessData-&gt;mergeShouldNeverUnbox(true);
</span><span class="cx">         
</span><span class="cx">         variableAccessData-&gt;mergeStructureCheckHoistingFailed(
</span><span class="lines">@@ -604,7 +606,9 @@
</span><span class="cx">             numArguments = inlineStackEntry-&gt;m_codeBlock-&gt;numParameters();
</span><span class="cx">         for (unsigned argument = numArguments; argument-- &gt; 1;)
</span><span class="cx">             flushDirect(inlineStackEntry-&gt;remapOperand(virtualRegisterForArgument(argument)));
</span><del>-        if (m_hasDebuggerEnabled)
</del><ins>+        if (!inlineStackEntry-&gt;m_inlineCallFrame &amp;&amp; m_graph.needsFlushedThis())
+            flushDirect(virtualRegisterForArgument(0));
+        if (m_graph.needsScopeRegister())
</ins><span class="cx">             flush(m_codeBlock-&gt;scopeRegister());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -4564,6 +4568,15 @@
</span><span class="cx">             NEXT_OPCODE(op_construct_varargs);
</span><span class="cx">         }
</span><span class="cx">             
</span><ins>+        case op_call_eval: {
+            int result = currentInstruction[1].u.operand;
+            int callee = currentInstruction[2].u.operand;
+            int argumentCountIncludingThis = currentInstruction[3].u.operand;
+            int registerOffset = -currentInstruction[4].u.operand;
+            addCall(result, CallEval, OpInfo(), get(VirtualRegister(callee)), argumentCountIncludingThis, registerOffset, getPrediction());
+            NEXT_OPCODE(op_call_eval);
+        }
+            
</ins><span class="cx">         case op_jneq_ptr: {
</span><span class="cx">             Special::Pointer specialPointer = currentInstruction[2].u.specialPointer;
</span><span class="cx">             ASSERT(pointerIsCell(specialPointer));
</span><span class="lines">@@ -4596,7 +4609,7 @@
</span><span class="cx"> 
</span><span class="cx">             // get_from_scope and put_to_scope depend on this watchpoint forcing OSR exit, so they don't add their own watchpoints.
</span><span class="cx">             if (needsVarInjectionChecks(resolveType))
</span><del>-                addToGraph(VarInjectionWatchpoint);
</del><ins>+                m_graph.watchpoints().addLazily(m_inlineStackTop-&gt;m_codeBlock-&gt;globalObject()-&gt;varInjectionWatchpoint());
</ins><span class="cx"> 
</span><span class="cx">             switch (resolveType) {
</span><span class="cx">             case GlobalProperty:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -244,6 +244,7 @@
</span><span class="cx"> 
</span><span class="cx">     case op_new_regexp:
</span><span class="cx">     case op_switch_string: // Don't inline because we don't want to copy string tables in the concurrent JIT.
</span><ins>+    case op_call_eval:
</ins><span class="cx">         return CanCompile;
</span><span class="cx"> 
</span><span class="cx">     default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -431,11 +431,6 @@
</span><span class="cx">         write(HeapObjectCount);
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    case VarInjectionWatchpoint:
-        read(MiscFields);
-        def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), LazyNode(node));
-        return;
-
</del><span class="cx">     case IsObjectOrNull:
</span><span class="cx">         read(MiscFields);
</span><span class="cx">         def(HeapLocation(IsObjectOrNullLoc, MiscFields, node-&gt;child1()), LazyNode(node));
</span><span class="lines">@@ -484,6 +479,14 @@
</span><span class="cx">         write(Heap);
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    case CallEval:
+        ASSERT(!node-&gt;origin.semantic.inlineCallFrame);
+        read(AbstractHeap(Stack, graph.m_codeBlock-&gt;scopeRegister()));
+        read(AbstractHeap(Stack, virtualRegisterForArgument(0)));
+        read(World);
+        write(Heap);
+        return;
+
</ins><span class="cx">     case TailCall:
</span><span class="cx">     case TailCallVarargs:
</span><span class="cx">     case TailCallForwardVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -127,7 +127,6 @@
</span><span class="cx">     case GetGlobalVar:
</span><span class="cx">     case GetGlobalLexicalVariable:
</span><span class="cx">     case PutGlobalVariable:
</span><del>-    case VarInjectionWatchpoint:
</del><span class="cx">     case CheckCell:
</span><span class="cx">     case CheckNotEmpty:
</span><span class="cx">     case CheckIdent:
</span><span class="lines">@@ -144,6 +143,7 @@
</span><span class="cx">     case TailCallInlinedCaller:
</span><span class="cx">     case Construct:
</span><span class="cx">     case CallVarargs:
</span><ins>+    case CallEval:
</ins><span class="cx">     case TailCallVarargsInlinedCaller:
</span><span class="cx">     case ConstructVarargs:
</span><span class="cx">     case LoadVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1535,12 +1535,12 @@
</span><span class="cx">         case GetGlobalVar:
</span><span class="cx">         case GetGlobalLexicalVariable:
</span><span class="cx">         case NotifyWrite:
</span><del>-        case VarInjectionWatchpoint:
</del><span class="cx">         case Call:
</span><span class="cx">         case CheckTypeInfoFlags:
</span><span class="cx">         case TailCallInlinedCaller:
</span><span class="cx">         case Construct:
</span><span class="cx">         case CallVarargs:
</span><ins>+        case CallEval:
</ins><span class="cx">         case TailCallVarargsInlinedCaller:
</span><span class="cx">         case ConstructVarargs:
</span><span class="cx">         case CallForwardVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -813,6 +813,9 @@
</span><span class="cx">     // because it queries the m_hasExceptionHandlers boolean whose value
</span><span class="cx">     // is only fully determined after bytcode parsing.
</span><span class="cx">     bool willCatchExceptionInMachineFrame(CodeOrigin, CodeOrigin&amp; opCatchOriginOut, HandlerInfo*&amp; catchHandlerOut);
</span><ins>+    
+    bool needsScopeRegister() const { return m_hasDebuggerEnabled || m_codeBlock-&gt;usesEval(); }
+    bool needsFlushedThis() const { return m_codeBlock-&gt;usesEval(); }
</ins><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     Plan&amp; m_plan;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -136,10 +136,6 @@
</span><span class="cx">         out.print(&quot;TypedArrayByteOffsetLoc&quot;);
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case VarInjectionWatchpointLoc:
-        out.print(&quot;VarInjectionWatchpointLoc&quot;);
-        return;
-        
</del><span class="cx">     case StructureLoc:
</span><span class="cx">         out.print(&quot;StructureLoc&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -57,7 +57,6 @@
</span><span class="cx">     SetterLoc,
</span><span class="cx">     StructureLoc,
</span><span class="cx">     TypedArrayByteOffsetLoc,
</span><del>-    VarInjectionWatchpointLoc,
</del><span class="cx">     StackLoc,
</span><span class="cx">     StackPayloadLoc
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -96,6 +96,7 @@
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span><span class="cx">     case CallVarargs:
</span><ins>+    case CallEval:
</ins><span class="cx">     case ConstructVarargs:
</span><span class="cx">     case CallForwardVarargs:
</span><span class="cx">     case ConstructForwardVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1423,6 +1423,7 @@
</span><span class="cx">         case TailCallInlinedCaller:
</span><span class="cx">         case Construct:
</span><span class="cx">         case CallVarargs:
</span><ins>+        case CallEval:
</ins><span class="cx">         case TailCallVarargsInlinedCaller:
</span><span class="cx">         case ConstructVarargs:
</span><span class="cx">         case CallForwardVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -232,7 +232,6 @@
</span><span class="cx">     macro(GetDynamicVar, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(PutDynamicVar, NodeMustGenerate) \
</span><span class="cx">     macro(NotifyWrite, NodeMustGenerate) \
</span><del>-    macro(VarInjectionWatchpoint, NodeMustGenerate) \
</del><span class="cx">     macro(GetRegExpObjectLastIndex, NodeResultJS) \
</span><span class="cx">     macro(SetRegExpObjectLastIndex, NodeMustGenerate) \
</span><span class="cx">     macro(RecordRegExpCachedResult, NodeMustGenerate | NodeHasVarArgs) \
</span><span class="lines">@@ -277,6 +276,7 @@
</span><span class="cx">     macro(TailCallInlinedCaller, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
</span><span class="cx">     macro(TailCallVarargsInlinedCaller, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(TailCallForwardVarargsInlinedCaller, NodeResultJS | NodeMustGenerate) \
</span><ins>+    macro(CallEval, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
</ins><span class="cx">     \
</span><span class="cx">     /* Shadow Chicken */\
</span><span class="cx">     macro(LogShadowChickenPrologue, NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2013, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -153,9 +153,10 @@
</span><span class="cx">             // So, we must restore our call frame and stack pointer.
</span><span class="cx">             jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
</span><span class="cx">             jit.loadPtr(vm-&gt;addressOfCallFrameForCatch(), GPRInfo::callFrameRegister);
</span><del>-            jit.addPtr(CCallHelpers::TrustedImm32(codeBlock-&gt;stackPointerOffset() * sizeof(Register)),
-                GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
</del><span class="cx">         }
</span><ins>+        jit.addPtr(
+            CCallHelpers::TrustedImm32(codeBlock-&gt;stackPointerOffset() * sizeof(Register)),
+            GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
</ins><span class="cx"> 
</span><span class="cx">         jit.jitAssertHasValidCallFrame();
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -704,6 +704,7 @@
</span><span class="cx">         case TailCallInlinedCaller:
</span><span class="cx">         case Construct:
</span><span class="cx">         case CallVarargs:
</span><ins>+        case CallEval:
</ins><span class="cx">         case TailCallVarargsInlinedCaller:
</span><span class="cx">         case ConstructVarargs:
</span><span class="cx">         case CallForwardVarargs:
</span><span class="lines">@@ -1047,7 +1048,6 @@
</span><span class="cx">         case CheckIdent:
</span><span class="cx">         case CheckBadCell:
</span><span class="cx">         case PutStructure:
</span><del>-        case VarInjectionWatchpoint:
</del><span class="cx">         case Phantom:
</span><span class="cx">         case Check:
</span><span class="cx">         case PutGlobalVariable:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -222,7 +222,6 @@
</span><span class="cx">     case GetGlobalVar:
</span><span class="cx">     case GetGlobalLexicalVariable:
</span><span class="cx">     case PutGlobalVariable:
</span><del>-    case VarInjectionWatchpoint:
</del><span class="cx">     case CheckCell:
</span><span class="cx">     case CheckBadCell:
</span><span class="cx">     case CheckNotEmpty:
</span><span class="lines">@@ -240,6 +239,7 @@
</span><span class="cx">     case TailCallInlinedCaller:
</span><span class="cx">     case Construct:
</span><span class="cx">     case CallVarargs:
</span><ins>+    case CallEval:
</ins><span class="cx">     case TailCallVarargsInlinedCaller:
</span><span class="cx">     case TailCallForwardVarargsInlinedCaller:
</span><span class="cx">     case ConstructVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -660,6 +660,7 @@
</span><span class="cx">     bool isEmulatedTail = false;
</span><span class="cx">     switch (node-&gt;op()) {
</span><span class="cx">     case Call:
</span><ins>+    case CallEval:
</ins><span class="cx">         callType = CallLinkInfo::Call;
</span><span class="cx">         break;
</span><span class="cx">     case TailCall:
</span><span class="lines">@@ -879,7 +880,50 @@
</span><span class="cx">     m_jit.emitStoreCallSiteIndex(callSite);
</span><span class="cx">     
</span><span class="cx">     CallLinkInfo* info = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><ins>+    info-&gt;setUpCall(callType, node-&gt;origin.semantic, calleePayloadGPR);
+    
+    auto setResultAndResetStack = [&amp;] () {
+        m_jit.setupResults(resultPayloadGPR, resultTagGPR);
</ins><span class="cx"> 
</span><ins>+        jsValueResult(resultTagGPR, resultPayloadGPR, node, DataFormatJS, UseChildrenCalledExplicitly);
+        // After the calls are done, we need to reestablish our stack
+        // pointer. We rely on this for varargs calls, calls with arity
+        // mismatch (the callframe is slided) and tail calls.
+        m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
+    };
+    
+    if (node-&gt;op() == CallEval) {
+        // We want to call operationCallEval but we don't want to overwrite the parameter area in
+        // which we have created a prototypical eval call frame. This means that we have to
+        // subtract stack to make room for the call. Lucky for us, at this point we have the whole
+        // register file to ourselves.
+        
+        m_jit.addPtr(TrustedImm32(-static_cast&lt;ptrdiff_t&gt;(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
+        m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
+        
+        // Now we need to make room for:
+        // - The caller frame and PC of a call to operationCallEval.
+        // - Potentially two arguments on the stack.
+        unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
+        requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
+        m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
+        m_jit.setupArgumentsWithExecState(GPRInfo::regT0);
+        prepareForExternalCall();
+        m_jit.appendCall(operationCallEval);
+        m_jit.exceptionCheck();
+        JITCompiler::Jump done = m_jit.branch32(JITCompiler::NotEqual, GPRInfo::returnValueGPR2, TrustedImm32(JSValue::EmptyValueTag));
+        
+        // This is the part where we meant to make a normal call. Oops.
+        m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
+        m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(PayloadOffset), GPRInfo::regT0);
+        m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(TagOffset), GPRInfo::regT1);
+        m_jit.emitDumbVirtualCall(info);
+        
+        done.link(&amp;m_jit);
+        setResultAndResetStack();
+        return;
+    }
+
</ins><span class="cx">     slowPath.append(m_jit.branchIfNotCell(JSValueRegs(calleeTagGPR, calleePayloadGPR)));
</span><span class="cx">     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
</span><span class="cx"> 
</span><span class="lines">@@ -929,17 +973,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (isTail)
</span><span class="cx">         m_jit.abortWithReason(JITDidReturnFromTailCall);
</span><del>-    else {
-        m_jit.setupResults(resultPayloadGPR, resultTagGPR);
</del><ins>+    else
+        setResultAndResetStack();
</ins><span class="cx"> 
</span><del>-        jsValueResult(resultTagGPR, resultPayloadGPR, node, DataFormatJS, UseChildrenCalledExplicitly);
-        // After the calls are done, we need to reestablish our stack
-        // pointer. We rely on this for varargs calls, calls with arity
-        // mismatch (the callframe is slided) and tail calls.
-        m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
-    }
-
-    info-&gt;setUpCall(callType, node-&gt;origin.semantic, calleePayloadGPR);
</del><span class="cx">     m_jit.addJSCall(fastCall, slowCall, targetToCheck, info);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -4591,11 +4627,6 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case VarInjectionWatchpoint: {
-        noResult(node);
-        break;
-    }
-
</del><span class="cx">     case CheckTypeInfoFlags: {
</span><span class="cx">         compileCheckTypeInfoFlags(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -4803,6 +4834,7 @@
</span><span class="cx">     case TailCallForwardVarargs:
</span><span class="cx">     case TailCallForwardVarargsInlinedCaller:
</span><span class="cx">     case ConstructForwardVarargs:
</span><ins>+    case CallEval:
</ins><span class="cx">         emitCall(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -635,6 +635,7 @@
</span><span class="cx">     bool isEmulatedTail = false;
</span><span class="cx">     switch (node-&gt;op()) {
</span><span class="cx">     case Call:
</span><ins>+    case CallEval:
</ins><span class="cx">         callType = CallLinkInfo::Call;
</span><span class="cx">         break;
</span><span class="cx">     case TailCall:
</span><span class="lines">@@ -838,8 +839,53 @@
</span><span class="cx">     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream-&gt;size());
</span><span class="cx">     m_jit.emitStoreCallSiteIndex(callSite);
</span><span class="cx">     
</span><ins>+    auto setResultAndResetStack = [&amp;] () {
+        GPRFlushedCallResult result(this);
+        GPRReg resultGPR = result.gpr();
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+
+        jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
+
+        // After the calls are done, we need to reestablish our stack
+        // pointer. We rely on this for varargs calls, calls with arity
+        // mismatch (the callframe is slided) and tail calls.
+        m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
+    };
+    
</ins><span class="cx">     CallLinkInfo* callLinkInfo = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><ins>+    callLinkInfo-&gt;setUpCall(callType, m_currentNode-&gt;origin.semantic, calleeGPR);
</ins><span class="cx"> 
</span><ins>+    if (node-&gt;op() == CallEval) {
+        // We want to call operationCallEval but we don't want to overwrite the parameter area in
+        // which we have created a prototypical eval call frame. This means that we have to
+        // subtract stack to make room for the call. Lucky for us, at this point we have the whole
+        // register file to ourselves.
+        
+        m_jit.addPtr(TrustedImm32(-static_cast&lt;ptrdiff_t&gt;(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
+        m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
+        
+        // Now we need to make room for:
+        // - The caller frame and PC of a call to operationCallEval.
+        // - Potentially two arguments on the stack.
+        unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
+        requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
+        m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
+        m_jit.setupArgumentsWithExecState(GPRInfo::regT0);
+        prepareForExternalCall();
+        m_jit.appendCall(operationCallEval);
+        m_jit.exceptionCheck();
+        JITCompiler::Jump done = m_jit.branchTest64(JITCompiler::NonZero, GPRInfo::returnValueGPR);
+        
+        // This is the part where we meant to make a normal call. Oops.
+        m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
+        m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
+        m_jit.emitDumbVirtualCall(callLinkInfo);
+        
+        done.link(&amp;m_jit);
+        setResultAndResetStack();
+        return;
+    }
+    
</ins><span class="cx">     JITCompiler::DataLabelPtr targetToCheck;
</span><span class="cx">     JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
</span><span class="cx"> 
</span><span class="lines">@@ -877,20 +923,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (isTail)
</span><span class="cx">         m_jit.abortWithReason(JITDidReturnFromTailCall);
</span><del>-    else {
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
</del><ins>+    else
+        setResultAndResetStack();
</ins><span class="cx"> 
</span><del>-        jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
-
-        // After the calls are done, we need to reestablish our stack
-        // pointer. We rely on this for varargs calls, calls with arity
-        // mismatch (the callframe is slided) and tail calls.
-        m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
-    }
-
-    callLinkInfo-&gt;setUpCall(callType, m_currentNode-&gt;origin.semantic, calleeGPR);
</del><span class="cx">     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -4506,11 +4541,6 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case VarInjectionWatchpoint: {
-        noResult(node);
-        break;
-    }
-
</del><span class="cx">     case CheckTypeInfoFlags: {
</span><span class="cx">         compileCheckTypeInfoFlags(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -4721,6 +4751,7 @@
</span><span class="cx">     case ConstructForwardVarargs:
</span><span class="cx">     case TailCallForwardVarargs:
</span><span class="cx">     case TailCallForwardVarargsInlinedCaller:
</span><ins>+    case CallEval:
</ins><span class="cx">         emitCall(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStackLayoutPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -173,7 +173,7 @@
</span><span class="cx">             data-&gt;machineLocal = assign(allocation, data-&gt;local);
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        if (LIKELY(!m_graph.hasDebuggerEnabled()))
</del><ins>+        if (!m_graph.needsScopeRegister())
</ins><span class="cx">             codeBlock()-&gt;setScopeRegister(VirtualRegister());
</span><span class="cx">         else
</span><span class="cx">             codeBlock()-&gt;setScopeRegister(assign(allocation, codeBlock()-&gt;scopeRegister()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWatchpointCollectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -97,10 +97,6 @@
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">             
</span><del>-        case VarInjectionWatchpoint:
-            addLazily(globalObject()-&gt;varInjectionWatchpoint());
-            break;
-            
</del><span class="cx">         default:
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -142,6 +142,7 @@
</span><span class="cx">     case TailCallInlinedCaller:
</span><span class="cx">     case Construct:
</span><span class="cx">     case CallVarargs:
</span><ins>+    case CallEval:
</ins><span class="cx">     case TailCallVarargs:
</span><span class="cx">     case TailCallVarargsInlinedCaller:
</span><span class="cx">     case ConstructVarargs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -105,7 +105,10 @@
</span><span class="cx"> 
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (graph.hasDebuggerEnabled())
</del><ins>+    // Note that the scope register could be invalid here if the original code had CallEval but it
+    // got killed. That's because it takes the CallEval to cause the scope register to be kept alive
+    // unless the debugger is also enabled.
+    if (graph.needsScopeRegister() &amp;&amp; codeBlock-&gt;scopeRegister().isValid())
</ins><span class="cx">         codeBlock-&gt;setScopeRegister(codeBlock-&gt;scopeRegister() + localsOffset);
</span><span class="cx"> 
</span><span class="cx">     for (OSRExitDescriptor&amp; descriptor : state.jitCode-&gt;osrExitDescriptors) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -843,6 +843,9 @@
</span><span class="cx">         case ConstructForwardVarargs:
</span><span class="cx">             compileCallOrConstructVarargs();
</span><span class="cx">             break;
</span><ins>+        case CallEval:
+            compileCallEval();
+            break;
</ins><span class="cx">         case LoadVarargs:
</span><span class="cx">             compileLoadVarargs();
</span><span class="cx">             break;
</span><span class="lines">@@ -5543,6 +5546,90 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileCallEval()
+    {
+        Node* node = m_node;
+        unsigned numArgs = node-&gt;numChildren() - 1;
+        
+        LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0));
+        
+        unsigned frameSize = CallFrame::headerSizeInRegisters + numArgs;
+        unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize);
+        
+        m_proc.requestCallArgAreaSize(alignedFrameSize);
+        
+        Vector&lt;ConstrainedValue&gt; arguments;
+        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
+        
+        auto addArgument = [&amp;] (LValue value, VirtualRegister reg, int offset) {
+            intptr_t offsetFromSP = 
+                (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset;
+            arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
+        };
+        
+        addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
+        addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
+        for (unsigned i = 0; i &lt; numArgs; ++i)
+            addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
+        
+        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint-&gt;appendVector(arguments);
+        
+        RefPtr&lt;PatchpointExceptionHandle&gt; exceptionHandle = preparePatchpointForExceptions(patchpoint);
+        
+        patchpoint-&gt;append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
+        patchpoint-&gt;append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
+        patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
+        patchpoint-&gt;clobberLate(RegisterSet::volatileRegistersForJSCall());
+        patchpoint-&gt;resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
+        
+        CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
+        State* state = &amp;m_ftlState;
+        patchpoint-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+                CallSiteIndex callSiteIndex = state-&gt;jitCode-&gt;common.addUniqueCallSiteIndex(codeOrigin);
+                
+                Box&lt;CCallHelpers::JumpList&gt; exceptions = exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
+                
+                exceptionHandle-&gt;scheduleExitCreationForUnwind(params, callSiteIndex);
+                
+                jit.store32(
+                    CCallHelpers::TrustedImm32(callSiteIndex.bits()),
+                    CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
+                
+                CallLinkInfo* callLinkInfo = jit.codeBlock()-&gt;addCallLinkInfo();
+                callLinkInfo-&gt;setUpCall(CallLinkInfo::Call, node-&gt;origin.semantic, GPRInfo::regT0);
+                
+                jit.addPtr(CCallHelpers::TrustedImm32(-static_cast&lt;ptrdiff_t&gt;(sizeof(CallerFrameAndPC))), CCallHelpers::stackPointerRegister, GPRInfo::regT1);
+                jit.storePtr(GPRInfo::callFrameRegister, CCallHelpers::Address(GPRInfo::regT1, CallFrame::callerFrameOffset()));
+                
+                // Now we need to make room for:
+                // - The caller frame and PC for a call to operationCallEval.
+                // - Potentially two arguments on the stack.
+                unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
+                requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
+                jit.subPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister);
+                jit.setupArgumentsWithExecState(GPRInfo::regT1);
+                jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(operationCallEval)), GPRInfo::nonPreservedNonArgumentGPR);
+                jit.call(GPRInfo::nonPreservedNonArgumentGPR);
+                exceptions-&gt;append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
+                
+                CCallHelpers::Jump done = jit.branchTest64(CCallHelpers::NonZero, GPRInfo::returnValueGPR);
+                
+                jit.addPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister);
+                jit.load64(CCallHelpers::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
+                jit.emitDumbVirtualCall(callLinkInfo);
+                
+                done.link(&amp;jit);
+                jit.addPtr(
+                    CCallHelpers::TrustedImm32(-params.proc().frameSize()),
+                    GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
+            });
+        
+        setJSValue(patchpoint);
+    }
+    
</ins><span class="cx">     void compileLoadVarargs()
</span><span class="cx">     {
</span><span class="cx">         LoadVarargsData* data = m_node-&gt;loadVarargsData();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JITOperations.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;LinkBuffer.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -613,6 +614,18 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AssemblyHelpers::emitDumbVirtualCall(CallLinkInfo* info)
+{
+    move(TrustedImmPtr(info), GPRInfo::regT2);
+    Call call = nearCall();
+    addLinkTask(
+        [=] (LinkBuffer&amp; linkBuffer) {
+            MacroAssemblerCodeRef virtualThunk = virtualThunkFor(&amp;linkBuffer.vm(), *info);
+            info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, linkBuffer.vm(), nullptr, true));
+            linkBuffer.link(call, CodeLocationLabel(virtualThunk.code()));
+        });
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -165,9 +165,20 @@
</span><span class="cx">     void moveValueRegs(JSValueRegs srcRegs, JSValueRegs destRegs)
</span><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><ins>+        if (destRegs.tagGPR() == srcRegs.payloadGPR()) {
+            if (destRegs.payloadGPR() == srcRegs.tagGPR()) {
+                swap(srcRegs.payloadGPR(), srcRegs.tagGPR());
+                return;
+            }
+            move(srcRegs.payloadGPR(), destRegs.payloadGPR());
+            move(srcRegs.tagGPR(), destRegs.tagGPR());
+            return;
+        }
</ins><span class="cx">         move(srcRegs.tagGPR(), destRegs.tagGPR());
</span><ins>+        move(srcRegs.payloadGPR(), destRegs.payloadGPR());
+#else
+        move(srcRegs.gpr(), destRegs.gpr());
</ins><span class="cx"> #endif
</span><del>-        move(srcRegs.payloadGPR(), destRegs.payloadGPR());
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void moveValue(JSValue value, JSValueRegs regs)
</span><span class="lines">@@ -1380,7 +1391,9 @@
</span><span class="cx">         
</span><span class="cx">         functor(TypeofType::Undefined, true);
</span><span class="cx">     }
</span><del>-
</del><ins>+    
+    void emitDumbVirtualCall(CallLinkInfo*);
+    
</ins><span class="cx">     Vector&lt;BytecodeAndMachineOffset&gt;&amp; decodedCodeMapFor(CodeBlock*);
</span><span class="cx"> 
</span><span class="cx">     void makeSpaceOnStackForCCall();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -124,14 +124,7 @@
</span><span class="cx">     addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span><span class="cx">     load64(Address(stackPointerRegister, sizeof(Register) * CallFrameSlot::callee - sizeof(CallerFrameAndPC)), regT0);
</span><del>-    move(TrustedImmPtr(info), regT2);
-    Call call = emitNakedCall();
-    addLinkTask(
-        [=] (LinkBuffer&amp; linkBuffer) {
-            MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
-            info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
-            linkBuffer.link(call, CodeLocationLabel(virtualThunk.code()));
-        });
</del><ins>+    emitDumbVirtualCall(info);
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -214,8 +214,6 @@
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span><del>-    loadPtr(Address(stackPointerRegister, sizeof(Register) * CallFrameSlot::callee - sizeof(CallerFrameAndPC)), regT0);
-    loadPtr(Address(stackPointerRegister, sizeof(Register) * CallFrameSlot::callee - sizeof(CallerFrameAndPC)), regT1);
</del><span class="cx">     move(TrustedImmPtr(info), regT2);
</span><span class="cx"> 
</span><span class="cx">     emitLoad(CallFrameSlot::callee, regT1, regT0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (203363 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-18 19:23:41 UTC (rev 203363)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -772,7 +772,7 @@
</span><span class="cx">     UNUSED_PARAM(exec);
</span><span class="cx"> 
</span><span class="cx">     execCallee-&gt;setCodeBlock(0);
</span><del>-
</del><ins>+    
</ins><span class="cx">     if (!isHostFunction(execCallee-&gt;calleeAsValue(), globalFuncEval))
</span><span class="cx">         return JSValue::encode(JSValue());
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexitthenevaljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exit-then-eval.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exit-then-eval.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exit-then-eval.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+function foo(a, b, string)
+{
+    var x = a + b;
+    return eval(string);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(1, 2, &quot;x + 1&quot;);
+    if (result != 1 + 2 + 1)
+        throw &quot;Error: bad result in loop: &quot; + result;
+}
+
+var result = foo(2000000000, 2000000000, &quot;x - 1&quot;);
+if (result != 2000000000 + 2000000000 - 1)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressforceexitthenevaldfgjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval-dfg.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval-dfg.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval-dfg.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+function foo(a, b, string)
+{
+    OSRExit();
+    return eval(string);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(1, 2, &quot;a + b + 1&quot;);
+    if (result != 1 + 2 + 1)
+        throw &quot;Error: bad result in loop: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressforceexitthenevaljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval.js (0 => 203364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/force-exit-then-eval.js        2016-07-18 19:32:34 UTC (rev 203364)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+var flag = true;
+flag = false;
+
+function foo(a, b, string)
+{
+    var x = a + b;
+    if (flag)
+        return eval(string);
+    return 42;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(1, 2, &quot;x + 1&quot;);
+    if (result != 42)
+        throw &quot;Error: bad result in loop: &quot; + result;
+}
+
+flag = true;
+var result = foo(1, 2, &quot;x - 1&quot;);
+if (result != 1 + 2 - 1)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre>
</div>
</div>

</body>
</html>