<!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>[161732] branches/jsCStack/Source/JavaScriptCore</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>FTL should enough things to compile inlined closure calls (like CheckExecutable and GetScope)
https://bugs.webkit.org/show_bug.cgi?id=126799

Reviewed by Oliver Hunt.
        
Added FTL support for CheckExecutable and GetScope because I wanted to compile
closure calls. But then I realized that closure call inlining was broken because
the baseline JIT would link the closure stubs to the slow path, thereby causing
the DFG's profiling to think that all closure calls are actually virtual calls.
        
Also fixed some hash() computing stuff to make debugging easier.

* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
(JSC::FTL::LowerDFGToLLVM::compileGetScope):
* jit/Repatch.cpp:
(JSC::linkClosureCall):
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
(JSC::Options::initialize):
(JSC::Options::setOption):
* tests/stress/inline-closure-call.js: Added.
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreChangeLog">branches/jsCStack/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRepatchcpp">branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp">branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoretestsstressinlineclosurecalljs">branches/jsCStack/Source/JavaScriptCore/tests/stress/inline-closure-call.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsCStackSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ChangeLog (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -1,5 +1,35 @@
</span><span class="cx"> 2014-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        FTL should enough things to compile inlined closure calls (like CheckExecutable and GetScope)
+        https://bugs.webkit.org/show_bug.cgi?id=126799
+
+        Reviewed by Oliver Hunt.
+        
+        Added FTL support for CheckExecutable and GetScope because I wanted to compile
+        closure calls. But then I realized that closure call inlining was broken because
+        the baseline JIT would link the closure stubs to the slow path, thereby causing
+        the DFG's profiling to think that all closure calls are actually virtual calls.
+        
+        Also fixed some hash() computing stuff to make debugging easier.
+
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
+        (JSC::FTL::LowerDFGToLLVM::compileGetScope):
+        * jit/Repatch.cpp:
+        (JSC::linkClosureCall):
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        (JSC::Options::initialize):
+        (JSC::Options::setOption):
+        * tests/stress/inline-closure-call.js: Added.
+        (bar):
+
+2014-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         It should be easier to diagnose FTL performance issues due to register preservation thunks
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=126798
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx">     macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
</span><span class="cx">     macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
</span><span class="cx">     macro(JSCell_structure, JSCell::structureOffset()) \
</span><ins>+    macro(JSFunction_executable, JSFunction::offsetOfExecutable()) \
+    macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
</ins><span class="cx">     macro(JSObject_butterfly, JSObject::butterflyOffset()) \
</span><span class="cx">     macro(JSScope_next, JSScope::offsetOfNext()) \
</span><span class="cx">     macro(JSString_length, JSString::offsetOfLength()) \
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -116,6 +116,8 @@
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><ins>+    case CheckExecutable:
+    case GetScope:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx">     case GetById:
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -353,6 +353,9 @@
</span><span class="cx">         case CheckFunction:
</span><span class="cx">             compileCheckFunction();
</span><span class="cx">             break;
</span><ins>+        case CheckExecutable:
+            compileCheckExecutable();
+            break;
</ins><span class="cx">         case ArrayifyToStructure:
</span><span class="cx">             compileArrayifyToStructure();
</span><span class="cx">             break;
</span><span class="lines">@@ -427,6 +430,9 @@
</span><span class="cx">         case NotifyWrite:
</span><span class="cx">             compileNotifyWrite();
</span><span class="cx">             break;
</span><ins>+        case GetScope:
+            compileGetScope();
+            break;
</ins><span class="cx">         case GetMyScope:
</span><span class="cx">             compileGetMyScope();
</span><span class="cx">             break;
</span><span class="lines">@@ -1333,6 +1339,17 @@
</span><span class="cx">             m_out.notEqual(cell, weakPointer(m_node-&gt;function())));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileCheckExecutable()
+    {
+        LValue cell = lowCell(m_node-&gt;child1());
+        
+        speculate(
+            BadExecutable, jsValueValue(cell), m_node-&gt;child1().node(),
+            m_out.notEqual(
+                m_out.loadPtr(cell, m_heaps.JSFunction_executable),
+                weakPointer(m_node-&gt;function())));
+    }
+    
</ins><span class="cx">     void compileArrayifyToStructure()
</span><span class="cx">     {
</span><span class="cx">         LValue cell = lowCell(m_node-&gt;child1());
</span><span class="lines">@@ -2403,6 +2420,11 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileGetScope()
+    {
+        setJSValue(m_out.loadPtr(lowCell(m_node-&gt;child1()), m_heaps.JSFunction_scope));
+    }
+    
</ins><span class="cx">     void compileGetMyScope()
</span><span class="cx">     {
</span><span class="cx">         setJSValue(m_out.loadPtr(addressFor(
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -1406,7 +1406,10 @@
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;stubJit, callerCodeBlock);
</span><span class="cx">     
</span><span class="cx">     patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
</span><del>-    patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
</del><ins>+    if (JITCode::isOptimizingJIT(callerCodeBlock-&gt;jitType()))
+        patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
+    else
+        patchBuffer.link(done, callLinkInfo.hotPathOther.labelAtOffset(0));
</ins><span class="cx">     patchBuffer.link(slow, CodeLocationLabel(vm-&gt;getCTIStub(virtualThunkGeneratorFor(CodeForCall, registers)).code()));
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;ClosureCallStubRoutine&gt; stubRoutine = adoptRef(new ClosureCallStubRoutine(
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp (161731 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &lt;limits&gt;
</span><span class="cx"> #include &lt;stdlib.h&gt;
</span><span class="cx"> #include &lt;string.h&gt;
</span><ins>+#include &lt;wtf/DataLog.h&gt;
</ins><span class="cx"> #include &lt;wtf/NumberOfCores.h&gt;
</span><span class="cx"> #include &lt;wtf/PageBlock.h&gt;
</span><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="lines">@@ -175,6 +176,49 @@
</span><span class="cx"> #undef FOR_EACH_OPTION
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+static void recomputeDependentOptions()
+{
+#if !ENABLE(JIT)
+    Options::useJIT() = false;
+    Options::useDFGJIT() = false;
+#endif
+#if !ENABLE(YARR_JIT)
+    Options::useRegExpJIT() = false;
+#endif
+    
+    if (Options::showDisassembly()
+        || Options::showDFGDisassembly()
+        || Options::dumpBytecodeAtDFGTime()
+        || Options::dumpGraphAtEachPhase()
+        || Options::verboseCompilation()
+        || Options::logCompilationChanges()
+        || Options::validateGraph()
+        || Options::validateGraphAtEachPhase()
+        || Options::verboseOSR()
+        || Options::verboseCompilationQueue()
+        || Options::reportCompileTimes()
+        || Options::verboseCFA()
+        || Options::verboseFTLFailure())
+        Options::alwaysComputeHash() = true;
+    
+    // Do range checks where needed and make corrections to the options:
+    ASSERT(Options::thresholdForOptimizeAfterLongWarmUp() &gt;= Options::thresholdForOptimizeAfterWarmUp());
+    ASSERT(Options::thresholdForOptimizeAfterWarmUp() &gt;= Options::thresholdForOptimizeSoon());
+    ASSERT(Options::thresholdForOptimizeAfterWarmUp() &gt;= 0);
+
+    // Compute the maximum value of the reoptimization retry counter. This is simply
+    // the largest value at which we don't overflow the execute counter, when using it
+    // to left-shift the execution counter by this amount. Currently the value ends
+    // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
+    // total on a 32-bit processor.
+    Options::reoptimizationRetryCounterMax() = 0;
+    while ((static_cast&lt;int64_t&gt;(Options::thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; (Options::reoptimizationRetryCounterMax() + 1)) &lt;= static_cast&lt;int64_t&gt;(std::numeric_limits&lt;int32_t&gt;::max()))
+        Options::reoptimizationRetryCounterMax()++;
+
+    ASSERT((static_cast&lt;int64_t&gt;(Options::thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; Options::reoptimizationRetryCounterMax()) &gt; 0);
+    ASSERT((static_cast&lt;int64_t&gt;(Options::thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; Options::reoptimizationRetryCounterMax()) &lt;= static_cast&lt;int64_t&gt;(std::numeric_limits&lt;int32_t&gt;::max()));
+}
+
</ins><span class="cx"> void Options::initialize()
</span><span class="cx"> {
</span><span class="cx">     // Initialize each of the options with their default values:
</span><span class="lines">@@ -204,45 +248,7 @@
</span><span class="cx">     ; // Deconfuse editors that do auto indentation
</span><span class="cx"> #endif
</span><span class="cx">     
</span><del>-#if !ENABLE(JIT)
-    useJIT() = false;
-    useDFGJIT() = false;
-#endif
-#if !ENABLE(YARR_JIT)
-    useRegExpJIT() = false;
-#endif
-    
-    if (showDisassembly()
-        || showDFGDisassembly()
-        || dumpBytecodeAtDFGTime()
-        || dumpGraphAtEachPhase()
-        || verboseCompilation()
-        || logCompilationChanges()
-        || validateGraph()
-        || validateGraphAtEachPhase()
-        || verboseOSR()
-        || verboseCompilationQueue()
-        || reportCompileTimes()
-        || verboseCFA()
-        || verboseFTLFailure())
-        alwaysComputeHash() = true;
-    
-    // Do range checks where needed and make corrections to the options:
-    ASSERT(thresholdForOptimizeAfterLongWarmUp() &gt;= thresholdForOptimizeAfterWarmUp());
-    ASSERT(thresholdForOptimizeAfterWarmUp() &gt;= thresholdForOptimizeSoon());
-    ASSERT(thresholdForOptimizeAfterWarmUp() &gt;= 0);
-
-    // Compute the maximum value of the reoptimization retry counter. This is simply
-    // the largest value at which we don't overflow the execute counter, when using it
-    // to left-shift the execution counter by this amount. Currently the value ends
-    // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
-    // total on a 32-bit processor.
-    reoptimizationRetryCounterMax() = 0;
-    while ((static_cast&lt;int64_t&gt;(thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; (reoptimizationRetryCounterMax() + 1)) &lt;= static_cast&lt;int64_t&gt;(std::numeric_limits&lt;int32&gt;::max()))
-        reoptimizationRetryCounterMax()++;
-
-    ASSERT((static_cast&lt;int64_t&gt;(thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; reoptimizationRetryCounterMax()) &gt; 0);
-    ASSERT((static_cast&lt;int64_t&gt;(thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; reoptimizationRetryCounterMax()) &lt;= static_cast&lt;int64_t&gt;(std::numeric_limits&lt;int32&gt;::max()));
</del><ins>+    recomputeDependentOptions();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Parses a single command line option in the format &quot;&lt;optionName&gt;=&lt;value&gt;&quot;
</span><span class="lines">@@ -266,6 +272,7 @@
</span><span class="cx">         bool success = parse(valueStr, value);          \
</span><span class="cx">         if (success) {                                  \
</span><span class="cx">             name_() = value;                            \
</span><ins>+            recomputeDependentOptions();                \
</ins><span class="cx">             return true;                                \
</span><span class="cx">         }                                               \
</span><span class="cx">         return false;                                   \
</span><span class="lines">@@ -274,7 +281,7 @@
</span><span class="cx">     JSC_OPTIONS(FOR_EACH_OPTION)
</span><span class="cx"> #undef FOR_EACH_OPTION
</span><span class="cx"> 
</span><del>-        return false; // No option matched.
</del><ins>+    return false; // No option matched.
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Options::dumpAllOptions(FILE* stream)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoretestsstressinlineclosurecalljs"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/tests/stress/inline-closure-call.js (0 => 161732)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/tests/stress/inline-closure-call.js                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/tests/stress/inline-closure-call.js        2014-01-11 05:06:10 UTC (rev 161732)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(x) {
+    return function(y) { return x + y; }
+}
+
+function bar(a, b) {
+    return foo(a)(b);
+}
+
+noInline(foo);
+noInline(bar);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = bar(i, i + 1);
+    if (result != i * 2 + 1)
+        throw &quot;Error: bad result for &quot; + i + &quot;: &quot; + result;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>