<!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>[193362] trunk/Source</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/193362">193362</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-12-03 12:01:57 -0800 (Thu, 03 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL B3 should support OSR exit
https://bugs.webkit.org/show_bug.cgi?id=151710

Reviewed by Saam Barati.

Source/JavaScriptCore:

This adds OSR exit support using the same style that I established with lazy slow paths. All of
the work is driven by FTL::LowerDFGToLLVM, and from there any work that needs to be deferred
until after B3 finishes is attached to the stackmap generator. In order to make it easy to port
all of the different forms of OSR exit - invalidation points, exceptions, etc. - the logic for
registering an OSR exit is abstracted behind OSRExitDescriptor and OSRExitHandle.

An issue that I encountered repeatedly in this patch is OSRExitDescriptor being passed as a
reference (&amp;) rather than pointer (*). The new code uses a lot of lambdas that run after the
current frame pops, so the capture list cannot be [&amp;]. I believe that always listing all of the
captured variables is not scalable considering how sophisticated our use of lambdas is. So, it
makes sense to use [=]. But anytime we captured a variable whose type was OSRExitDescriptor&amp;, it
would be captured by value, because that's how references work. One has to be mindful of these
things whenever using [=]. Note that it's not enough to say that we should have listed the
captured variables explicitly - in that case, we still could have made the mistake by forgetting
to put &amp; in front of the variant. The pattern that worked for me to reason about whether I'm
capturing an object or a pointer to an object is to always use pointer types for pointers: either
RefPtr&lt;&gt; when we also want the lambda to prolong the object's life, or * if we are confident that
the object will stay alive. For this reason, this patch changes all code that references
OSRExitDescriptor to use * instead of &amp;. Consistency makes the code easier to grok, and it made
it easier to introduce the required uses of * in places where there were lambdas.

