<!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>[162035] 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/162035">162035</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-01-14 18:57:18 -0800 (Tue, 14 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL should be cool with runtime functions throwing exceptions
https://bugs.webkit.org/show_bug.cgi?id=127018

Reviewed by Geoffrey Garen.
        
This just adds the appropriate exception throwing off-ramp to the FTL. There's no
way to express that off-ramp in LLVM IR, so we just use a stackmap that we fill
with a jump to our own off-ramp. It's easy!
        
The throw-through-optimized-code test already worked because the architecture of
the FTL allows our existing unwinding to &quot;just work&quot;. The
runtime-throw-through-optimized-code test used to crash but now works. The
empty-function test currently covers the case where there won't be any exception
handlers, though that will cease to be the case once we have real stack checks.
But even then the test will be useful - an overly optimizable function leads to
many otherwise-needed stackmaps not being emitted, so this will always test some
fun corner cases in FTL::fixFunctionBasedOnStackMaps().
        
* assembler/LinkBuffer.h:
(JSC::LinkBuffer::entrypoint):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLJITFinalizer.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::callCheck):
* ftl/FTLState.h:
* tests/stress/empty-function.js: Added.
(foo):
* tests/stress/runtime-throw-through-optimized-code.js: Added.
(foo):
(bar):
* tests/stress/throw-through-optimized-code.js: Added.
(foo):
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreChangeLog">branches/jsCStack/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreassemblerLinkBufferh">branches/jsCStack/Source/JavaScriptCore/assembler/LinkBuffer.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizercpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizerh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLStateh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoretestsstressemptyfunctionjs">branches/jsCStack/Source/JavaScriptCore/tests/stress/empty-function.js</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoretestsstressruntimethrowthroughoptimizedcodejs">branches/jsCStack/Source/JavaScriptCore/tests/stress/runtime-throw-through-optimized-code.js</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoretestsstressthrowthroughoptimizedcodejs">branches/jsCStack/Source/JavaScriptCore/tests/stress/throw-through-optimized-code.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 (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2014-01-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should be cool with runtime functions throwing exceptions
+        https://bugs.webkit.org/show_bug.cgi?id=127018
+
+        Reviewed by Geoffrey Garen.
+        
+        This just adds the appropriate exception throwing off-ramp to the FTL. There's no
+        way to express that off-ramp in LLVM IR, so we just use a stackmap that we fill
+        with a jump to our own off-ramp. It's easy!
+        
+        The throw-through-optimized-code test already worked because the architecture of
+        the FTL allows our existing unwinding to &quot;just work&quot;. The
+        runtime-throw-through-optimized-code test used to crash but now works. The
+        empty-function test currently covers the case where there won't be any exception
+        handlers, though that will cease to be the case once we have real stack checks.
+        But even then the test will be useful - an overly optimizable function leads to
+        many otherwise-needed stackmaps not being emitted, so this will always test some
+        fun corner cases in FTL::fixFunctionBasedOnStackMaps().
+        
+        * assembler/LinkBuffer.h:
+        (JSC::LinkBuffer::entrypoint):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeFunction):
+        * ftl/FTLJITFinalizer.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::lower):
+        (JSC::FTL::LowerDFGToLLVM::callCheck):
+        * ftl/FTLState.h:
+        * tests/stress/empty-function.js: Added.
+        (foo):
+        * tests/stress/runtime-throw-through-optimized-code.js: Added.
+        (foo):
+        (bar):
+        * tests/stress/throw-through-optimized-code.js: Added.
+        (foo):
+        (bar):
+
</ins><span class="cx"> 2014-01-13  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix 64-bit C Loop LLINT for !ENABLE(COMPUTED_GOTO_OPCODES).
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreassemblerLinkBufferh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/assembler/LinkBuffer.h (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/assembler/LinkBuffer.h        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/assembler/LinkBuffer.h        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -164,6 +164,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // These methods are used to obtain handles to allow the code to be relinked / repatched later.
</span><ins>+    
+    CodeLocationLabel entrypoint()
+    {
+        return CodeLocationLabel(code());
+    }
</ins><span class="cx"> 
</span><span class="cx">     CodeLocationCall locationOf(Call call)
</span><span class="cx">     {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -170,6 +170,31 @@
</span><span class="cx">     
</span><span class="cx">     // FIXME: Need to update all machine virtual registers in runtime meta-data.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=125725
</span><ins>+    
+    iter = recordMap.find(state.handleExceptionStackmapID);
+    // It's sort of remotely possible that we won't have an exception handling path, for
+    // some kinds of functions. That's not an optimization per se; it just fell out that
+    // way.
+    if (iter != recordMap.end()) {
+        RELEASE_ASSERT(!iter-&gt;value.locations.size());
+        
+        CCallHelpers checkJIT(&amp;vm, codeBlock);
+        
+        // At this point it's perfectly fair to just blow away all state and restore the
+        // JS JIT view of the universe.
+        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
+        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
+        
+        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        MacroAssembler::Call call = checkJIT.call();
+        checkJIT.jumpToExceptionHandler();
+        
+        OwnPtr&lt;LinkBuffer&gt; linkBuffer = adoptPtr(new LinkBuffer(
+            vm, &amp;checkJIT, codeBlock, JITCompilationMustSucceed));
+        linkBuffer-&gt;link(call, FunctionPtr(lookupExceptionHandler));
+        
+        state.finalizer-&gt;handleExceptionsLinkBuffer = linkBuffer.release();
+    }
</ins><span class="cx"> 
</span><span class="cx">     ExitThunkGenerator exitThunkGenerator(state);
</span><span class="cx">     exitThunkGenerator.emitThunks();
</span><span class="lines">@@ -345,6 +370,18 @@
</span><span class="cx">     
</span><span class="cx">     RepatchBuffer repatchBuffer(codeBlock);
</span><span class="cx">     
</span><ins>+    if (state.finalizer-&gt;handleExceptionsLinkBuffer) {
+        iter = recordMap.find(state.handleExceptionStackmapID);
+        RELEASE_ASSERT(iter != recordMap.end());
+        
+        StackMaps::Record&amp; record = iter-&gt;value;
+        
+        CodeLocationLabel source = CodeLocationLabel(
+            bitwise_cast&lt;char*&gt;(generatedFunction) + record.instructionOffset);
+
+        repatchBuffer.replaceWithJump(source, state.finalizer-&gt;handleExceptionsLinkBuffer-&gt;entrypoint());
+    }
+    
</ins><span class="cx">     for (unsigned exitIndex = 0; exitIndex &lt; jitCode-&gt;osrExit.size(); ++exitIndex) {
</span><span class="cx">         OSRExitCompilationInfo&amp; info = state.finalizer-&gt;osrExit[exitIndex];
</span><span class="cx">         OSRExit&amp; exit = jitCode-&gt;osrExit[exitIndex];
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -100,6 +100,14 @@
</span><span class="cx">             .executableMemory());
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (handleExceptionsLinkBuffer) {
+        jitCode-&gt;addHandle(FINALIZE_DFG_CODE(
+            *handleExceptionsLinkBuffer,
+            (&quot;FTL exception handler for %s&quot;,
+                toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data()))
+            .executableMemory());
+    }
+    
</ins><span class="cx">     MacroAssemblerCodePtr withArityCheck;
</span><span class="cx">     if (arityCheck.isSet())
</span><span class="cx">         withArityCheck = entrypointLinkBuffer-&gt;locationOf(arityCheck);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizerh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.h (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.h        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.h        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">     OwnPtr&lt;LinkBuffer&gt; exitThunksLinkBuffer;
</span><span class="cx">     OwnPtr&lt;LinkBuffer&gt; entrypointLinkBuffer;
</span><span class="cx">     OwnPtr&lt;LinkBuffer&gt; sideCodeLinkBuffer;
</span><ins>+    OwnPtr&lt;LinkBuffer&gt; handleExceptionsLinkBuffer;
</ins><span class="cx">     Vector&lt;SlowPathCall&gt; slowPathCalls; // Calls inside the side code.
</span><span class="cx">     Vector&lt;OSRExitCompilationInfo&gt; osrExit;
</span><span class="cx">     MacroAssembler::Label arityCheck;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -109,6 +109,7 @@
</span><span class="cx">         
</span><span class="cx">         m_prologue = FTL_NEW_BLOCK(m_out, (&quot;Prologue&quot;));
</span><span class="cx">         LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, (&quot;Stack overflow&quot;));
</span><ins>+        m_handleExceptions = FTL_NEW_BLOCK(m_out, (&quot;Handle Exceptions&quot;));
</ins><span class="cx"> 
</span><span class="cx">         for (BlockIndex blockIndex = 0; blockIndex &lt; m_graph.numBlocks(); ++blockIndex) {
</span><span class="cx">             m_highBlock = m_graph.block(blockIndex);
</span><span class="lines">@@ -142,10 +143,18 @@
</span><span class="cx">             m_out.below(m_callFrame, m_out.loadPtr(m_out.absolute(&amp;stackLimit))),
</span><span class="cx">             stackOverflow, lowBlock(m_graph.block(0)));
</span><span class="cx">         
</span><del>-        m_out.appendTo(stackOverflow, lowBlock(m_graph.block(0)));
-        // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
</del><ins>+        m_out.appendTo(stackOverflow, m_handleExceptions);
+        // FIXME: Do a real stack check and throw the exception appropriately.
+        // https://bugs.webkit.org/show_bug.cgi?id=125650
</ins><span class="cx">         m_out.crash();
</span><span class="cx">         
</span><ins>+        m_out.appendTo(m_handleExceptions, lowBlock(m_graph.block(0)));
+        m_ftlState.handleExceptionStackmapID = m_stackmapIDs++;
+        m_out.call(
+            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID),
+            m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
+        m_out.unreachable();
+        
</ins><span class="cx">         Vector&lt;BasicBlock*&gt; depthFirst;
</span><span class="cx">         m_graph.getBlocksInDepthFirstOrder(depthFirst);
</span><span class="cx">         for (unsigned i = 0; i &lt; depthFirst.size(); ++i)
</span><span class="lines">@@ -4154,18 +4163,13 @@
</span><span class="cx">         if (mode == NoExceptions)
</span><span class="cx">             return;
</span><span class="cx">         
</span><del>-        LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, (&quot;Did have exception&quot;));
</del><span class="cx">         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;Exception check continuation&quot;));
</span><span class="cx">         
</span><span class="cx">         m_out.branch(
</span><span class="cx">             m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
</span><del>-            didHaveException, continuation);
</del><ins>+            m_handleExceptions, continuation);
</ins><span class="cx">         
</span><del>-        LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation);
-        // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
-        m_out.crash();
-        
-        m_out.appendTo(continuation, lastNext);
</del><ins>+        m_out.appendTo(continuation);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     LBasicBlock lowBlock(BasicBlock* block)
</span><span class="lines">@@ -4559,6 +4563,7 @@
</span><span class="cx">     Output m_out;
</span><span class="cx">     
</span><span class="cx">     LBasicBlock m_prologue;
</span><ins>+    LBasicBlock m_handleExceptions;
</ins><span class="cx">     HashMap&lt;BasicBlock*, LBasicBlock&gt; m_blocks;
</span><span class="cx">     
</span><span class="cx">     LValue m_callFrame;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLStateh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h (162034 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h        2014-01-15 02:43:31 UTC (rev 162034)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     RefPtr&lt;JITCode&gt; jitCode;
</span><span class="cx">     GeneratedFunction generatedFunction;
</span><span class="cx">     JITFinalizer* finalizer;
</span><ins>+    unsigned handleExceptionStackmapID;
</ins><span class="cx">     unsigned capturedStackmapID;
</span><span class="cx">     SegmentedVector&lt;GetByIdDescriptor&gt; getByIds;
</span><span class="cx">     SegmentedVector&lt;PutByIdDescriptor&gt; putByIds;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoretestsstressemptyfunctionjs"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/tests/stress/empty-function.js (0 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/tests/stress/empty-function.js                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/tests/stress/empty-function.js        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+function foo() { }
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo();
+    if (result !== void 0)
+        throw &quot;You broke JSC so hard that even the empty function doesn't work: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoretestsstressruntimethrowthroughoptimizedcodejs"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/tests/stress/runtime-throw-through-optimized-code.js (0 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/tests/stress/runtime-throw-through-optimized-code.js                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/tests/stress/runtime-throw-through-optimized-code.js        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+function foo(a, s) {
+    return a[s] + 1;
+}
+
+var shouldThrow = false;
+function bar() {
+    if (shouldThrow)
+        throw &quot;hello&quot;;
+    return 42;
+}
+
+var a = {};
+a.__defineGetter__(&quot;bar&quot;, bar);
+
+noInline(foo);
+noInline(bar);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(a, &quot;bar&quot;);
+    if (result != 43)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var didThrow;
+try {
+    shouldThrow = true;
+    foo(a, &quot;bar&quot;);
+} catch (e) {
+    didThrow = e;
+}
+
+if (didThrow != &quot;hello&quot;)
+    throw &quot;Error: didn't throw or threw wrong exception: &quot; + didThrow;
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoretestsstressthrowthroughoptimizedcodejs"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/tests/stress/throw-through-optimized-code.js (0 => 162035)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/tests/stress/throw-through-optimized-code.js                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/tests/stress/throw-through-optimized-code.js        2014-01-15 02:57:18 UTC (rev 162035)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function foo(f) {
+    return f(1) + 1;
+}
+
+var shouldThrow = false;
+function bar(x) {
+    if (shouldThrow)
+        throw &quot;hello&quot;;
+    return 42 - x;
+}
+
+noInline(foo);
+noInline(bar);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(bar);
+    if (result != 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var didThrow;
+try {
+    shouldThrow = true;
+    foo(bar);
+} catch (e) {
+    didThrow = e;
+}
+
+if (didThrow != &quot;hello&quot;)
+    throw &quot;Error: didn't throw or threw wrong exception: &quot; + didThrow;
</ins></span></pre>
</div>
</div>

</body>
</html>