<!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>[161863] 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/161863">161863</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-01-12 23:20:55 -0800 (Sun, 12 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>internal-js-tests.yaml/Octane/mandreel.js.default-ftl fails about 1/30 times with &quot;TypeError: undefined is not an object&quot;
https://bugs.webkit.org/show_bug.cgi?id=126797

Not yet reviewed.
        
This bug was a hilarious combination of concurrent JIT (making it a flake),
LLInt-&gt;JIT OSR, and the FTL's register preservation wrapper.
        
Consider that a CodeBlock with a LLInt JITCode may get called, and while running,
it may decide to tier up to the baseline JIT. At that point, the old JITCode gets
summarily deleted and replaced by the baseline JITCode. This used to be &quot;correct&quot;
because the LLInt's JITCode only held a reference to an immortal entrypoint thunk.
But not anymore: now the LLInt's JITCode may also hold references to register
preservation wrappers, which get generated lazily.
        
So consider that the FTL calls a LLInt'd CodeBlock and that LLInt JITCode lazily
creates a register preservation wrapper. That register preservation wrapper is on
the stack and the stack will have a return PC that points to it. Then the LLInt
code decides to tier up to the baseline JIT. This causes the LLInt JITCode to get
deleted. That means that the register preservation wrapper also gets deleted. Now
all it takes is for some more executable memory to get allocated, and when that
baseline JIT frame (that used to be a LLInt frame) returns, it returns into what
it *thinks* is a register preservation wrapper - except now it's something else!
        
Hilariously, the thing that we'd return into in mandreel was a PutByVal stub. When
the concurrent JIT interleaved itself in such a way as to make this case happen
(i.e. the FTL code for runMandreel was compiled just as some mandreel init routine
was *about* to get tiered up to baseline JIT), then the baseline code would
*always* allocate a PutByVal stub right where the register preservation wrapper's
return site used to be. Thus, returning from the baseline code for that
initialization function would cause it to jump to a PutByVal stub for one of the
PutByVal's in that same function. Somehow, we'd always end up returning to a valid
instruction rather than into the middle of something. That PutByVal stub would
then do a type check on some random variable that it thought was the base - it
would of course fail - and then the slow path would try to do conversions - that
would result in it seeing undefined - and then usually we would crash while trying
to throw the exception.
        
The solution is to make the return site of the register preservation thunk be
always immortal. We already had a standalone immortal return ramp for that thunk
for use by FTL OSR exit. I figure it doesn't hurt to just always use that immortal
return site.
        
This bug took several days to track down. I don't think I can add more tests for
this, although I'll think about it. Basically the lesson here is that running big
tests like Mandreel over and over again with the concurrent JIT enabled shakes out
interesting bugs.
        