I tested this by running imaging-gaussian-blur, and running some tests that reqiure OSR exit. I'm
not promising that all kinds of exits work, but we have to begin somewhere.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3Compilation.cpp:
(JSC::B3::Compilation::Compilation):
(JSC::B3::Compilation::~Compilation):
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::addDataSection):
(JSC::B3::Procedure::frameSize):
(JSC::B3::Procedure::calleeSaveRegisters):
* b3/B3Procedure.h:
(JSC::B3::Procedure::releaseByproducts):
(JSC::B3::Procedure::code):
(JSC::B3::Procedure::takeByproducts): Deleted.
* b3/air/AirCode.h:
(JSC::B3::Air::Code::setFrameSize):
(JSC::B3::Air::Code::calleeSaveRegisters):
* b3/air/AirGenerationContext.h:
* ftl/FTLB3Compile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLExceptionHandlerManager.cpp:
(JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
(JSC::FTL::ExceptionHandlerManager::getCallOSRExitCommon):
* ftl/FTLExitThunkGenerator.cpp:
* ftl/FTLExitThunkGenerator.h:
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::JITCode):
(JSC::FTL::JITCode::initializeB3Code):
(JSC::FTL::JITCode::initializeB3Byproducts):
(JSC::FTL::JITCode::initializeExitThunks):
(JSC::FTL::JITCode::validateReferences):
(JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
* ftl/FTLJITCode.h:
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLJITFinalizer.h:
* ftl/FTLJSCall.cpp:
(JSC::FTL::JSCall::emit):
* ftl/FTLJSCallBase.cpp:
(JSC::FTL::JSCallBase::emit):
* ftl/FTLJSTailCall.cpp:
(JSC::FTL::JSTailCall::JSTailCall):
(JSC::FTL::JSTailCall::emit):
(JSC::FTL::DFG::getRegisterWithAddend): Deleted.
(JSC::FTL::m_instructionOffset): Deleted.
* ftl/FTLJSTailCall.h:
(JSC::FTL::JSTailCall::patchpoint):
(JSC::FTL::JSTailCall::stackmapID):
(JSC::FTL::JSTailCall::estimatedSize):
(JSC::FTL::JSTailCall::operator&lt;):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
(JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitDescriptor):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
(JSC::FTL::DFG::LowerDFGToLLVM::emitOSRExitCall):
(JSC::FTL::DFG::LowerDFGToLLVM::buildExitArguments):
(JSC::FTL::DFG::LowerDFGToLLVM::callStackmap):
(JSC::FTL::lowerDFGToLLVM):
* ftl/FTLOSRExit.cpp:
(JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
(JSC::FTL::OSRExitDescriptor::validateReferences):
(JSC::FTL::OSRExitDescriptor::appendOSRExit):
(JSC::FTL::OSRExitDescriptor::appendOSRExitLater):
(JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
(JSC::FTL::OSRExit::OSRExit):
(JSC::FTL::OSRExit::codeLocationForRepatch):
(JSC::FTL::OSRExit::gatherRegistersToSpillForCallIfException):
(JSC::FTL::OSRExit::spillRegistersToSpillSlot):
(JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
(JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
* ftl/FTLOSRExit.h:
(JSC::FTL::OSRExit::considerAddingAsFrequentExitSite):
* ftl/FTLOSRExitCompilationInfo.h:
(JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::reboxAccordingToFormat):
(JSC::FTL::compileRecovery):
(JSC::FTL::compileStub):
(JSC::FTL::compileFTLOSRExit):
* ftl/FTLOSRExitHandle.cpp: Added.
(JSC::FTL::OSRExitHandle::emitExitThunk):
* ftl/FTLOSRExitHandle.h: Added.
(JSC::FTL::OSRExitHandle::OSRExitHandle):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
(JSC::FTL::State::~State):

Source/WTF:

Make sure that this has perfect forwarding.

* wtf/SegmentedVector.h:
(WTF::SegmentedVector::append):
(WTF::SegmentedVector::alloc):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Compilationcpp">trunk/Source/JavaScriptCore/b3/B3Compilation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedureh">trunk/Source/JavaScriptCore/b3/B3Procedure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirCodeh">trunk/Source/JavaScriptCore/b3/air/AirCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGenerationContexth">trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Compilecpp">trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagercpp">trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorcpp">trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorh">trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodecpp">trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodeh">trunk/Source/JavaScriptCore/ftl/FTLJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITFinalizercpp">trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITFinalizerh">trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJSCallcpp">trunk/Source/JavaScriptCore/ftl/FTLJSCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJSCallBasecpp">trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJSTailCallcpp">trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJSTailCallh">trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitcpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExith">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilationInfoh">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStatecpp">trunk/Source/JavaScriptCore/ftl/FTLState.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfSegmentedVectorh">trunk/Source/WTF/wtf/SegmentedVector.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitHandlecpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitHandleh">trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -1031,6 +1031,7 @@
</span><span class="cx">         ftl/FTLOSREntry.cpp
</span><span class="cx">         ftl/FTLOSRExit.cpp
</span><span class="cx">         ftl/FTLOSRExitCompiler.cpp
</span><ins>+        ftl/FTLOSRExitHandle.cpp
</ins><span class="cx">         ftl/FTLOperations.cpp
</span><span class="cx">         ftl/FTLOutput.cpp
</span><span class="cx">         ftl/FTLRecoveryOpcode.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -1,3 +1,125 @@
</span><ins>+2015-12-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 should support OSR exit
+        https://bugs.webkit.org/show_bug.cgi?id=151710
+
+        Reviewed by Saam Barati.
+
+        This adds OSR exit support using the same style that I established with lazy slow paths. All of
+        the work is driven by FTL::LowerDFGToLLVM, and from there any work that needs to be deferred
+        until after B3 finishes is attached to the stackmap generator. In order to make it easy to port
+        all of the different forms of OSR exit - invalidation points, exceptions, etc. - the logic for
+        registering an OSR exit is abstracted behind OSRExitDescriptor and OSRExitHandle.
+
+        An issue that I encountered repeatedly in this patch is OSRExitDescriptor being passed as a
+        reference (&amp;) rather than pointer (*). The new code uses a lot of lambdas that run after the
+        current frame pops, so the capture list cannot be [&amp;]. I believe that always listing all of the
+        captured variables is not scalable considering how sophisticated our use of lambdas is. So, it
+        makes sense to use [=]. But anytime we captured a variable whose type was OSRExitDescriptor&amp;, it
+        would be captured by value, because that's how references work. One has to be mindful of these
+        things whenever using [=]. Note that it's not enough to say that we should have listed the
+        captured variables explicitly - in that case, we still could have made the mistake by forgetting
+        to put &amp; in front of the variant. The pattern that worked for me to reason about whether I'm
+        capturing an object or a pointer to an object is to always use pointer types for pointers: either
+        RefPtr&lt;&gt; when we also want the lambda to prolong the object's life, or * if we are confident that
+        the object will stay alive. For this reason, this patch changes all code that references
+        OSRExitDescriptor to use * instead of &amp;. Consistency makes the code easier to grok, and it made
+        it easier to introduce the required uses of * in places where there were lambdas.
+
+        I tested this by running imaging-gaussian-blur, and running some tests that reqiure OSR exit. I'm
+        not promising that all kinds of exits work, but we have to begin somewhere.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3Compilation.cpp:
+        (JSC::B3::Compilation::Compilation):
+        (JSC::B3::Compilation::~Compilation):
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::addDataSection):
+        (JSC::B3::Procedure::frameSize):
+        (JSC::B3::Procedure::calleeSaveRegisters):
+        * b3/B3Procedure.h:
+        (JSC::B3::Procedure::releaseByproducts):
+        (JSC::B3::Procedure::code):
+        (JSC::B3::Procedure::takeByproducts): Deleted.
+        * b3/air/AirCode.h:
+        (JSC::B3::Air::Code::setFrameSize):
+        (JSC::B3::Air::Code::calleeSaveRegisters):
+        * b3/air/AirGenerationContext.h:
+        * ftl/FTLB3Compile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::mmAllocateDataSection):
+        * ftl/FTLExceptionHandlerManager.cpp:
+        (JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
+        (JSC::FTL::ExceptionHandlerManager::getCallOSRExitCommon):
+        * ftl/FTLExitThunkGenerator.cpp:
+        * ftl/FTLExitThunkGenerator.h:
+        * ftl/FTLJITCode.cpp:
+        (JSC::FTL::JITCode::JITCode):
+        (JSC::FTL::JITCode::initializeB3Code):
+        (JSC::FTL::JITCode::initializeB3Byproducts):
+        (JSC::FTL::JITCode::initializeExitThunks):
+        (JSC::FTL::JITCode::validateReferences):
+        (JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
+        * ftl/FTLJITCode.h:
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeFunction):
+        * ftl/FTLJITFinalizer.h:
+        * ftl/FTLJSCall.cpp:
+        (JSC::FTL::JSCall::emit):
+        * ftl/FTLJSCallBase.cpp:
+        (JSC::FTL::JSCallBase::emit):
+        * ftl/FTLJSTailCall.cpp:
+        (JSC::FTL::JSTailCall::JSTailCall):
+        (JSC::FTL::JSTailCall::emit):
+        (JSC::FTL::DFG::getRegisterWithAddend): Deleted.
+        (JSC::FTL::m_instructionOffset): Deleted.
+        * ftl/FTLJSTailCall.h:
+        (JSC::FTL::JSTailCall::patchpoint):
+        (JSC::FTL::JSTailCall::stackmapID):
+        (JSC::FTL::JSTailCall::estimatedSize):
+        (JSC::FTL::JSTailCall::operator&lt;):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
+        (JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitDescriptor):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
+        (JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
+        (JSC::FTL::DFG::LowerDFGToLLVM::emitOSRExitCall):
+        (JSC::FTL::DFG::LowerDFGToLLVM::buildExitArguments):
+        (JSC::FTL::DFG::LowerDFGToLLVM::callStackmap):
+        (JSC::FTL::lowerDFGToLLVM):
+        * ftl/FTLOSRExit.cpp:
+        (JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
+        (JSC::FTL::OSRExitDescriptor::validateReferences):
+        (JSC::FTL::OSRExitDescriptor::appendOSRExit):
+        (JSC::FTL::OSRExitDescriptor::appendOSRExitLater):
+        (JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
+        (JSC::FTL::OSRExit::OSRExit):
+        (JSC::FTL::OSRExit::codeLocationForRepatch):
+        (JSC::FTL::OSRExit::gatherRegistersToSpillForCallIfException):
+        (JSC::FTL::OSRExit::spillRegistersToSpillSlot):
+        (JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
+        (JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
+        * ftl/FTLOSRExit.h:
+        (JSC::FTL::OSRExit::considerAddingAsFrequentExitSite):
+        * ftl/FTLOSRExitCompilationInfo.h:
+        (JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::reboxAccordingToFormat):
+        (JSC::FTL::compileRecovery):
+        (JSC::FTL::compileStub):
+        (JSC::FTL::compileFTLOSRExit):
+        * ftl/FTLOSRExitHandle.cpp: Added.
+        (JSC::FTL::OSRExitHandle::emitExitThunk):
+        * ftl/FTLOSRExitHandle.h: Added.
+        (JSC::FTL::OSRExitHandle::OSRExitHandle):
+        * ftl/FTLState.cpp:
+        (JSC::FTL::State::State):
+        (JSC::FTL::State::~State):
+
</ins><span class="cx"> 2015-12-03  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION:(r192753): Remote Web Inspector: RemoteInspector::sendMessageToRemote with null connection
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -494,6 +494,9 @@
</span><span class="cx">                 0F978B3B1AAEA71D007C7369 /* ConstantMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */; };
</span><span class="cx">                 0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */; };
</span><span class="cx">                 0F98206116BFE38300240D02 /* PreciseJumpTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F9B1DB41C0E42A500E5BFD2 /* FTLB3Output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */; };
+                0F9B1DB71C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */; };
+                0F9B1DB81C0E42BD00E5BFD2 /* FTLOSRExitHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */; };
</ins><span class="cx">                 0F9C5E5E18E35F5E00D431C3 /* FTLDWARFRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9C5E5C18E35F5E00D431C3 /* FTLDWARFRegister.cpp */; };
</span><span class="cx">                 0F9C5E5F18E35F5E00D431C3 /* FTLDWARFRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9C5E5D18E35F5E00D431C3 /* FTLDWARFRegister.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9D3370165DBB90005AD387 /* Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D336E165DBB8D005AD387 /* Disassembler.cpp */; };
</span><span class="lines">@@ -1092,7 +1095,6 @@
</span><span class="cx">                 26718BA51BE99F780052017B /* AirIteratedRegisterCoalescing.h in Headers */ = {isa = PBXBuildFile; fileRef = 26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */; };
</span><span class="cx">                 2684D4381C00161C0081D663 /* AirLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684D4371C00161C0081D663 /* AirLiveness.h */; };
</span><span class="cx">                 269D636E1BFBE5D100101B1D /* FTLB3Output.h in Headers */ = {isa = PBXBuildFile; fileRef = 269D636D1BFBE5D000101B1D /* FTLB3Output.h */; };
</span><del>-                26BB57601BFC4328005F12EB /* FTLB3Output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BB575F1BFC4328005F12EB /* FTLB3Output.cpp */; };
</del><span class="cx">                 2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */; };
</span><span class="cx">                 2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
</span><span class="cx">                 2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */; };
</span><span class="lines">@@ -2580,6 +2582,9 @@
</span><span class="cx">                 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantMode.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreciseJumpTargets.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargets.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLB3Output.cpp; path = ftl/FTLB3Output.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLOSRExitHandle.cpp; path = ftl/FTLOSRExitHandle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLOSRExitHandle.h; path = ftl/FTLOSRExitHandle.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F9C5E5C18E35F5E00D431C3 /* FTLDWARFRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDWARFRegister.cpp; path = ftl/FTLDWARFRegister.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9C5E5D18E35F5E00D431C3 /* FTLDWARFRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFRegister.h; path = ftl/FTLDWARFRegister.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9D336E165DBB8D005AD387 /* Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disassembler.cpp; path = disassembler/Disassembler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3147,7 +3152,6 @@
</span><span class="cx">                 26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirIteratedRegisterCoalescing.h; path = b3/air/AirIteratedRegisterCoalescing.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2684D4371C00161C0081D663 /* AirLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLiveness.h; path = b3/air/AirLiveness.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 269D636D1BFBE5D000101B1D /* FTLB3Output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLB3Output.h; path = ftl/FTLB3Output.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                26BB575F1BFC4328005F12EB /* FTLB3Output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLB3Output.cpp; path = ftl/FTLB3Output.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4424,6 +4428,7 @@
</span><span class="cx">                                 0F485323187DFDEC0083B687 /* FTLAvailableRecovery.cpp */,
</span><span class="cx">                                 0F485324187DFDEC0083B687 /* FTLAvailableRecovery.h */,
</span><span class="cx">                                 0FB387911BFD31A100E3AB1E /* FTLB3Compile.cpp */,
</span><ins>+                                0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */,
</ins><span class="cx">                                 269D636D1BFBE5D000101B1D /* FTLB3Output.h */,
</span><span class="cx">                                 0FEA09FE170513DB00BB722C /* FTLCapabilities.cpp */,
</span><span class="cx">                                 0FEA09FF170513DB00BB722C /* FTLCapabilities.h */,
</span><span class="lines">@@ -4496,6 +4501,8 @@
</span><span class="cx">                                 0F235BC817178E1C00690C7F /* FTLOSRExitCompilationInfo.h */,
</span><span class="cx">                                 0F235BC917178E1C00690C7F /* FTLOSRExitCompiler.cpp */,
</span><span class="cx">                                 0F235BCA17178E1C00690C7F /* FTLOSRExitCompiler.h */,
</span><ins>+                                0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */,
+                                0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */,
</ins><span class="cx">                                 0FEA0A291709629600BB722C /* FTLOutput.cpp */,
</span><span class="cx">                                 0FEA0A06170513DB00BB722C /* FTLOutput.h */,
</span><span class="cx">                                 0F485325187DFDEC0083B687 /* FTLRecoveryOpcode.cpp */,
</span><span class="lines">@@ -7575,6 +7582,7 @@
</span><span class="cx">                                 A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */,
</span><span class="cx">                                 C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */,
</span><span class="cx">                                 142D6F0913539A2800B02E86 /* MarkedBlock.h in Headers */,
</span><ins>+                                0F9B1DB81C0E42BD00E5BFD2 /* FTLOSRExitHandle.h in Headers */,
</ins><span class="cx">                                 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
</span><span class="cx">                                 14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
</span><span class="cx">                                 142D6F1213539A4100B02E86 /* MarkStack.h in Headers */,
</span><span class="lines">@@ -8618,6 +8626,7 @@
</span><span class="cx">                                 0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
</span><span class="cx">                                 0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
</span><span class="cx">                                 0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
</span><ins>+                                0F9B1DB41C0E42A500E5BFD2 /* FTLB3Output.cpp in Sources */,
</ins><span class="cx">                                 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */,
</span><span class="cx">                                 0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
</span><span class="cx">                                 0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */,
</span><span class="lines">@@ -8832,6 +8841,7 @@
</span><span class="cx">                                 A51007C0187CC3C600B38879 /* JSGlobalObjectInspectorController.cpp in Sources */,
</span><span class="cx">                                 A50E4B6318809DD50068A46D /* JSGlobalObjectRuntimeAgent.cpp in Sources */,
</span><span class="cx">                                 A503FA29188F105900110F14 /* JSGlobalObjectScriptDebugServer.cpp in Sources */,
</span><ins>+                                0F9B1DB71C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp in Sources */,
</ins><span class="cx">                                 A513E5BF185BFACC007E95AD /* JSInjectedScriptHost.cpp in Sources */,
</span><span class="cx">                                 A513E5C1185BFACC007E95AD /* JSInjectedScriptHostPrototype.cpp in Sources */,
</span><span class="cx">                                 E33F50801B8429A400413856 /* JSInternalPromise.cpp in Sources */,
</span><span class="lines">@@ -8987,7 +8997,6 @@
</span><span class="cx">                                 0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */,
</span><span class="cx">                                 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
</span><span class="cx">                                 0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
</span><del>-                                26BB57601BFC4328005F12EB /* FTLB3Output.cpp in Sources */,
</del><span class="cx">                                 0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
</span><span class="cx">                                 E33637A51B63220200EE0840 /* ReflectObject.cpp in Sources */,
</span><span class="cx">                                 0FA7A8EB18B413C80052371D /* Reg.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Compilationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Compilation.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Compilation.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/b3/B3Compilation.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -42,13 +42,14 @@
</span><span class="cx"> {
</span><span class="cx">     TimingScope timingScope(&quot;Compilation&quot;);
</span><span class="cx">     
</span><ins>+    prepareForGeneration(proc, optLevel);
+    
</ins><span class="cx">     CCallHelpers jit(&amp;vm);
</span><del>-    prepareForGeneration(proc, optLevel);
</del><span class="cx">     generate(proc, jit);
</span><span class="cx">     LinkBuffer linkBuffer(vm, jit, nullptr);
</span><span class="cx"> 
</span><span class="cx">     m_codeRef = FINALIZE_CODE(linkBuffer, (&quot;B3::Compilation&quot;));
</span><del>-    m_byproducts = proc.takeByproducts();
</del><ins>+    m_byproducts = proc.releaseByproducts();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Compilation::~Compilation()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -148,8 +148,13 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const RegisterAtOffsetList&amp; Procedure::calleeSaveRegisters()
</del><ins>+unsigned Procedure::frameSize() const
</ins><span class="cx"> {
</span><ins>+    return code().frameSize();
+}
+
+const RegisterAtOffsetList&amp; Procedure::calleeSaveRegisters() const
+{
</ins><span class="cx">     return code().calleeSaveRegisters();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -219,11 +219,13 @@
</span><span class="cx">     // just keeps alive things like the double constant pool and switch lookup tables. If this sounds
</span><span class="cx">     // confusing, you should probably be using the B3::Compilation API to compile code. If you use
</span><span class="cx">     // that API, then you don't have to worry about this.
</span><del>-    std::unique_ptr&lt;OpaqueByproducts&gt; takeByproducts() { return WTF::move(m_byproducts); }
</del><ins>+    std::unique_ptr&lt;OpaqueByproducts&gt; releaseByproducts() { return WTF::move(m_byproducts); }
</ins><span class="cx"> 
</span><ins>+    const Air::Code&amp; code() const { return *m_code; }
</ins><span class="cx">     Air::Code&amp; code() { return *m_code; }
</span><span class="cx"> 
</span><del>-    const RegisterAtOffsetList&amp; calleeSaveRegisters();
</del><ins>+    unsigned frameSize() const;
+    const RegisterAtOffsetList&amp; calleeSaveRegisters() const;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class BlockInsertionSet;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirCode.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirCode.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/b3/air/AirCode.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx">         m_frameSize = frameSize;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    const RegisterAtOffsetList&amp; calleeSaveRegisters() const { return m_calleeSaveRegisters; }
</ins><span class="cx">     RegisterAtOffsetList&amp; calleeSaveRegisters() { return m_calleeSaveRegisters; }
</span><span class="cx"> 
</span><span class="cx">     // Recomputes predecessors and deletes unreachable blocks.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGenerationContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerationContext.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -29,9 +29,12 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/SharedTask.h&gt;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+class Code;
+
</ins><span class="cx"> struct GenerationContext {
</span><span class="cx">     typedef void LatePathFunction(CCallHelpers&amp;, GenerationContext&amp;);
</span><span class="cx">     typedef SharedTask&lt;LatePathFunction&gt; LatePath;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Compilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -77,6 +77,8 @@
</span><span class="cx">         dataLog(&quot;    &quot;, *registerOffsets, &quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     state.graph.m_codeBlock-&gt;setCalleeSaveRegisters(WTF::move(registerOffsets));
</span><ins>+    ASSERT(!(state.proc-&gt;frameSize() % sizeof(EncodedJSValue)));
+    state.jitCode-&gt;common.frameRegisterCount = state.proc-&gt;frameSize() / sizeof(EncodedJSValue);
</ins><span class="cx"> 
</span><span class="cx">     CCallHelpers jit(&amp;vm, codeBlock);
</span><span class="cx">     B3::generate(*state.proc, jit);
</span><span class="lines">@@ -90,6 +92,7 @@
</span><span class="cx"> 
</span><span class="cx">     state.generatedFunction = bitwise_cast&lt;GeneratedFunction&gt;(
</span><span class="cx">         state.finalizer-&gt;b3CodeLinkBuffer-&gt;entrypoint().executableAddress());
</span><ins>+    state.jitCode-&gt;initializeB3Byproducts(state.proc-&gt;releaseByproducts());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -498,7 +498,7 @@
</span><span class="cx">         for (unsigned j = 0; j &lt; iter-&gt;value.size(); j++) {
</span><span class="cx">             {
</span><span class="cx">                 uint32_t stackmapRecordIndex = iter-&gt;value[j].index;
</span><del>-                OSRExit exit(exitDescriptor, stackmapRecordIndex);
</del><ins>+                OSRExit exit(&amp;exitDescriptor, stackmapRecordIndex);
</ins><span class="cx">                 state.jitCode-&gt;osrExit.append(exit);
</span><span class="cx">                 state.finalizer-&gt;osrExit.append(OSRExitCompilationInfo());
</span><span class="cx">             }
</span><span class="lines">@@ -506,8 +506,8 @@
</span><span class="cx">             OSRExit&amp; exit = state.jitCode-&gt;osrExit.last();
</span><span class="cx">             if (exit.willArriveAtExitFromIndirectExceptionCheck()) {
</span><span class="cx">                 StackMaps::Record&amp; record = iter-&gt;value[j].record;
</span><del>-                RELEASE_ASSERT(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader.isSet());
-                CallSiteIndex callSiteIndex = state.jitCode-&gt;common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
</del><ins>+                RELEASE_ASSERT(exit.m_descriptor-&gt;m_semanticCodeOriginForCallFrameHeader.isSet());
+                CallSiteIndex callSiteIndex = state.jitCode-&gt;common.addUniqueCallSiteIndex(exit.m_descriptor-&gt;m_semanticCodeOriginForCallFrameHeader);
</ins><span class="cx">                 exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
</span><span class="cx"> 
</span><span class="cx">                 OSRExit* callOperationExit = nullptr;
</span><span class="lines">@@ -523,12 +523,12 @@
</span><span class="cx">                     // and the other that will be arrived at from the callOperation exception handler path.
</span><span class="cx">                     // This code here generates the second callOperation variant.
</span><span class="cx">                     uint32_t stackmapRecordIndex = iter-&gt;value[j].index;
</span><del>-                    OSRExit exit(exitDescriptor, stackmapRecordIndex);
</del><ins>+                    OSRExit exit(&amp;exitDescriptor, stackmapRecordIndex);
</ins><span class="cx">                     if (exitDescriptor.m_exceptionType == ExceptionType::GetById)
</span><span class="cx">                         exit.m_exceptionType = ExceptionType::GetByIdCallOperation;
</span><span class="cx">                     else
</span><span class="cx">                         exit.m_exceptionType = ExceptionType::PutByIdCallOperation;
</span><del>-                    CallSiteIndex callSiteIndex = state.jitCode-&gt;common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
</del><ins>+                    CallSiteIndex callSiteIndex = state.jitCode-&gt;common.addUniqueCallSiteIndex(exit.m_descriptor-&gt;m_semanticCodeOriginForCallFrameHeader);
</ins><span class="cx">                     exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
</span><span class="cx"> 
</span><span class="cx">                     state.jitCode-&gt;osrExit.append(exit);
</span><span class="lines">@@ -586,13 +586,13 @@
</span><span class="cx">             OSRExit&amp; exit = state.jitCode-&gt;osrExit[i];
</span><span class="cx">             
</span><span class="cx">             if (verboseCompilationEnabled())
</span><del>-                dataLog(&quot;Handling OSR stackmap #&quot;, exit.m_descriptor.m_stackmapID, &quot; for &quot;, exit.m_codeOrigin, &quot;\n&quot;);
</del><ins>+                dataLog(&quot;Handling OSR stackmap #&quot;, exit.m_descriptor-&gt;m_stackmapID, &quot; for &quot;, exit.m_codeOrigin, &quot;\n&quot;);
</ins><span class="cx"> 
</span><span class="cx">             info.m_thunkAddress = linkBuffer-&gt;locationOf(info.m_thunkLabel);
</span><span class="cx">             exit.m_patchableCodeOffset = linkBuffer-&gt;offsetOf(info.m_thunkJump);
</span><span class="cx"> 
</span><span class="cx">             if (exit.willArriveAtOSRExitFromGenericUnwind()) {
</span><del>-                HandlerInfo newHandler = exit.m_descriptor.m_baselineExceptionHandler;
</del><ins>+                HandlerInfo newHandler = exit.m_descriptor-&gt;m_baselineExceptionHandler;
</ins><span class="cx">                 newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
</span><span class="cx">                 newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
</span><span class="cx">                 newHandler.nativeCode = info.m_thunkAddress;
</span><span class="lines">@@ -601,10 +601,10 @@
</span><span class="cx"> 
</span><span class="cx">             if (verboseCompilationEnabled()) {
</span><span class="cx">                 DumpContext context;
</span><del>-                dataLog(&quot;    Exit values: &quot;, inContext(exit.m_descriptor.m_values, &amp;context), &quot;\n&quot;);
-                if (!exit.m_descriptor.m_materializations.isEmpty()) {
</del><ins>+                dataLog(&quot;    Exit values: &quot;, inContext(exit.m_descriptor-&gt;m_values, &amp;context), &quot;\n&quot;);
+                if (!exit.m_descriptor-&gt;m_materializations.isEmpty()) {
</ins><span class="cx">                     dataLog(&quot;    Materializations: \n&quot;);
</span><del>-                    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
</del><ins>+                    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations)
</ins><span class="cx">                         dataLog(&quot;        Materialize(&quot;, pointerDump(materialization), &quot;)\n&quot;);
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="lines">@@ -997,7 +997,7 @@
</span><span class="cx">         
</span><span class="cx">         codeAddresses.append(bitwise_cast&lt;char*&gt;(generatedFunction) + record.instructionOffset + MacroAssembler::maxJumpReplacementSize());
</span><span class="cx">         
</span><del>-        if (exit.m_descriptor.m_isInvalidationPoint)
</del><ins>+        if (exit.m_descriptor-&gt;m_isInvalidationPoint)
</ins><span class="cx">             jitCode-&gt;common.jumpReplacements.append(JumpReplacement(source, info.m_thunkAddress));
</span><span class="cx">         else
</span><span class="cx">             MacroAssembler::replaceWithJump(source, info.m_thunkAddress);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">         return CodeLocationLabel();
</span><span class="cx"> 
</span><span class="cx">     size_t osrExitIndex = findResult-&gt;value;
</span><del>-    RELEASE_ASSERT(m_state.jitCode-&gt;osrExit[osrExitIndex].m_descriptor.m_exceptionType == ExceptionType::LazySlowPath);
</del><ins>+    RELEASE_ASSERT(m_state.jitCode-&gt;osrExit[osrExitIndex].m_descriptor-&gt;m_exceptionType == ExceptionType::LazySlowPath);
</ins><span class="cx">     OSRExitCompilationInfo&amp; info = m_state.finalizer-&gt;osrExit[osrExitIndex];
</span><span class="cx">     RELEASE_ASSERT(info.m_thunkLabel.isSet());
</span><span class="cx">     return m_state.finalizer-&gt;exitThunksLinkBuffer-&gt;locationOf(info.m_thunkLabel);
</span><span class="lines">@@ -109,7 +109,7 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     size_t osrExitIndex = findResult-&gt;value;
</span><span class="cx">     OSRExit* exit = &amp;m_state.jitCode-&gt;osrExit[osrExitIndex];
</span><del>-    RELEASE_ASSERT(exit-&gt;m_descriptor.m_exceptionType == ExceptionType::JSCall);
</del><ins>+    RELEASE_ASSERT(exit-&gt;m_descriptor-&gt;m_exceptionType == ExceptionType::JSCall);
</ins><span class="cx">     return exit; 
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;FTLExitThunkGenerator.h&quot;
</span><span class="cx"> 
</span><del>-#if ENABLE(FTL_JIT)
</del><ins>+#if ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;FTLOSRExitCompilationInfo.h&quot;
</span><span class="cx"> #include &quot;FTLState.h&quot;
</span><span class="lines">@@ -79,5 +79,5 @@
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><del>-#endif // ENABLE(FTL_JIT)
</del><ins>+#endif // ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -26,8 +26,10 @@
</span><span class="cx"> #ifndef FTLExitThunkGenerator_h
</span><span class="cx"> #define FTLExitThunkGenerator_h
</span><span class="cx"> 
</span><del>-#if ENABLE(FTL_JIT)
</del><ins>+#include &quot;DFGCommon.h&quot;
</ins><span class="cx"> 
</span><ins>+#if ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
+
</ins><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="lines">@@ -52,7 +54,7 @@
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><del>-#endif // ENABLE(FTL_JIT)
</del><ins>+#endif // ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx"> #endif // FTLExitThunkGenerator_h
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -32,6 +32,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+using namespace B3;
+
</ins><span class="cx"> JITCode::JITCode()
</span><span class="cx">     : JSC::JITCode(FTLJIT)
</span><span class="cx"> {
</span><span class="lines">@@ -60,6 +62,11 @@
</span><span class="cx"> {
</span><span class="cx">     m_b3Code = b3Code;
</span><span class="cx"> }
</span><ins>+
+void JITCode::initializeB3Byproducts(std::unique_ptr&lt;OpaqueByproducts&gt; byproducts)
+{
+    m_b3Byproducts = WTF::move(byproducts);
+}
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx"> void JITCode::initializeExitThunks(CodeRef exitThunks)
</span><span class="cx"> {
</span><span class="lines">@@ -155,17 +162,21 @@
</span><span class="cx">     common.validateReferences(trackedReferences);
</span><span class="cx">     
</span><span class="cx">     for (OSRExit&amp; exit : osrExit)
</span><del>-        exit.m_descriptor.validateReferences(trackedReferences);
</del><ins>+        exit.m_descriptor-&gt;validateReferences(trackedReferences);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex callSiteIndex)
</span><span class="cx"> {
</span><ins>+#if FTL_USES_B3
+    UNUSED_PARAM(callSiteIndex);
+#else // FTL_USES_B3
</ins><span class="cx">     for (OSRExit&amp; exit : osrExit) {
</span><span class="cx">         if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
</span><span class="cx">             RELEASE_ASSERT(exit.m_isExceptionHandler);
</span><span class="cx">             return stackmaps.records[exit.m_stackmapRecordIndex].usedRegisterSet();
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">     return RegisterSet();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3OpaqueByproducts.h&quot;
</ins><span class="cx"> #include &quot;DFGCommonData.h&quot;
</span><span class="cx"> #include &quot;FTLDataSection.h&quot;
</span><span class="cx"> #include &quot;FTLLazySlowPath.h&quot;
</span><span class="lines">@@ -68,6 +69,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">     void initializeB3Code(CodeRef);
</span><ins>+    void initializeB3Byproducts(std::unique_ptr&lt;B3::OpaqueByproducts&gt;);
</ins><span class="cx"> #else
</span><span class="cx">     void initializeExitThunks(CodeRef);
</span><span class="cx">     void addHandle(PassRefPtr&lt;ExecutableMemoryHandle&gt;);
</span><span class="lines">@@ -95,13 +97,16 @@
</span><span class="cx">     DFG::CommonData common;
</span><span class="cx">     SegmentedVector&lt;OSRExit, 8&gt; osrExit;
</span><span class="cx">     SegmentedVector&lt;OSRExitDescriptor, 8&gt; osrExitDescriptors;
</span><ins>+#if !FTL_USES_B3
</ins><span class="cx">     StackMaps stackmaps;
</span><ins>+#endif // !FTL_USES_B3
</ins><span class="cx">     Vector&lt;std::unique_ptr&lt;LazySlowPath&gt;&gt; lazySlowPaths;
</span><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     CodePtr m_addressForCall;
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">     CodeRef m_b3Code;
</span><ins>+    std::unique_ptr&lt;B3::OpaqueByproducts&gt; m_b3Byproducts;
</ins><span class="cx"> #else
</span><span class="cx">     Vector&lt;RefPtr&lt;DataSection&gt;&gt; m_dataSections;
</span><span class="cx">     Vector&lt;RefPtr&lt;ExecutableMemoryHandle&gt;&gt; m_handles;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -82,13 +82,6 @@
</span><span class="cx">     bool dumpDisassembly = shouldDumpDisassembly() || Options::asyncDisassembly();
</span><span class="cx">     
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    for (OSRExitCompilationInfo&amp; info : osrExit) {
-        b3CodeLinkBuffer-&gt;link(
-            info.m_thunkJump,
-            CodeLocationLabel(
-                m_plan.vm.getCTIStub(osrExitGenerationThunkGenerator).code()));
-    }
-    
</del><span class="cx">     jitCode-&gt;initializeB3Code(
</span><span class="cx">         FINALIZE_CODE_IF(
</span><span class="cx">             dumpDisassembly, *b3CodeLinkBuffer,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITFinalizerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -73,9 +73,9 @@
</span><span class="cx">     std::unique_ptr&lt;LinkBuffer&gt; sideCodeLinkBuffer;
</span><span class="cx">     std::unique_ptr&lt;LinkBuffer&gt; handleExceptionsLinkBuffer;
</span><span class="cx">     Vector&lt;OutOfLineCodeInfo&gt; outOfLineCodeInfos;
</span><ins>+    Vector&lt;OSRExitCompilationInfo&gt; osrExit;
</ins><span class="cx"> #endif
</span><del>-    
-    Vector&lt;OSRExitCompilationInfo&gt; osrExit;
</del><ins>+
</ins><span class="cx">     Vector&lt;CCallHelpers::Jump&gt; lazySlowPathGeneratorJumps;
</span><span class="cx">     GeneratedFunction function;
</span><span class="cx">     RefPtr&lt;JITCode&gt; jitCode;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJSCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJSCall.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJSCall.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJSCall.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -54,7 +54,11 @@
</span><span class="cx"> {
</span><span class="cx">     JSCallBase::emit(jit, state, osrExitFromGenericUnwindSpillSlots);
</span><span class="cx"> 
</span><ins>+#if FTL_USES_B3
+    jit.addPtr(CCallHelpers::TrustedImm32(- static_cast&lt;int64_t&gt;(state.jitCode-&gt;common.frameRegisterCount * sizeof(EncodedJSValue))), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+#else // FTL_USES_B3
</ins><span class="cx">     jit.addPtr(CCallHelpers::TrustedImm32(- static_cast&lt;int64_t&gt;(state.jitCode-&gt;stackmaps.stackSizeForLocals())), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJSCallBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -54,9 +54,13 @@
</span><span class="cx"> void JSCallBase::emit(CCallHelpers&amp; jit, State&amp; /*state*/, int32_t osrExitFromGenericUnwindStackSpillSlot)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!!m_callSiteIndex);
</span><del>-    
</del><ins>+
+#if FTL_USES_B3
+    UNUSED_PARAM(osrExitFromGenericUnwindStackSpillSlot);
+#else // FTL_USES_B3
</ins><span class="cx">     if (m_correspondingGenericUnwindOSRExit)
</span><span class="cx">         m_correspondingGenericUnwindOSRExit-&gt;spillRegistersToSpillSlot(jit, osrExitFromGenericUnwindStackSpillSlot);
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx">     jit.store32(CCallHelpers::TrustedImm32(m_callSiteIndex.bits()), CCallHelpers::tagFor(static_cast&lt;VirtualRegister&gt;(JSStack::ArgumentCount)));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJSTailCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -38,8 +38,27 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+using namespace B3;
</ins><span class="cx"> using namespace DFG;
</span><span class="cx"> 
</span><ins>+#if FTL_USES_B3
+
+JSTailCall::JSTailCall(PatchpointValue* patchpoint, Node* node, const Vector&lt;ExitValue&gt;&amp; arguments)
+    : JSCallBase(CallLinkInfo::TailCall, node-&gt;origin.semantic, node-&gt;origin.semantic)
+    , m_patchpoint(patchpoint)
+    , m_arguments(arguments)
+    , m_instructionOffset(0)
+{
+    UNREACHABLE_FOR_PLATFORM();
+}
+
+void JSTailCall::emit(JITCode&amp;, CCallHelpers&amp;)
+{
+    UNREACHABLE_FOR_PLATFORM();
+}
+
+#else // FTL_USES_B3
+
</ins><span class="cx"> namespace {
</span><span class="cx"> 
</span><span class="cx"> FTL::Location getRegisterWithAddend(const ExitValue&amp; value, StackMaps::Record&amp; record, StackMaps&amp; stackmaps)
</span><span class="lines">@@ -180,10 +199,10 @@
</span><span class="cx"> 
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><del>-JSTailCall::JSTailCall(unsigned stackmapID, Node* node, Vector&lt;ExitValue&gt; arguments)
</del><ins>+JSTailCall::JSTailCall(unsigned stackmapID, Node* node, const Vector&lt;ExitValue&gt;&amp; arguments)
</ins><span class="cx">     : JSCallBase(CallLinkInfo::TailCall, node-&gt;origin.semantic, node-&gt;origin.semantic)
</span><span class="cx">     , m_stackmapID(stackmapID)
</span><del>-    , m_arguments { WTF::move(arguments) }
</del><ins>+    , m_arguments(arguments)
</ins><span class="cx">     , m_instructionOffset(0)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(node-&gt;op() == TailCall);
</span><span class="lines">@@ -323,6 +342,8 @@
</span><span class="cx">     m_callLinkInfo-&gt;setUpCall(m_type, m_semanticeOrigin, calleeGPR);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#endif // FTL_USES_B3
+
</ins><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJSTailCallh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLJSTailCall.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3PatchpointValue.h&quot;
+#include &quot;DFGCommon.h&quot;
</ins><span class="cx"> #include &quot;FTLExitValue.h&quot;
</span><span class="cx"> #include &quot;FTLJSCallBase.h&quot;
</span><span class="cx"> #include &quot;FTLStackmapArgumentList.h&quot;
</span><span class="lines">@@ -42,11 +44,21 @@
</span><span class="cx"> 
</span><span class="cx"> class JSTailCall : public JSCallBase {
</span><span class="cx"> public:
</span><del>-    JSTailCall(unsigned stackmapID, DFG::Node*, Vector&lt;ExitValue&gt; arguments);
</del><ins>+    JSTailCall(
+#if FTL_USES_B3
+        B3::PatchpointValue*,
+#else // FTL_USES_B3
+        unsigned stackmapID,
+#endif // FTL_USES_B3
+        DFG::Node*, const Vector&lt;ExitValue&gt;&amp; arguments);
</ins><span class="cx"> 
</span><span class="cx">     void emit(JITCode&amp;, CCallHelpers&amp;);
</span><del>-    
</del><ins>+
+#if FTL_USES_B3
+    B3::PatchpointValue* patchpoint() const { return m_patchpoint; }
+#else // FTL_USES_B3
</ins><span class="cx">     unsigned stackmapID() const { return m_stackmapID; }
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx">     unsigned estimatedSize() const { return m_estimatedSize; }
</span><span class="cx"> 
</span><span class="lines">@@ -58,7 +70,11 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> private:
</span><ins>+#if FTL_USES_B3
+    B3::PatchpointValue* m_patchpoint;
+#else // FTL_USES_B3
</ins><span class="cx">     unsigned m_stackmapID;
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">     Vector&lt;ExitValue&gt; m_arguments;
</span><span class="cx">     unsigned m_estimatedSize;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -5374,14 +5374,12 @@
</span><span class="cx">         DFG_ASSERT(m_graph, m_node, m_origin.exitOK);
</span><span class="cx">         
</span><span class="cx"> 
</span><del>-        appendOSRExitDescriptor(UncountableInvalidation, ExceptionType::None, noValue(), nullptr, m_origin);
</del><ins>+        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(UncountableInvalidation, ExceptionType::None, noValue(), nullptr, m_origin);
</ins><span class="cx">         
</span><del>-        OSRExitDescriptor&amp; exitDescriptor = m_ftlState.jitCode-&gt;osrExitDescriptors.last();
-        
</del><span class="cx">         StackmapArgumentList arguments = buildExitArguments(exitDescriptor, FormattedValue());
</span><span class="cx">         callStackmap(exitDescriptor, arguments);
</span><span class="cx">         
</span><del>-        exitDescriptor.m_isInvalidationPoint = true;
</del><ins>+        exitDescriptor-&gt;m_isInvalidationPoint = true;
</ins><span class="cx"> #endif // FTL_USES_B3
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -9267,11 +9265,10 @@
</span><span class="cx">         if (!willCatchException)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
-        OSRExitDescriptor&amp; exitDescriptor = m_ftlState.jitCode-&gt;osrExitDescriptors.last();
-        exitDescriptor.m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
-        exitDescriptor.m_baselineExceptionHandler = *exceptionHandler;
-        exitDescriptor.m_stackmapID = m_stackmapIDs - 1;
</del><ins>+        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
+        exitDescriptor-&gt;m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
+        exitDescriptor-&gt;m_baselineExceptionHandler = *exceptionHandler;
+        exitDescriptor-&gt;m_stackmapID = m_stackmapIDs - 1;
</ins><span class="cx"> 
</span><span class="cx">         StackmapArgumentList freshList =
</span><span class="cx">             buildExitArguments(exitDescriptor, noValue(), offsetOfExitArguments);
</span><span class="lines">@@ -9295,9 +9292,9 @@
</span><span class="cx">         return m_blocks.get(block);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    OSRExitDescriptor&amp; appendOSRExitDescriptor(ExitKind kind, ExceptionType exceptionType, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
</del><ins>+    OSRExitDescriptor* appendOSRExitDescriptor(ExitKind kind, ExceptionType exceptionType, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
</ins><span class="cx">     {
</span><del>-        return m_ftlState.jitCode-&gt;osrExitDescriptors.alloc(
</del><ins>+        return &amp;m_ftlState.jitCode-&gt;osrExitDescriptors.alloc(
</ins><span class="cx">             kind, exceptionType, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
</span><span class="cx">             origin.forExit, origin.semantic,
</span><span class="cx">             availabilityMap().m_locals.numberOfArguments(),
</span><span class="lines">@@ -9342,7 +9339,7 @@
</span><span class="cx">         blessSpeculation(
</span><span class="cx">             m_out.speculate(failCondition), kind, lowValue, highValue, origin, isExceptionHandler);
</span><span class="cx"> #else // FTL_USES_B3
</span><del>-        OSRExitDescriptor&amp; exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
</del><ins>+        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
</ins><span class="cx"> 
</span><span class="cx">         if (failCondition == m_out.booleanTrue) {
</span><span class="cx">             emitOSRExitCall(exitDescriptor, lowValue);
</span><span class="lines">@@ -9368,26 +9365,32 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    void blessSpeculation(B3::StackmapValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
</del><ins>+    void blessSpeculation(B3::CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
</ins><span class="cx">     {
</span><del>-        OSRExitDescriptor&amp; exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
</del><ins>+        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(
+            kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue,
+            highValue, origin);
+        
+        unsigned offset = value-&gt;numChildren();
</ins><span class="cx">         value-&gt;appendAnys(buildExitArguments(exitDescriptor, lowValue));
</span><ins>+
+        State* state = &amp;m_ftlState;
</ins><span class="cx">         value-&gt;setGenerator(
</span><del>-            [&amp;] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp;) {
-                jit.oops();
</del><ins>+            [=] (CCallHelpers&amp; jit, const B3::StackmapGenerationParams&amp; params) {
+                exitDescriptor-&gt;emitOSRExit(*state, jit, params, offset);
</ins><span class="cx">             });
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if !FTL_USES_B3
</span><del>-    void emitOSRExitCall(OSRExitDescriptor&amp; exitDescriptor, FormattedValue lowValue)
</del><ins>+    void emitOSRExitCall(OSRExitDescriptor* exitDescriptor, FormattedValue lowValue)
</ins><span class="cx">     {
</span><span class="cx">         callStackmap(exitDescriptor, buildExitArguments(exitDescriptor, lowValue));
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     StackmapArgumentList buildExitArguments(
</span><del>-        OSRExitDescriptor&amp; exitDescriptor, FormattedValue lowValue,
</del><ins>+        OSRExitDescriptor* exitDescriptor, FormattedValue lowValue,
</ins><span class="cx">         unsigned offsetOfExitArgumentsInStackmapLocations = 0)
</span><span class="cx">     {
</span><span class="cx">         StackmapArgumentList result;
</span><span class="lines">@@ -9397,14 +9400,14 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void buildExitArguments(
</span><del>-        OSRExitDescriptor&amp; exitDescriptor, StackmapArgumentList&amp; arguments, FormattedValue lowValue,
</del><ins>+        OSRExitDescriptor* exitDescriptor, StackmapArgumentList&amp; arguments, FormattedValue lowValue,
</ins><span class="cx">         unsigned offsetOfExitArgumentsInStackmapLocations = 0)
</span><span class="cx">     {
</span><span class="cx">         if (!!lowValue)
</span><span class="cx">             arguments.append(lowValue.value());
</span><span class="cx">         
</span><span class="cx">         AvailabilityMap availabilityMap = this-&gt;availabilityMap();
</span><del>-        availabilityMap.pruneByLiveness(m_graph, exitDescriptor.m_codeOrigin);
</del><ins>+        availabilityMap.pruneByLiveness(m_graph, exitDescriptor-&gt;m_codeOrigin);
</ins><span class="cx">         
</span><span class="cx">         HashMap&lt;Node*, ExitTimeObjectMaterialization*&gt; map;
</span><span class="cx">         availabilityMap.forEachAvailability(
</span><span class="lines">@@ -9419,24 +9422,24 @@
</span><span class="cx">                 auto result = map.add(node, nullptr);
</span><span class="cx">                 if (result.isNewEntry) {
</span><span class="cx">                     result.iterator-&gt;value =
</span><del>-                        exitDescriptor.m_materializations.add(node-&gt;op(), node-&gt;origin.semantic);
</del><ins>+                        exitDescriptor-&gt;m_materializations.add(node-&gt;op(), node-&gt;origin.semantic);
</ins><span class="cx">                 }
</span><span class="cx">             });
</span><span class="cx">         
</span><del>-        for (unsigned i = 0; i &lt; exitDescriptor.m_values.size(); ++i) {
-            int operand = exitDescriptor.m_values.operandForIndex(i);
</del><ins>+        for (unsigned i = 0; i &lt; exitDescriptor-&gt;m_values.size(); ++i) {
+            int operand = exitDescriptor-&gt;m_values.operandForIndex(i);
</ins><span class="cx">             
</span><span class="cx">             Availability availability = availabilityMap.m_locals[i];
</span><span class="cx">             
</span><span class="cx">             if (Options::validateFTLOSRExitLiveness()) {
</span><span class="cx">                 DFG_ASSERT(
</span><span class="cx">                     m_graph, m_node,
</span><del>-                    (!(availability.isDead() &amp;&amp; m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptor.m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
</del><ins>+                    (!(availability.isDead() &amp;&amp; m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptor-&gt;m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
</ins><span class="cx">             }
</span><span class="cx">             ExitValue exitValue = exitValueForAvailability(arguments, map, availability);
</span><span class="cx">             if (exitValue.hasIndexInStackmapLocations())
</span><span class="cx">                 exitValue.adjustStackmapLocationsIndexByOffset(offsetOfExitArgumentsInStackmapLocations);
</span><del>-            exitDescriptor.m_values[i] = exitValue;
</del><ins>+            exitDescriptor-&gt;m_values[i] = exitValue;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         for (auto heapPair : availabilityMap.m_heap) {
</span><span class="lines">@@ -9451,21 +9454,21 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (verboseCompilationEnabled()) {
</span><del>-            dataLog(&quot;        Exit values: &quot;, exitDescriptor.m_values, &quot;\n&quot;);
-            if (!exitDescriptor.m_materializations.isEmpty()) {
</del><ins>+            dataLog(&quot;        Exit values: &quot;, exitDescriptor-&gt;m_values, &quot;\n&quot;);
+            if (!exitDescriptor-&gt;m_materializations.isEmpty()) {
</ins><span class="cx">                 dataLog(&quot;        Materializations: \n&quot;);
</span><del>-                for (ExitTimeObjectMaterialization* materialization : exitDescriptor.m_materializations)
</del><ins>+                for (ExitTimeObjectMaterialization* materialization : exitDescriptor-&gt;m_materializations)
</ins><span class="cx">                     dataLog(&quot;            &quot;, pointerDump(materialization), &quot;\n&quot;);
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if !FTL_USES_B3
</span><del>-    void callStackmap(OSRExitDescriptor&amp; exitDescriptor, StackmapArgumentList arguments)
</del><ins>+    void callStackmap(OSRExitDescriptor* exitDescriptor, StackmapArgumentList arguments)
</ins><span class="cx">     {
</span><del>-        exitDescriptor.m_stackmapID = m_stackmapIDs++;
</del><ins>+        exitDescriptor-&gt;m_stackmapID = m_stackmapIDs++;
</ins><span class="cx">         arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
</span><del>-        arguments.insert(0, m_out.constInt64(exitDescriptor.m_stackmapID));
</del><ins>+        arguments.insert(0, m_out.constInt64(exitDescriptor-&gt;m_stackmapID));
</ins><span class="cx">         
</span><span class="cx">         m_out.call(m_out.voidType, m_out.stackmapIntrinsic(), arguments);
</span><span class="cx">     }
</span><span class="lines">@@ -9929,10 +9932,6 @@
</span><span class="cx"> 
</span><span class="cx"> void lowerDFGToLLVM(State&amp; state)
</span><span class="cx"> {
</span><del>-#if FTL_USES_B3
-    state.proc = std::make_unique&lt;Procedure&gt;();
-#endif
-
</del><span class="cx">     LowerDFGToLLVM lowering(state);
</span><span class="cx">     lowering.lower();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 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">@@ -28,16 +28,20 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirGenerationContext.h&quot;
+#include &quot;B3StackmapValue.h&quot;
</ins><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;DFGBasicBlock.h&quot;
</span><span class="cx"> #include &quot;DFGNode.h&quot;
</span><span class="cx"> #include &quot;FTLExitArgument.h&quot;
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLLocation.h&quot;
</span><ins>+#include &quot;FTLState.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+using namespace B3;
</ins><span class="cx"> using namespace DFG;
</span><span class="cx"> 
</span><span class="cx"> OSRExitDescriptor::OSRExitDescriptor(
</span><span class="lines">@@ -70,23 +74,61 @@
</span><span class="cx">         materialization-&gt;validateReferences(trackedReferences);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if FTL_USES_B3
+RefPtr&lt;OSRExitHandle&gt; OSRExitDescriptor::emitOSRExit(
+    State&amp; state, CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params, unsigned offset)
+{
+    RefPtr&lt;OSRExitHandle&gt; handle = prepareOSRExitHandle(state, params, offset);
+    handle-&gt;emitExitThunk(jit);
+    return handle;
+}
</ins><span class="cx"> 
</span><del>-OSRExit::OSRExit(OSRExitDescriptor&amp; descriptor, uint32_t stackmapRecordIndex)
-    : OSRExitBase(descriptor.m_kind, descriptor.m_codeOrigin, descriptor.m_codeOriginForExitProfile)
</del><ins>+RefPtr&lt;OSRExitHandle&gt; OSRExitDescriptor::emitOSRExitLater(
+    State&amp; state, const StackmapGenerationParams&amp; params, unsigned offset)
+{
+    RefPtr&lt;OSRExitHandle&gt; handle = prepareOSRExitHandle(state, params, offset);
+    params.context-&gt;latePaths.append(
+        createSharedTask&lt;Air::GenerationContext::LatePathFunction&gt;(
+            [handle] (CCallHelpers&amp; jit, Air::GenerationContext&amp;) {
+                handle-&gt;emitExitThunk(jit);
+            }));
+    return handle;
+}
+
+RefPtr&lt;OSRExitHandle&gt; OSRExitDescriptor::prepareOSRExitHandle(
+    State&amp; state, const StackmapGenerationParams&amp; params, unsigned offset)
+{
+    unsigned index = state.jitCode-&gt;osrExit.size();
+    RefPtr&lt;OSRExitHandle&gt; handle = adoptRef(
+        new OSRExitHandle(index, state.jitCode-&gt;osrExit.alloc(this)));
+    for (unsigned i = offset; i &lt; params.reps.size(); ++i)
+        handle-&gt;exit.m_valueReps.append(params.reps[i]);
+    handle-&gt;exit.m_valueReps.shrinkToFit();
+    return handle;
+}
+#endif // FTL_USES_B3
+
+OSRExit::OSRExit(
+    OSRExitDescriptor* descriptor
+#if !FTL_USES_B3
+    , uint32_t stackmapRecordIndex
+#endif // !FTL_USES_B3
+    )
+    : OSRExitBase(descriptor-&gt;m_kind, descriptor-&gt;m_codeOrigin, descriptor-&gt;m_codeOriginForExitProfile)
</ins><span class="cx">     , m_descriptor(descriptor)
</span><ins>+#if !FTL_USES_B3
</ins><span class="cx">     , m_stackmapRecordIndex(stackmapRecordIndex)
</span><del>-    , m_exceptionType(descriptor.m_exceptionType)
</del><ins>+#endif // !FTL_USES_B3
+    , m_exceptionType(descriptor-&gt;m_exceptionType)
</ins><span class="cx"> {
</span><del>-    m_isExceptionHandler = descriptor.isExceptionHandler();
</del><ins>+    m_isExceptionHandler = descriptor-&gt;isExceptionHandler();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const
</span><span class="cx"> {
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    return CodeLocationJump(
-        reinterpret_cast&lt;char*&gt;(
-            ftlCodeBlock-&gt;jitCode()-&gt;ftl()-&gt;b3Code().code().dataLocation()) +
-        m_patchableCodeOffset);
</del><ins>+    UNUSED_PARAM(ftlCodeBlock);
+    return m_patchableJump;
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">     return CodeLocationJump(
</span><span class="cx">         reinterpret_cast&lt;char*&gt;(
</span><span class="lines">@@ -95,9 +137,10 @@
</span><span class="cx"> #endif // FTL_USES_B3
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !FTL_USES_B3
</ins><span class="cx"> void OSRExit::gatherRegistersToSpillForCallIfException(StackMaps&amp; stackmaps, StackMaps::Record&amp; record)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_descriptor.m_exceptionType == ExceptionType::JSCall);
</del><ins>+    RELEASE_ASSERT(m_descriptor-&gt;m_exceptionType == ExceptionType::JSCall);
</ins><span class="cx"> 
</span><span class="cx">     RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall();
</span><span class="cx"> 
</span><span class="lines">@@ -121,12 +164,12 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     };
</span><del>-    for (ExitTimeObjectMaterialization* materialization : m_descriptor.m_materializations) {
</del><ins>+    for (ExitTimeObjectMaterialization* materialization : m_descriptor-&gt;m_materializations) {
</ins><span class="cx">         for (unsigned propertyIndex = materialization-&gt;properties().size(); propertyIndex--;)
</span><span class="cx">             addNeededRegisters(materialization-&gt;properties()[propertyIndex].value());
</span><span class="cx">     }
</span><del>-    for (unsigned index = m_descriptor.m_values.size(); index--;)
-        addNeededRegisters(m_descriptor.m_values[index]);
</del><ins>+    for (unsigned index = m_descriptor-&gt;m_values.size(); index--;)
+        addNeededRegisters(m_descriptor-&gt;m_values[index]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void OSRExit::spillRegistersToSpillSlot(CCallHelpers&amp; jit, int32_t stackSpillSlot)
</span><span class="lines">@@ -164,6 +207,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><ins>+#endif // !FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx"> bool OSRExit::willArriveAtExitFromIndirectExceptionCheck() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExith"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3ValueRep.h&quot;
</ins><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGExitProfile.h&quot;
</span><span class="cx"> #include &quot;DFGOSRExitBase.h&quot;
</span><span class="lines">@@ -35,6 +36,7 @@
</span><span class="cx"> #include &quot;FTLExitTimeObjectMaterialization.h&quot;
</span><span class="cx"> #include &quot;FTLExitValue.h&quot;
</span><span class="cx"> #include &quot;FTLFormattedValue.h&quot;
</span><ins>+#include &quot;FTLOSRExitHandle.h&quot;
</ins><span class="cx"> #include &quot;FTLStackMaps.h&quot;
</span><span class="cx"> #include &quot;FTLStackmapArgumentList.h&quot;
</span><span class="cx"> #include &quot;HandlerInfo.h&quot;
</span><span class="lines">@@ -48,93 +50,16 @@
</span><span class="cx"> 
</span><span class="cx"> class TrackedReferences;
</span><span class="cx"> 
</span><ins>+namespace B3 {
+struct StackmapGenerationParams;
+namespace Air {
+struct GenerationContext;
+} // namespace Air
+} // namespace B3
+
</ins><span class="cx"> namespace FTL {
</span><span class="cx"> 
</span><del>-// Tracks one OSR exit site within the FTL JIT. OSR exit in FTL works by deconstructing
-// the crazy that is OSR down to simple SSA CFG primitives that any compiler backend
-// (including of course LLVM) can grok and do meaningful things to. An exit is just a
-// conditional branch in the emitted code where one destination is the continuation and
-// the other is a basic block that performs a no-return tail-call to an  exit thunk.
-// This thunk takes as its arguments the live non-constant not-already-accounted-for
-// bytecode state. To appreciate how this works consider the following JavaScript
-// program, and its lowering down to LLVM IR including the relevant exits:
-//
-// function foo(o) {
-//     var a = o.a; // predicted int
-//     var b = o.b;
-//     var c = o.c; // NB this is dead
-//     a = a | 5; // our example OSR exit: need to check if a is an int
-//     return a + b;
-// }
-//
-// Just consider the &quot;a | 5&quot;. In the DFG IR, this looks like:
-//
-// BitOr(Check:Int32:@a, Int32:5)
-//
-// Where @a is the node for the value of the 'a' variable. Conceptually, this node can
-// be further broken down to the following (note that this particular lowering never
-// actually happens - we skip this step and go straight to LLVM IR - but it's still
-// useful to see this):
-//
-// exitIf(@a is not int32);
-// continuation;
-//
-// Where 'exitIf()' is a function that will exit if the argument is true, and
-// 'continuation' is the stuff that we will do after the exitIf() check. (Note that
-// FTL refers to 'exitIf()' as 'speculate()', which is in line with DFG terminology.)
-// This then gets broken down to the following LLVM IR, assuming that %0 is the LLVM
-// value corresponding to variable 'a', and %1 is the LLVM value for variable 'b':
-//
-//   %2 = ... // the predictate corresponding to '@a is not int32'
-//   br i1 %2, label %3, label %4
-// ; &lt;label&gt;:3
-//   call void exitThunk1(%0, %1) // pass 'a' and 'b', since they're both live-in-bytecode
-//   unreachable
-// ; &lt;label&gt;:4
-//   ... // code for the continuation
-//
-// Where 'exitThunk1' is the IR to get the exit thunk for *this* OSR exit. Each OSR
-// exit will appear to LLVM to have a distinct exit thunk.
-//
-// Note that this didn't have to pass '5', 'o', or 'c' to the exit thunk. 5 is a
-// constant and the DFG already knows that, and can already tell the OSR exit machinery
-// what that contant is and which bytecode variables (if any) it needs to be dropped
-// into. This is conveyed to the exit statically, via the OSRExit data structure below.
-// See the code for ExitValue for details. 'o' is an argument, and arguments are always
-// &quot;flushed&quot; - if you never assign them then their values are still in the argument
-// stack slots, and if you do assign them then we eagerly store them into those slots.
-// 'c' is dead in bytecode, and the DFG knows this; we statically tell the exit thunk
-// that it's dead and don't have to pass anything. The exit thunk will &quot;initialize&quot; its
-// value to Undefined.
-//
-// This approach to OSR exit has a number of virtues:
-//
-// - It is an entirely unsurprising representation for a compiler that already groks
-//   CFG-like IRs for C-like languages. All existing analyses and transformations just
-//   work.
-//
-// - It lends itself naturally to modern approaches to code motion. For example, you
-//   could sink operations from above the exit to below it, if you just duplicate the
-//   operation into the OSR exit block. This is both legal and desirable. It works
-//   because the backend sees the OSR exit block as being no different than any other,
-//   and LLVM already supports sinking if it sees that a value is only partially used.
-//   Hence there exists a value that dominates the exit but is only used by the exit
-//   thunk and not by the continuation, sinking ought to kick in for that value.
-//   Hoisting operations from below it to above it is also possible, for similar
-//   reasons.
-//
-// - The no-return tail-call to the OSR exit thunk can be subjected to specialized
-//   code-size reduction optimizations, though this is optional. For example, instead
-//   of actually emitting a call along with all that goes with it (like placing the
-//   arguments into argument position), the backend could choose to simply inform us
-//   where it had placed the arguments and expect the callee (i.e. the exit thunk) to
-//   figure it out from there. It could also tell us what we need to do to pop stack,
-//   although again, it doesn't have to; it could just emit that code normally. We do
-//   all of these things through the patchpoint/stackmap LLVM intrinsics.
-//
-// - It could be extended to allow the backend to do its own exit hoisting, by using
-//   intrinsics (or meta-data, or something) to inform the backend that it's safe to
-//   make the predicate passed to 'exitIf()' more truthy.
</del><ins>+class State;
</ins><span class="cx"> 
</span><span class="cx"> enum class ExceptionType : uint8_t {
</span><span class="cx">     None,
</span><span class="lines">@@ -175,20 +100,59 @@
</span><span class="cx">     
</span><span class="cx">     uint32_t m_stackmapID;
</span><span class="cx">     HandlerInfo m_baselineExceptionHandler;
</span><del>-    bool m_isInvalidationPoint : 1;
</del><ins>+    bool m_isInvalidationPoint;
</ins><span class="cx">     
</span><span class="cx">     void validateReferences(const TrackedReferences&amp;);
</span><ins>+
+#if FTL_USES_B3
+    // Call this once we have a place to emit the OSR exit jump and we have data about how the state
+    // should be recovered. This effectively emits code that does the exit, though the code is really a
+    // patchable jump and we emit the real code lazily. The description of how to emit the real code is
+    // up to the OSRExit object, which this creates. Note that it's OK to drop the OSRExitHandle object
+    // on the ground. It contains information that is mostly not useful if you use this API, since after
+    // this call, the OSRExit is simply ready to go.
+    RefPtr&lt;OSRExitHandle&gt; emitOSRExit(
+        State&amp;, CCallHelpers&amp;, const B3::StackmapGenerationParams&amp;, unsigned offset);
+
+    // In some cases you want an OSRExit to come into existence, but you don't want to emit it right now.
+    // This will emit the OSR exit in a late path. You can't be sure exactly when that will happen, but
+    // you know that it will be done by the time late path emission is done. So, a linker task will
+    // surely happen after that. You can use the OSRExitHandle to retrieve the exit's label.
+    //
+    // This API is meant to be used for things like exception handling, where some patchpoint wants to
+    // have a place to jump to for OSR exit. It doesn't care where that OSR exit is emitted so long as it
+    // eventually gets access to its label.
+    RefPtr&lt;OSRExitHandle&gt; emitOSRExitLater(
+        State&amp;, const B3::StackmapGenerationParams&amp;, unsigned offset);
+
+    // This is the low-level interface. It will create a handle representing the desire to emit code for
+    // an OSR exit. You can call OSRExitHandle::emitExitThunk() once you have a place to emit it. Note
+    // that the above two APIs are written in terms of this and OSRExitHandle::emitExitThunk().
+    RefPtr&lt;OSRExitHandle&gt; prepareOSRExitHandle(
+        State&amp;, const B3::StackmapGenerationParams&amp;, unsigned offset);
+#endif // FTL_USES_B3
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct OSRExit : public DFG::OSRExitBase {
</span><del>-    OSRExit(OSRExitDescriptor&amp;, uint32_t stackmapRecordIndex);
</del><ins>+    OSRExit(
+        OSRExitDescriptor*
+#if !FTL_USES_B3
+        , uint32_t stackmapRecordIndex
+#endif // !FTL_USES_B3
+        );
</ins><span class="cx"> 
</span><del>-    OSRExitDescriptor&amp; m_descriptor;
</del><ins>+    OSRExitDescriptor* m_descriptor;
</ins><span class="cx">     MacroAssemblerCodeRef m_code;
</span><ins>+#if FTL_USES_B3
+    // This tells us where to place a jump.
+    CodeLocationJump m_patchableJump;
+    Vector&lt;B3::ValueRep&gt; m_valueReps;
+#else // FTL_USES_B3
</ins><span class="cx">     // Offset within the exit stubs of the stub for this exit.
</span><span class="cx">     unsigned m_patchableCodeOffset;
</span><span class="cx">     // Offset within Stackmap::records
</span><span class="cx">     uint32_t m_stackmapRecordIndex;
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">     ExceptionType m_exceptionType;
</span><span class="cx"> 
</span><span class="cx">     RegisterSet registersToPreserveForCallThatMightThrow;
</span><span class="lines">@@ -199,9 +163,11 @@
</span><span class="cx">         OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromFTL);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if !FTL_USES_B3
</ins><span class="cx">     void gatherRegistersToSpillForCallIfException(StackMaps&amp;, StackMaps::Record&amp;);
</span><span class="cx">     void spillRegistersToSpillSlot(CCallHelpers&amp;, int32_t stackSpillSlot);
</span><span class="cx">     void recoverRegistersFromSpillSlot(CCallHelpers&amp; jit, int32_t stackSpillSlot);
</span><ins>+#endif // !FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx">     bool willArriveAtOSRExitFromGenericUnwind() const;
</span><span class="cx">     bool willArriveAtExitFromIndirectExceptionCheck() const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilationInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -26,8 +26,10 @@
</span><span class="cx"> #ifndef FTLOSRExitCompilationInfo_h
</span><span class="cx"> #define FTLOSRExitCompilationInfo_h
</span><span class="cx"> 
</span><del>-#if ENABLE(FTL_JIT)
</del><ins>+#include &quot;DFGCommon.h&quot;
</ins><span class="cx"> 
</span><ins>+#if ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
+
</ins><span class="cx"> #include &quot;FTLAbbreviatedTypes.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -37,7 +39,7 @@
</span><span class="cx">     OSRExitCompilationInfo()
</span><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     MacroAssembler::Label m_thunkLabel;
</span><span class="cx">     MacroAssembler::PatchableJump m_thunkJump;
</span><span class="cx">     CodeLocationLabel m_thunkAddress;
</span><span class="lines">@@ -45,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><del>-#endif // ENABLE(FTL_JIT)
</del><ins>+#endif // ENABLE(FTL_JIT) &amp;&amp; !FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx"> #endif // FTLOSRExitCompilationInfo_h
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -98,7 +98,12 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void compileRecovery(
</span><del>-    CCallHelpers&amp; jit, const ExitValue&amp; value, StackMaps::Record* record, StackMaps&amp; stackmaps,
</del><ins>+    CCallHelpers&amp; jit, const ExitValue&amp; value,
+#if FTL_USES_B3
+    Vector&lt;B3::ValueRep&gt;&amp; valueReps,
+#else // FTL_USES_B3
+    StackMaps::Record* record, StackMaps&amp; stackmaps,
+#endif // FTL_USES_B3
</ins><span class="cx">     char* registerScratch,
</span><span class="cx">     const HashMap&lt;ExitTimeObjectMaterialization*, EncodedJSValue*&gt;&amp; materializationToPointer)
</span><span class="cx"> {
</span><span class="lines">@@ -112,8 +117,13 @@
</span><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case ExitValueArgument:
</span><ins>+#if FTL_USES_B3
+        Location::forValueRep(valueReps[value.exitArgument().argument()]).restoreInto(
+            jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
</ins><span class="cx">         record-&gt;locations[value.exitArgument().argument()].restoreInto(
</span><span class="cx">             jit, stackmaps, registerScratch, GPRInfo::regT0);
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case ExitValueInJSStack:
</span><span class="lines">@@ -124,10 +134,17 @@
</span><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case ExitValueRecovery:
</span><ins>+#if FTL_USES_B3
+        Location::forValueRep(valueReps[value.rightRecoveryArgument()]).restoreInto(
+            jit, registerScratch, GPRInfo::regT1);
+        Location::forValueRep(valueReps[value.leftRecoveryArgument()]).restoreInto(
+            jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
</ins><span class="cx">         record-&gt;locations[value.rightRecoveryArgument()].restoreInto(
</span><span class="cx">             jit, stackmaps, registerScratch, GPRInfo::regT1);
</span><span class="cx">         record-&gt;locations[value.leftRecoveryArgument()].restoreInto(
</span><span class="cx">             jit, stackmaps, registerScratch, GPRInfo::regT0);
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">         switch (value.recoveryOpcode()) {
</span><span class="cx">         case AddRecovery:
</span><span class="cx">             switch (value.recoveryFormat()) {
</span><span class="lines">@@ -177,8 +194,12 @@
</span><span class="cx"> static void compileStub(
</span><span class="cx">     unsigned exitID, JITCode* jitCode, OSRExit&amp; exit, VM* vm, CodeBlock* codeBlock)
</span><span class="cx"> {
</span><ins>+#if FTL_USES_B3
+    UNUSED_PARAM(jitCode);
+#else // FTL_USES_B3
</ins><span class="cx">     StackMaps::Record* record = &amp;jitCode-&gt;stackmaps.records[exit.m_stackmapRecordIndex];
</span><del>-    RELEASE_ASSERT(record-&gt;patchpointID == exit.m_descriptor.m_stackmapID);
</del><ins>+    RELEASE_ASSERT(record-&gt;patchpointID == exit.m_descriptor-&gt;m_stackmapID);
+#endif // FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx">     // This code requires framePointerRegister is the same as callFrameRegister
</span><span class="cx">     static_assert(MacroAssembler::framePointerRegister == GPRInfo::callFrameRegister, &quot;MacroAssembler::framePointerRegister and GPRInfo::callFrameRegister must be the same&quot;);
</span><span class="lines">@@ -192,7 +213,7 @@
</span><span class="cx">     // Figure out how much space we need for those object allocations.
</span><span class="cx">     unsigned numMaterializations = 0;
</span><span class="cx">     size_t maxMaterializationNumArguments = 0;
</span><del>-    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
</del><ins>+    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations) {
</ins><span class="cx">         numMaterializations++;
</span><span class="cx">         
</span><span class="cx">         maxMaterializationNumArguments = std::max(
</span><span class="lines">@@ -202,21 +223,32 @@
</span><span class="cx">     
</span><span class="cx">     ScratchBuffer* scratchBuffer = vm-&gt;scratchBufferForSize(
</span><span class="cx">         sizeof(EncodedJSValue) * (
</span><del>-            exit.m_descriptor.m_values.size() + numMaterializations + maxMaterializationNumArguments) +
</del><ins>+            exit.m_descriptor-&gt;m_values.size() + numMaterializations + maxMaterializationNumArguments) +
</ins><span class="cx">         requiredScratchMemorySizeInBytes() +
</span><span class="cx">         codeBlock-&gt;calleeSaveRegisters()-&gt;size() * sizeof(uint64_t));
</span><span class="cx">     EncodedJSValue* scratch = scratchBuffer ? static_cast&lt;EncodedJSValue*&gt;(scratchBuffer-&gt;dataBuffer()) : 0;
</span><del>-    EncodedJSValue* materializationPointers = scratch + exit.m_descriptor.m_values.size();
</del><ins>+    EncodedJSValue* materializationPointers = scratch + exit.m_descriptor-&gt;m_values.size();
</ins><span class="cx">     EncodedJSValue* materializationArguments = materializationPointers + numMaterializations;
</span><span class="cx">     char* registerScratch = bitwise_cast&lt;char*&gt;(materializationArguments + maxMaterializationNumArguments);
</span><span class="cx">     uint64_t* unwindScratch = bitwise_cast&lt;uint64_t*&gt;(registerScratch + requiredScratchMemorySizeInBytes());
</span><span class="cx">     
</span><span class="cx">     HashMap&lt;ExitTimeObjectMaterialization*, EncodedJSValue*&gt; materializationToPointer;
</span><span class="cx">     unsigned materializationCount = 0;
</span><del>-    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
</del><ins>+    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations) {
</ins><span class="cx">         materializationToPointer.add(
</span><span class="cx">             materialization, materializationPointers + materializationCount++);
</span><span class="cx">     }
</span><ins>+
+    auto recoverValue = [&amp;] (const ExitValue&amp; value) {
+        compileRecovery(
+            jit, value,
+#if FTL_USES_B3
+            exit.m_valueReps,
+#else // FTL_USES_B3
+            record, jitCode-&gt;stackmaps,
+#endif // FTL_USES_B3
+            registerScratch, materializationToPointer);
+    };
</ins><span class="cx">     
</span><span class="cx">     // Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave().
</span><span class="cx">     // We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use
</span><span class="lines">@@ -247,10 +279,14 @@
</span><span class="cx">     jit.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
</span><span class="cx">     
</span><span class="cx">     // Do some value profiling.
</span><del>-    if (exit.m_descriptor.m_profileDataFormat != DataFormatNone) {
</del><ins>+    if (exit.m_descriptor-&gt;m_profileDataFormat != DataFormatNone) {
+#if FTL_USES_B3
+        Location::forValueRep(exit.m_valueReps[0]).restoreInto(jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
</ins><span class="cx">         record-&gt;locations[0].restoreInto(jit, jitCode-&gt;stackmaps, registerScratch, GPRInfo::regT0);
</span><ins>+#endif // FTL_USES_B3
</ins><span class="cx">         reboxAccordingToFormat(
</span><del>-            exit.m_descriptor.m_profileDataFormat, jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
</del><ins>+            exit.m_descriptor-&gt;m_profileDataFormat, jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
</ins><span class="cx">         
</span><span class="cx">         if (exit.m_kind == BadCache || exit.m_kind == BadIndexingType) {
</span><span class="cx">             CodeOrigin codeOrigin = exit.m_codeOriginForExitProfile;
</span><span class="lines">@@ -264,8 +300,8 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!!exit.m_descriptor.m_valueProfile)
-            jit.store64(GPRInfo::regT0, exit.m_descriptor.m_valueProfile.getSpecFailBucket(0));
</del><ins>+        if (!!exit.m_descriptor-&gt;m_valueProfile)
+            jit.store64(GPRInfo::regT0, exit.m_descriptor-&gt;m_valueProfile.getSpecFailBucket(0));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Materialize all objects. Don't materialize an object until all
</span><span class="lines">@@ -275,7 +311,7 @@
</span><span class="cx">     // allocation of the former.
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;ExitTimeObjectMaterialization*&gt; toMaterialize;
</span><del>-    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
</del><ins>+    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations)
</ins><span class="cx">         toMaterialize.add(materialization);
</span><span class="cx"> 
</span><span class="cx">     while (!toMaterialize.isEmpty()) {
</span><span class="lines">@@ -307,13 +343,10 @@
</span><span class="cx">             // We only recover the fields that are needed for the allocation.
</span><span class="cx">             for (unsigned propertyIndex = materialization-&gt;properties().size(); propertyIndex--;) {
</span><span class="cx">                 const ExitPropertyValue&amp; property = materialization-&gt;properties()[propertyIndex];
</span><del>-                const ExitValue&amp; value = property.value();
</del><span class="cx">                 if (!property.location().neededForMaterialization())
</span><span class="cx">                     continue;
</span><span class="cx"> 
</span><del>-                compileRecovery(
-                    jit, value, record, jitCode-&gt;stackmaps, registerScratch,
-                    materializationToPointer);
</del><ins>+                recoverValue(property.value());
</ins><span class="cx">                 jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex);
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="lines">@@ -338,12 +371,9 @@
</span><span class="cx">     // Now that all the objects have been allocated, we populate them
</span><span class="cx">     // with the correct values. This time we can recover all the
</span><span class="cx">     // fields, including those that are only needed for the allocation.
</span><del>-    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
</del><ins>+    for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations) {
</ins><span class="cx">         for (unsigned propertyIndex = materialization-&gt;properties().size(); propertyIndex--;) {
</span><del>-            const ExitValue&amp; value = materialization-&gt;properties()[propertyIndex].value();
-            compileRecovery(
-                jit, value, record, jitCode-&gt;stackmaps, registerScratch,
-                materializationToPointer);
</del><ins>+            recoverValue(materialization-&gt;properties()[propertyIndex].value());
</ins><span class="cx">             jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -359,16 +389,14 @@
</span><span class="cx">     // Save all state from wherever the exit data tells us it was, into the appropriate place in
</span><span class="cx">     // the scratch buffer. This also does the reboxing.
</span><span class="cx">     
</span><del>-    for (unsigned index = exit.m_descriptor.m_values.size(); index--;) {
-        compileRecovery(
-            jit, exit.m_descriptor.m_values[index], record, jitCode-&gt;stackmaps, registerScratch,
-            materializationToPointer);
</del><ins>+    for (unsigned index = exit.m_descriptor-&gt;m_values.size(); index--;) {
+        recoverValue(exit.m_descriptor-&gt;m_values[index]);
</ins><span class="cx">         jit.store64(GPRInfo::regT0, scratch + index);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Henceforth we make it look like the exiting function was called through a register
</span><span class="cx">     // preservation wrapper. This implies that FP must be nudged down by a certain amount. Then
</span><del>-    // we restore the various things according to either exit.m_descriptor.m_values or by copying from the
</del><ins>+    // we restore the various things according to either exit.m_descriptor-&gt;m_values or by copying from the
</ins><span class="cx">     // old frame, and finally we save the various callee-save registers into where the
</span><span class="cx">     // restoration thunk would restore them from.
</span><span class="cx">     
</span><span class="lines">@@ -416,7 +444,7 @@
</span><span class="cx"> 
</span><span class="cx">     // First set up SP so that our data doesn't get clobbered by signals.
</span><span class="cx">     unsigned conservativeStackDelta =
</span><del>-        (exit.m_descriptor.m_values.numberOfLocals() + baselineCodeBlock-&gt;calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
</del><ins>+        (exit.m_descriptor-&gt;m_values.numberOfLocals() + baselineCodeBlock-&gt;calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
</ins><span class="cx">         maxFrameExtentForSlowPathCall;
</span><span class="cx">     conservativeStackDelta = WTF::roundUpToMultipleOf(
</span><span class="cx">         stackAlignmentBytes(), conservativeStackDelta);
</span><span class="lines">@@ -493,8 +521,8 @@
</span><span class="cx"> 
</span><span class="cx">     // Now get state out of the scratch buffer and place it back into the stack. The values are
</span><span class="cx">     // already reboxed so we just move them.
</span><del>-    for (unsigned index = exit.m_descriptor.m_values.size(); index--;) {
-        VirtualRegister reg = exit.m_descriptor.m_values.virtualRegisterForIndex(index);
</del><ins>+    for (unsigned index = exit.m_descriptor-&gt;m_values.size(); index--;) {
+        VirtualRegister reg = exit.m_descriptor-&gt;m_values.virtualRegisterForIndex(index);
</ins><span class="cx"> 
</span><span class="cx">         if (reg.isLocal() &amp;&amp; reg.toLocal() &lt; static_cast&lt;int&gt;(baselineVirtualRegistersForCalleeSaves))
</span><span class="cx">             continue;
</span><span class="lines">@@ -511,11 +539,19 @@
</span><span class="cx">     exit.m_code = FINALIZE_CODE_IF(
</span><span class="cx">         shouldDumpDisassembly() || Options::verboseOSR() || Options::verboseFTLOSRExit(),
</span><span class="cx">         patchBuffer,
</span><ins>+#if FTL_USES_B3
+        (&quot;FTL OSR exit #%u (%s, %s) from %s, with operands = %s&quot;,
+            exitID, toCString(exit.m_codeOrigin).data(),
+            exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
+            toCString(ignoringContext&lt;DumpContext&gt;(exit.m_descriptor-&gt;m_values)).data())
+#else // FTL_USES_B3
</ins><span class="cx">         (&quot;FTL OSR exit #%u (%s, %s) from %s, with operands = %s, and record = %s&quot;,
</span><span class="cx">             exitID, toCString(exit.m_codeOrigin).data(),
</span><span class="cx">             exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
</span><del>-            toCString(ignoringContext&lt;DumpContext&gt;(exit.m_descriptor.m_values)).data(),
-            toCString(*record).data()));
</del><ins>+            toCString(ignoringContext&lt;DumpContext&gt;(exit.m_descriptor-&gt;m_values)).data(),
+            toCString(*record).data())
+#endif // FTL_USES_B3
+        );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; void* compileFTLOSRExit(ExecState* exec, unsigned exitID)
</span><span class="lines">@@ -544,15 +580,15 @@
</span><span class="cx">         dataLog(&quot;    Origin: &quot;, exit.m_codeOrigin, &quot;\n&quot;);
</span><span class="cx">         if (exit.m_codeOriginForExitProfile != exit.m_codeOrigin)
</span><span class="cx">             dataLog(&quot;    Origin for exit profile: &quot;, exit.m_codeOriginForExitProfile, &quot;\n&quot;);
</span><del>-        dataLog(&quot;    Exit stackmap ID: &quot;, exit.m_descriptor.m_stackmapID, &quot;\n&quot;);
</del><ins>+        dataLog(&quot;    Exit stackmap ID: &quot;, exit.m_descriptor-&gt;m_stackmapID, &quot;\n&quot;);
</ins><span class="cx">         dataLog(&quot;    Current call site index: &quot;, exec-&gt;callSiteIndex().bits(), &quot;\n&quot;);
</span><span class="cx">         dataLog(&quot;    Exit is exception handler: &quot;, exit.m_isExceptionHandler,
</span><span class="cx">             &quot; will arrive at exit from genericUnwind(): &quot;, exit.willArriveAtOSRExitFromGenericUnwind(), 
</span><del>-            &quot; will arrive at exit from lazy slow path: &quot;, exit.m_descriptor.m_exceptionType == ExceptionType::LazySlowPath, &quot;\n&quot;);
-        dataLog(&quot;    Exit values: &quot;, exit.m_descriptor.m_values, &quot;\n&quot;);
-        if (!exit.m_descriptor.m_materializations.isEmpty()) {
</del><ins>+            &quot; will arrive at exit from lazy slow path: &quot;, exit.m_descriptor-&gt;m_exceptionType == ExceptionType::LazySlowPath, &quot;\n&quot;);
+        dataLog(&quot;    Exit values: &quot;, exit.m_descriptor-&gt;m_values, &quot;\n&quot;);
+        if (!exit.m_descriptor-&gt;m_materializations.isEmpty()) {
</ins><span class="cx">             dataLog(&quot;    Materializations:\n&quot;);
</span><del>-            for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
</del><ins>+            for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor-&gt;m_materializations)
</ins><span class="cx">                 dataLog(&quot;        &quot;, pointerDump(materialization), &quot;\n&quot;);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitHandlecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.cpp (0 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;FTLOSRExitHandle.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;FTLOSRExit.h&quot;
+#include &quot;FTLThunks.h&quot;
+#include &quot;LinkBuffer.h&quot;
+
+namespace JSC { namespace FTL {
+
+void OSRExitHandle::emitExitThunk(CCallHelpers&amp; jit)
+{
+    label = jit.label();
+    jit.pushToSaveImmediateWithoutTouchingRegisters(CCallHelpers::TrustedImm32(index));
+    CCallHelpers::PatchableJump jump = jit.patchableJump();
+    jit.addLinkTask(
+        [this, jump] (LinkBuffer&amp; linkBuffer) {
+            exit.m_patchableJump = CodeLocationJump(linkBuffer.locationOf(jump));
+
+            linkBuffer.link(
+                jump.m_jump,
+                CodeLocationLabel(linkBuffer.vm().getCTIStub(osrExitGenerationThunkGenerator).code()));
+        });
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitHandleh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.h (0 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitHandle.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FTLOSRExitHandle_h
+#define FTLOSRExitHandle_h
+
+#include &quot;DFGCommon.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;CCallHelpers.h&quot;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+
+namespace JSC { namespace FTL {
+
+struct OSRExit;
+
+// This is an object that stores some interesting data about an OSR exit. It's expected that you will
+// scrape this data from this object by the time compilation finishes.
+struct OSRExitHandle : public ThreadSafeRefCounted&lt;OSRExitHandle&gt; {
+    OSRExitHandle(unsigned index, OSRExit&amp; exit)
+        : index(index)
+        , exit(exit)
+    {
+    }
+
+    unsigned index;
+    OSRExit&amp; exit;
+
+    // This is the label at which the OSR exit jump lives. This will get populated once the OSR exit
+    // emits its jump. This happens immediately when you call OSRExit::appendOSRExit(). It happens at
+    // some time during late path emission if you do OSRExit::appendOSRExitLater().
+    CCallHelpers::Label label;
+
+    // This emits the exit thunk and populates 'label'.
+    void emitExitThunk(CCallHelpers&amp;);
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#endif // FTLOSRExitHandle_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLState.cpp (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLState.cpp        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/JavaScriptCore/ftl/FTLState.cpp        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+using namespace B3;
</ins><span class="cx"> using namespace DFG;
</span><span class="cx"> 
</span><span class="cx"> State::State(Graph&amp; graph)
</span><span class="lines">@@ -68,6 +69,10 @@
</span><span class="cx"> 
</span><span class="cx">     graph.m_plan.finalizer = std::make_unique&lt;JITFinalizer&gt;(graph.m_plan);
</span><span class="cx">     finalizer = static_cast&lt;JITFinalizer*&gt;(graph.m_plan.finalizer.get());
</span><ins>+
+#if FTL_USES_B3
+    proc = std::make_unique&lt;Procedure&gt;();
+#endif // FTL_USES_B3
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> State::~State()
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/WTF/ChangeLog        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-12-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 should support OSR exit
+        https://bugs.webkit.org/show_bug.cgi?id=151710
+
+        Reviewed by Saam Barati.
+
+        Make sure that this has perfect forwarding.
+
+        * wtf/SegmentedVector.h:
+        (WTF::SegmentedVector::append):
+        (WTF::SegmentedVector::alloc):
+
</ins><span class="cx"> 2015-12-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Implement LLInt/Baseline Support for ES6 Generators and enable this feature
</span></span></pre></div>
<a id="trunkSourceWTFwtfSegmentedVectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/SegmentedVector.h (193361 => 193362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/SegmentedVector.h        2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/WTF/wtf/SegmentedVector.h        2015-12-03 20:01:57 UTC (rev 193362)
</span><span class="lines">@@ -141,9 +141,9 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         template&lt;typename... Args&gt;
</span><del>-        T&amp; alloc(Args... args)
</del><ins>+        T&amp; alloc(Args&amp;&amp;... args)
</ins><span class="cx">         {
</span><del>-            append&lt;T&gt;(T(args...));
</del><ins>+            append&lt;T&gt;(T(std::forward&lt;Args&gt;(args)...));
</ins><span class="cx">             return last();
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>