This change also adds some useful debug flags, like --breakOnThrow=true, which
causes us to CRASH() whenever an exception is thrown. Without this, this bug was
basically impossible to figure out: we would wind up somewhere in
handleUncaughtException and then that code would go *completely berserk* because
the stack is of course totally screwed up once we &quot;returned&quot; into that PutByVal
stub.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpAssumingJITType):
(JSC::CodeBlock::CodeBlock):
* dfg/DFGCompilationMode.h:
(JSC::DFG::isFTL):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::reportCompileTimes):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPlan.h:
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* jit/RegisterPreservationWrapperGenerator.cpp:
(JSC::generateRegisterPreservationWrapper):
(JSC::generateRegisterRestoration):
* jit/RegisterPreservationWrapperGenerator.h:
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
* runtime/Options.h:
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::throwException):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreChangeLog">branches/jsCStack/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockcpp">branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGCompilationModeh">branches/jsCStack/Source/JavaScriptCore/dfg/DFGCompilationMode.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGPlancpp">branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGPlanh">branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITExceptionscpp">branches/jsCStack/Source/JavaScriptCore/jit/JITExceptions.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp">branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorh">branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp">branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeOptionsh">branches/jsCStack/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeVMcpp">branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsCStackSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ChangeLog (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -1,3 +1,85 @@
</span><ins>+2014-01-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        internal-js-tests.yaml/Octane/mandreel.js.default-ftl fails about 1/30 times with &quot;TypeError: undefined is not an object&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=126797
+
+        Not yet reviewed.
+        
+        This bug was a hilarious combination of concurrent JIT (making it a flake),
+        LLInt-&gt;JIT OSR, and the FTL's register preservation wrapper.
+        
+        Consider that a CodeBlock with a LLInt JITCode may get called, and while running,
+        it may decide to tier up to the baseline JIT. At that point, the old JITCode gets
+        summarily deleted and replaced by the baseline JITCode. This used to be &quot;correct&quot;
+        because the LLInt's JITCode only held a reference to an immortal entrypoint thunk.
+        But not anymore: now the LLInt's JITCode may also hold references to register
+        preservation wrappers, which get generated lazily.
+        
+        So consider that the FTL calls a LLInt'd CodeBlock and that LLInt JITCode lazily
+        creates a register preservation wrapper. That register preservation wrapper is on
+        the stack and the stack will have a return PC that points to it. Then the LLInt
+        code decides to tier up to the baseline JIT. This causes the LLInt JITCode to get
+        deleted. That means that the register preservation wrapper also gets deleted. Now
+        all it takes is for some more executable memory to get allocated, and when that
+        baseline JIT frame (that used to be a LLInt frame) returns, it returns into what
+        it *thinks* is a register preservation wrapper - except now it's something else!
+        
+        Hilariously, the thing that we'd return into in mandreel was a PutByVal stub. When
+        the concurrent JIT interleaved itself in such a way as to make this case happen
+        (i.e. the FTL code for runMandreel was compiled just as some mandreel init routine
+        was *about* to get tiered up to baseline JIT), then the baseline code would
+        *always* allocate a PutByVal stub right where the register preservation wrapper's
+        return site used to be. Thus, returning from the baseline code for that
+        initialization function would cause it to jump to a PutByVal stub for one of the
+        PutByVal's in that same function. Somehow, we'd always end up returning to a valid
+        instruction rather than into the middle of something. That PutByVal stub would
+        then do a type check on some random variable that it thought was the base - it
+        would of course fail - and then the slow path would try to do conversions - that
+        would result in it seeing undefined - and then usually we would crash while trying
+        to throw the exception.
+        
+        The solution is to make the return site of the register preservation thunk be
+        always immortal. We already had a standalone immortal return ramp for that thunk
+        for use by FTL OSR exit. I figure it doesn't hurt to just always use that immortal
+        return site.
+        
+        This bug took several days to track down. I don't think I can add more tests for
+        this, although I'll think about it. Basically the lesson here is that running big
+        tests like Mandreel over and over again with the concurrent JIT enabled shakes out
+        interesting bugs.
+        
+        This change also adds some useful debug flags, like --breakOnThrow=true, which
+        causes us to CRASH() whenever an exception is thrown. Without this, this bug was
+        basically impossible to figure out: we would wind up somewhere in
+        handleUncaughtException and then that code would go *completely berserk* because
+        the stack is of course totally screwed up once we &quot;returned&quot; into that PutByVal
+        stub.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpAssumingJITType):
+        (JSC::CodeBlock::CodeBlock):
+        * dfg/DFGCompilationMode.h:
+        (JSC::DFG::isFTL):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::reportCompileTimes):
+        (JSC::DFG::Plan::compileInThread):
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGPlan.h:
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * jit/JITExceptions.cpp:
+        (JSC::genericUnwind):
+        * jit/RegisterPreservationWrapperGenerator.cpp:
+        (JSC::generateRegisterPreservationWrapper):
+        (JSC::generateRegisterRestoration):
+        * jit/RegisterPreservationWrapperGenerator.h:
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        * runtime/Options.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::throwException):
+
</ins><span class="cx"> 2014-01-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Eliminate obviously redundant InvalidationPoints
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -128,10 +128,15 @@
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::dumpAssumingJITType(PrintStream&amp; out, JITCode::JITType jitType) const
</span><span class="cx"> {
</span><ins>+    out.print(inferredName(), &quot;#&quot;);
</ins><span class="cx">     if (hasHash() || isSafeToComputeHash())
</span><del>-        out.print(inferredName(), &quot;#&quot;, hash(), &quot;:[&quot;, RawPointer(this), &quot;-&gt;&quot;, RawPointer(ownerExecutable()), &quot;, &quot;, jitType, codeType());
</del><ins>+        out.print(hash());
</ins><span class="cx">     else
</span><del>-        out.print(inferredName(), &quot;#&lt;no-hash&gt;:[&quot;, RawPointer(this), &quot;-&gt;&quot;, RawPointer(ownerExecutable()), &quot;, &quot;, jitType, codeType());
</del><ins>+        out.print(&quot;&lt;no-hash&gt;&quot;);
+    out.print(&quot;:[&quot;, RawPointer(this), &quot;-&gt;&quot;);
+    if (!!m_alternative)
+        out.print(RawPointer(m_alternative.get()), &quot;-&gt;&quot;);
+    out.print(RawPointer(ownerExecutable()), &quot;, &quot;, jitType, codeType());
</ins><span class="cx"> 
</span><span class="cx">     if (codeType() == FunctionCode)
</span><span class="cx">         out.print(specializationKind());
</span><span class="lines">@@ -1849,6 +1854,7 @@
</span><span class="cx">     if (Options::dumpGeneratedBytecodes())
</span><span class="cx">         dumpBytecode();
</span><span class="cx"> 
</span><ins>+    
</ins><span class="cx">     m_heap-&gt;m_codeBlocks.add(this);
</span><span class="cx">     m_heap-&gt;reportExtraMemoryCost(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGCompilationModeh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGCompilationMode.h (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGCompilationMode.h        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGCompilationMode.h        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -37,6 +37,17 @@
</span><span class="cx">     FTLForOSREntryMode
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline bool isFTL(CompilationMode mode)
+{
+    switch (mode) {
+    case FTLMode:
+    case FTLForOSREntryMode:
+        return true;
+    default:
+        return false;
+    }
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -125,10 +125,16 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Plan::reportCompileTimes() const
+{
+    return Options::reportCompileTimes()
+        || (Options::reportFTLCompileTimes() &amp;&amp; isFTL(mode));
+}
+
</ins><span class="cx"> void Plan::compileInThread(LongLivedState&amp; longLivedState)
</span><span class="cx"> {
</span><span class="cx">     double before = 0;
</span><del>-    if (Options::reportCompileTimes())
</del><ins>+    if (reportCompileTimes())
</ins><span class="cx">         before = currentTimeMS();
</span><span class="cx">     
</span><span class="cx">     SamplingRegion samplingRegion(&quot;DFG Compilation (Plan)&quot;);
</span><span class="lines">@@ -141,7 +147,7 @@
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(finalizer);
</span><span class="cx">     
</span><del>-    if (Options::reportCompileTimes()) {
</del><ins>+    if (reportCompileTimes()) {
</ins><span class="cx">         const char* pathName;
</span><span class="cx">         switch (path) {
</span><span class="cx">         case FailPath:
</span><span class="lines">@@ -159,7 +165,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         double now = currentTimeMS();
</span><del>-        dataLog(&quot;Optimized &quot;, *codeBlock-&gt;alternative(), &quot; using &quot;, mode, &quot; with &quot;, pathName, &quot; in &quot;, now - before, &quot; ms&quot;);
</del><ins>+        dataLog(&quot;Optimized &quot;, *codeBlock, &quot; using &quot;, mode, &quot; with &quot;, pathName, &quot; in &quot;, now - before, &quot; ms&quot;);
</ins><span class="cx">         if (path == FTLPath)
</span><span class="cx">             dataLog(&quot; (DFG: &quot;, beforeFTL - before, &quot;, LLVM: &quot;, now - beforeFTL, &quot;)&quot;);
</span><span class="cx">         dataLog(&quot;.\n&quot;);
</span><span class="lines">@@ -307,7 +313,7 @@
</span><span class="cx">         FTL::State state(dfg);
</span><span class="cx">         FTL::lowerDFGToLLVM(state);
</span><span class="cx">         
</span><del>-        if (Options::reportCompileTimes())
</del><ins>+        if (reportCompileTimes())
</ins><span class="cx">             beforeFTL = currentTimeMS();
</span><span class="cx">         
</span><span class="cx">         if (Options::llvmAlwaysFailsBeforeCompile()) {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGPlanh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.h (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.h        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGPlan.h        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -92,6 +92,8 @@
</span><span class="cx">     RefPtr&lt;DeferredCompilationCallback&gt; callback;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    bool reportCompileTimes() const;
+    
</ins><span class="cx">     enum CompilationPath { FailPath, DFGPath, FTLPath };
</span><span class="cx">     CompilationPath compileInThreadImpl(LongLivedState&amp;);
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -495,7 +495,8 @@
</span><span class="cx">                 dataLog(
</span><span class="cx">                     &quot;Generated LLVM code after stackmap-based fix-up for &quot;,
</span><span class="cx">                     CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT),
</span><del>-                    &quot; #&quot;, i, &quot;, &quot;, state.codeSectionNames[i], &quot;:\n&quot;);
</del><ins>+                    &quot; in &quot;, state.graph.m_plan.mode, &quot; #&quot;, i, &quot;, &quot;,
+                    state.codeSectionNames[i], &quot;:\n&quot;);
</ins><span class="cx">                 disassemble(
</span><span class="cx">                     MacroAssemblerCodePtr(handle-&gt;start()), handle-&gt;sizeInBytes(),
</span><span class="cx">                     &quot;    &quot;, WTF::dataFile(), LLVMSubset);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITExceptionscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITExceptions.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITExceptions.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITExceptions.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -43,6 +43,11 @@
</span><span class="cx"> 
</span><span class="cx"> void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
</span><span class="cx"> {
</span><ins>+    if (Options::breakOnThrow()) {
+        dataLog(&quot;In call frame &quot;, RawPointer(callFrame), &quot; for code block &quot;, *callFrame-&gt;codeBlock(), &quot;\n&quot;);
+        CRASH();
+    }
+    
</ins><span class="cx">     RELEASE_ASSERT(exceptionValue);
</span><span class="cx">     HandlerInfo* handler = vm-&gt;interpreter-&gt;unwind(callFrame, exceptionValue); // This may update callFrame.
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -110,12 +110,15 @@
</span><span class="cx">     jit.move(AssemblyHelpers::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
</span><span class="cx">     jit.add64(AssemblyHelpers::TrustedImm32(TagMask - TagTypeNumber), GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
</span><span class="cx">     
</span><del>-    AssemblyHelpers::Call call = jit.nearCall();
</del><ins>+    jit.move(
+        AssemblyHelpers::TrustedImmPtr(
+            vm.getCTIStub(registerRestorationThunkGenerator).code().executableAddress()),
+        GPRInfo::nonArgGPR0);
+    jit.restoreReturnAddressBeforeReturn(GPRInfo::nonArgGPR0);
+    AssemblyHelpers::Jump jump = jit.jump();
</ins><span class="cx">     
</span><del>-    generateRegisterRestoration(jit);
-    
</del><span class="cx">     LinkBuffer linkBuffer(vm, &amp;jit, GLOBAL_THUNK_ID);
</span><del>-    linkBuffer.link(call, CodeLocationLabel(target));
</del><ins>+    linkBuffer.link(jump, CodeLocationLabel(target));
</ins><span class="cx"> 
</span><span class="cx">     if (Options::verboseFTLToJSThunk())
</span><span class="cx">         dataLog(&quot;Need a thunk for calls from FTL to non-FTL version of &quot;, *executable, &quot;\n&quot;);
</span><span class="lines">@@ -135,7 +138,7 @@
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void generateRegisterRestoration(AssemblyHelpers&amp; jit)
</del><ins>+static void generateRegisterRestoration(AssemblyHelpers&amp; jit)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx">     RegisterSet toSave = registersToPreserve();
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -41,8 +41,6 @@
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM&amp;, ExecutableBase*, MacroAssemblerCodePtr target);
</span><span class="cx"> 
</span><del>-void generateRegisterRestoration(AssemblyHelpers&amp;);
-
</del><span class="cx"> MacroAssemblerCodeRef registerRestorationThunkGenerator(VM*);
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -197,6 +197,7 @@
</span><span class="cx">         || Options::verboseOSR()
</span><span class="cx">         || Options::verboseCompilationQueue()
</span><span class="cx">         || Options::reportCompileTimes()
</span><ins>+        || Options::reportFTLCompileTimes()
</ins><span class="cx">         || Options::verboseCFA()
</span><span class="cx">         || Options::verboseFTLFailure())
</span><span class="cx">         Options::alwaysComputeHash() = true;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Options.h (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Options.h        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Options.h        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -123,6 +123,7 @@
</span><span class="cx">     v(bool, verboseCallLink, false) \
</span><span class="cx">     v(bool, verboseCompilationQueue, false) \
</span><span class="cx">     v(bool, reportCompileTimes, false) \
</span><ins>+    v(bool, reportFTLCompileTimes, false) \
</ins><span class="cx">     v(bool, verboseCFA, false) \
</span><span class="cx">     v(bool, verboseFTLToJSThunk, false) \
</span><span class="cx">     v(bool, verboseFTLFailure, false) \
</span><span class="lines">@@ -156,6 +157,8 @@
</span><span class="cx">     \
</span><span class="cx">     v(bool, enableArchitectureSpecificOptimizations, true) \
</span><span class="cx">     \
</span><ins>+    v(bool, breakOnThrow, false) \
+    \
</ins><span class="cx">     v(unsigned, maximumOptimizationCandidateInstructionCount, 10000) \
</span><span class="cx">     \
</span><span class="cx">     v(unsigned, maximumFunctionForCallInlineCandidateInstructionCount, 180) \
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp (161862 => 161863)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp        2014-01-13 06:29:18 UTC (rev 161862)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp        2014-01-13 07:20:55 UTC (rev 161863)
</span><span class="lines">@@ -288,7 +288,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     heap.notifyIsSafeToCollect();
</span><del>-
</del><ins>+    
</ins><span class="cx">     LLInt::Data::performAssertions(*this);
</span><span class="cx">     
</span><span class="cx">     if (Options::enableProfiler()) {
</span><span class="lines">@@ -656,6 +656,11 @@
</span><span class="cx">     
</span><span class="cx"> JSValue VM::throwException(ExecState* exec, JSValue error)
</span><span class="cx"> {
</span><ins>+    if (Options::breakOnThrow()) {
+        dataLog(&quot;In call frame &quot;, RawPointer(exec), &quot; for code block &quot;, *exec-&gt;codeBlock(), &quot;\n&quot;);
+        CRASH();
+    }
+    
</ins><span class="cx">     ASSERT(exec == topCallFrame || exec == exec-&gt;lexicalGlobalObject()-&gt;globalExec() || exec == exec-&gt;vmEntryGlobalObject()-&gt;globalExec());
</span><span class="cx">     
</span><span class="cx">     Vector&lt;StackFrame&gt; stackTrace;
</span></span></pre>
</div>
</div>

</body>
</html>