<!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>[194716] trunk/Source/JavaScriptCore</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>FTL B3 getById() should do exceptions
https://bugs.webkit.org/show_bug.cgi?id=152810

Reviewed by Saam Barati.

This adds abstractions for doing exceptions from patchpoints, and uses them to implement
exceptions from GetById. This covers all of the following ways that a GetById might throw an
exceptions:

- Throw without try/catch from the vmCall() in a GetById(Untyped:)
- Throw with try/catch from the vmCall() in a GetById(Untyped:)
- Throw without try/catch from the callOperation() in the patchpoint of a GetById
- Throw with try/catch from the callOperation() in the patchpoint of a GetById
- Throw without try/catch from the Call IC generated in the patchpoint of a GetById
- Throw with try/catch from the Call IC generated in the patchpoint of a GetById

This requires having a default exception target in FTL-generated code, and ensuring that this
target is generated regardless of whether we have branches to the B3 basic block of the
default exception target. This also requires adding some extra arguments to a
PatchpointValue, and then knowing that the arguments are used for OSR exit and not anything
else. This also requires associating the CallSiteIndex of the patchpoint with the register
set used for exit and with the OSR exit label for the unwind exit.

All of the stuff that you have to worry about when wiring a patchpoint to exception handling
is covered by the new PatchpointExceptionHandle object. You create one by calling
preparePatchpointForExceptions(). This sets up the B3 IR representation of the patchpoint
with stackmap arguments for the exceptional exit, and creates a PatchpointExceptionHandle
object that can be used to create zero or more actual OSR exits. It can create both OSR exits
for operation calls and OSR exits for unwind. You call the
PatchpointExceptionHandle::scheduleExitCreationXXX() methods from the generator callback to
actually get OSR exits.

This API makes heavy use of Box&lt;&gt;, late paths, and link tasks. For example, you can use the
PatchpointExceptionHandle to get a Box&lt;JumpList&gt; that you can append exception jumps to. When
you use this API, it automatically registers a link task that will link the JumpList to the
actual OSR exit label.

This API is very flexible about how you get to the label of the OSR exit. You are encouraged
to use the Box&lt;JumpList&gt; approach, but if you really just need the label, you can also get
a RefPtr&lt;ExceptionTarget&gt; and rely on the fact that the ExceptionTarget object will be able
to vend you the OSR exit label at link-time.

This reduces the number of JSC test failures with FTL B3 from 186 to 133. It also adds a
bunch of new tests specifically for all of the ways you might throw from GetById, and B3
passes all of these new tests. Note that I'm not counting the new tests as part of the
previous 186 test failures (FTL B3 failed all of the new tests prior to this change).

After this change, it should be easy to make all of the other patchpoints also handle
exceptions by just following the preparePatchpointForExceptions() idiom.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3StackmapValue.h:
* b3/B3ValueRep.cpp:
(JSC::B3::ValueRep::addUsedRegistersTo):
(JSC::B3::ValueRep::usedRegisters):
(JSC::B3::ValueRep::dump):
* b3/B3ValueRep.h:
(JSC::B3::ValueRep::doubleValue):
(JSC::B3::ValueRep::withOffset):
(JSC::B3::ValueRep::usedRegisters):
* ftl/FTLB3Compile.cpp:
(JSC::FTL::compile):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::unreachable):
(JSC::FTL::Output::speculate):
* ftl/FTLExceptionTarget.cpp: Added.
(JSC::FTL::ExceptionTarget::~ExceptionTarget):
(JSC::FTL::ExceptionTarget::label):
(JSC::FTL::ExceptionTarget::jumps):
(JSC::FTL::ExceptionTarget::ExceptionTarget):
* ftl/FTLExceptionTarget.h: Added.
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::lower):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithAddOrSub):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::DFG::LowerDFGToLLVM::compilePutById):
(JSC::FTL::DFG::LowerDFGToLLVM::compileMakeRope):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstructVarargs):
(JSC::FTL::DFG::LowerDFGToLLVM::compileIn):
(JSC::FTL::DFG::LowerDFGToLLVM::getById):
(JSC::FTL::DFG::LowerDFGToLLVM::emitBinarySnippet):
(JSC::FTL::DFG::LowerDFGToLLVM::emitBinaryBitOpSnippet):
(JSC::FTL::DFG::LowerDFGToLLVM::emitRightShiftSnippet):
(JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
(JSC::FTL::DFG::LowerDFGToLLVM::preparePatchpointForExceptions):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
(JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
* ftl/FTLPatchpointExceptionHandle.cpp: Added.
(JSC::FTL::PatchpointExceptionHandle::create):
(JSC::FTL::PatchpointExceptionHandle::defaultHandle):
(JSC::FTL::PatchpointExceptionHandle::~PatchpointExceptionHandle):
(JSC::FTL::PatchpointExceptionHandle::scheduleExitCreation):
(JSC::FTL::PatchpointExceptionHandle::scheduleExitCreationForUnwind):
(JSC::FTL::PatchpointExceptionHandle::PatchpointExceptionHandle):
(JSC::FTL::PatchpointExceptionHandle::createHandle):
* ftl/FTLPatchpointExceptionHandle.h: Added.
* ftl/FTLState.cpp:
* ftl/FTLState.h:
(JSC::FTL::verboseCompilationEnabled):
* tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js: Added.
* tests/stress/ftl-get-by-id-getter-exception-no-catch.js: Added.
* tests/stress/ftl-get-by-id-getter-exception.js: Added.
* tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js: Added.
* tests/stress/ftl-get-by-id-slow-exception-no-catch.js: Added.
* tests/stress/ftl-get-by-id-slow-exception.js: Added.
* tests/stress/ftl-operation-exception-interesting-live-state.js: Added.
* tests/stress/ftl-operation-exception-no-catch.js: Added.</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="#trunkSourceJavaScriptCoreb3B3StackmapValueh">trunk/Source/JavaScriptCore/b3/B3StackmapValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueRepcpp">trunk/Source/JavaScriptCore/b3/B3ValueRep.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueReph">trunk/Source/JavaScriptCore/b3/B3ValueRep.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Compilecpp">trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputh">trunk/Source/JavaScriptCore/ftl/FTLB3Output.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodecpp">trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStatecpp">trunk/Source/JavaScriptCore/ftl/FTLState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStateh">trunk/Source/JavaScriptCore/ftl/FTLState.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExceptionTargetcpp">trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExceptionTargeth">trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLPatchpointExceptionHandlecpp">trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLPatchpointExceptionHandleh">trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptioninterestinglivestatejs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptionnocatchjs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-no-catch.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptionjs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptioninterestinglivestatejs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptionnocatchjs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-no-catch.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptionjs">trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftloperationexceptioninterestinglivestatejs">trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-interesting-live-state.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressftloperationexceptionnocatchjs">trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-no-catch.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1023,6 +1023,7 @@
</span><span class="cx">         ftl/FTLDWARFRegister.cpp
</span><span class="cx">         ftl/FTLDataSection.cpp
</span><span class="cx">         ftl/FTLExceptionHandlerManager.cpp
</span><ins>+        ftl/FTLExceptionTarget.cpp
</ins><span class="cx">         ftl/FTLExitArgument.cpp
</span><span class="cx">         ftl/FTLExitArgumentForOperand.cpp
</span><span class="cx">         ftl/FTLExitPropertyValue.cpp
</span><span class="lines">@@ -1049,6 +1050,7 @@
</span><span class="cx">         ftl/FTLOSRExitHandle.cpp
</span><span class="cx">         ftl/FTLOperations.cpp
</span><span class="cx">         ftl/FTLOutput.cpp
</span><ins>+        ftl/FTLPatchpointExceptionHandle.cpp
</ins><span class="cx">         ftl/FTLRecoveryOpcode.cpp
</span><span class="cx">         ftl/FTLSaveRestore.cpp
</span><span class="cx">         ftl/FTLSlowPathCall.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,3 +1,118 @@
</span><ins>+2016-01-07  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 getById() should do exceptions
+        https://bugs.webkit.org/show_bug.cgi?id=152810
+
+        Reviewed by Saam Barati.
+
+        This adds abstractions for doing exceptions from patchpoints, and uses them to implement
+        exceptions from GetById. This covers all of the following ways that a GetById might throw an
+        exceptions:
+
+        - Throw without try/catch from the vmCall() in a GetById(Untyped:)
+        - Throw with try/catch from the vmCall() in a GetById(Untyped:)
+        - Throw without try/catch from the callOperation() in the patchpoint of a GetById
+        - Throw with try/catch from the callOperation() in the patchpoint of a GetById
+        - Throw without try/catch from the Call IC generated in the patchpoint of a GetById
+        - Throw with try/catch from the Call IC generated in the patchpoint of a GetById
+
+        This requires having a default exception target in FTL-generated code, and ensuring that this
+        target is generated regardless of whether we have branches to the B3 basic block of the
+        default exception target. This also requires adding some extra arguments to a
+        PatchpointValue, and then knowing that the arguments are used for OSR exit and not anything
+        else. This also requires associating the CallSiteIndex of the patchpoint with the register
+        set used for exit and with the OSR exit label for the unwind exit.
+
+        All of the stuff that you have to worry about when wiring a patchpoint to exception handling
+        is covered by the new PatchpointExceptionHandle object. You create one by calling
+        preparePatchpointForExceptions(). This sets up the B3 IR representation of the patchpoint
+        with stackmap arguments for the exceptional exit, and creates a PatchpointExceptionHandle
+        object that can be used to create zero or more actual OSR exits. It can create both OSR exits
+        for operation calls and OSR exits for unwind. You call the
+        PatchpointExceptionHandle::scheduleExitCreationXXX() methods from the generator callback to
+        actually get OSR exits.
+
+        This API makes heavy use of Box&lt;&gt;, late paths, and link tasks. For example, you can use the
+        PatchpointExceptionHandle to get a Box&lt;JumpList&gt; that you can append exception jumps to. When
+        you use this API, it automatically registers a link task that will link the JumpList to the
+        actual OSR exit label.
+
+        This API is very flexible about how you get to the label of the OSR exit. You are encouraged
+        to use the Box&lt;JumpList&gt; approach, but if you really just need the label, you can also get
+        a RefPtr&lt;ExceptionTarget&gt; and rely on the fact that the ExceptionTarget object will be able
+        to vend you the OSR exit label at link-time.
+
+        This reduces the number of JSC test failures with FTL B3 from 186 to 133. It also adds a
+        bunch of new tests specifically for all of the ways you might throw from GetById, and B3
+        passes all of these new tests. Note that I'm not counting the new tests as part of the
+        previous 186 test failures (FTL B3 failed all of the new tests prior to this change).
+
+        After this change, it should be easy to make all of the other patchpoints also handle
+        exceptions by just following the preparePatchpointForExceptions() idiom.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3StackmapValue.h:
+        * b3/B3ValueRep.cpp:
+        (JSC::B3::ValueRep::addUsedRegistersTo):
+        (JSC::B3::ValueRep::usedRegisters):
+        (JSC::B3::ValueRep::dump):
+        * b3/B3ValueRep.h:
+        (JSC::B3::ValueRep::doubleValue):
+        (JSC::B3::ValueRep::withOffset):
+        (JSC::B3::ValueRep::usedRegisters):
+        * ftl/FTLB3Compile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::unreachable):
+        (JSC::FTL::Output::speculate):
+        * ftl/FTLExceptionTarget.cpp: Added.
+        (JSC::FTL::ExceptionTarget::~ExceptionTarget):
+        (JSC::FTL::ExceptionTarget::label):
+        (JSC::FTL::ExceptionTarget::jumps):
+        (JSC::FTL::ExceptionTarget::ExceptionTarget):
+        * ftl/FTLExceptionTarget.h: Added.
+        * ftl/FTLJITCode.cpp:
+        (JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithAddOrSub):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compilePutById):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileMakeRope):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstructVarargs):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileIn):
+        (JSC::FTL::DFG::LowerDFGToLLVM::getById):
+        (JSC::FTL::DFG::LowerDFGToLLVM::emitBinarySnippet):
+        (JSC::FTL::DFG::LowerDFGToLLVM::emitBinaryBitOpSnippet):
+        (JSC::FTL::DFG::LowerDFGToLLVM::emitRightShiftSnippet):
+        (JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
+        (JSC::FTL::DFG::LowerDFGToLLVM::preparePatchpointForExceptions):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
+        (JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
+        (JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
+        * ftl/FTLPatchpointExceptionHandle.cpp: Added.
+        (JSC::FTL::PatchpointExceptionHandle::create):
+        (JSC::FTL::PatchpointExceptionHandle::defaultHandle):
+        (JSC::FTL::PatchpointExceptionHandle::~PatchpointExceptionHandle):
+        (JSC::FTL::PatchpointExceptionHandle::scheduleExitCreation):
+        (JSC::FTL::PatchpointExceptionHandle::scheduleExitCreationForUnwind):
+        (JSC::FTL::PatchpointExceptionHandle::PatchpointExceptionHandle):
+        (JSC::FTL::PatchpointExceptionHandle::createHandle):
+        * ftl/FTLPatchpointExceptionHandle.h: Added.
+        * ftl/FTLState.cpp:
+        * ftl/FTLState.h:
+        (JSC::FTL::verboseCompilationEnabled):
+        * tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js: Added.
+        * tests/stress/ftl-get-by-id-getter-exception-no-catch.js: Added.
+        * tests/stress/ftl-get-by-id-getter-exception.js: Added.
+        * tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js: Added.
+        * tests/stress/ftl-get-by-id-slow-exception-no-catch.js: Added.
+        * tests/stress/ftl-get-by-id-slow-exception.js: Added.
+        * tests/stress/ftl-operation-exception-interesting-live-state.js: Added.
+        * tests/stress/ftl-operation-exception-no-catch.js: Added.
+
</ins><span class="cx"> 2016-01-07  Konstantin Tokarev  &lt;annulen@yandex.ru&gt;
</span><span class="cx"> 
</span><span class="cx">         [mips] Implemented missing branch patching methods.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -518,6 +518,10 @@
</span><span class="cx">                 0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9D36941AE9CC33000D4DFB /* DFGCleanUpPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */; };
</span><span class="cx">                 0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */; };
</span><ins>+                0F9D4C0C1C3E1C11006CD984 /* FTLExceptionTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D4C0A1C3E1C11006CD984 /* FTLExceptionTarget.cpp */; };
+                0F9D4C0D1C3E1C11006CD984 /* FTLExceptionTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D4C0B1C3E1C11006CD984 /* FTLExceptionTarget.h */; };
+                0F9D4C101C3E2C74006CD984 /* FTLPatchpointExceptionHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D4C0E1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.cpp */; };
+                0F9D4C111C3E2C74006CD984 /* FTLPatchpointExceptionHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D4C0F1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.h */; };
</ins><span class="cx">                 0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */; };
</span><span class="cx">                 0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */; };
</span><span class="cx">                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */; };
</span><span class="lines">@@ -2650,6 +2654,10 @@
</span><span class="cx">                 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLStackMaps.h; path = ftl/FTLStackMaps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCleanUpPhase.cpp; path = dfg/DFGCleanUpPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCleanUpPhase.h; path = dfg/DFGCleanUpPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F9D4C0A1C3E1C11006CD984 /* FTLExceptionTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLExceptionTarget.cpp; path = ftl/FTLExceptionTarget.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9D4C0B1C3E1C11006CD984 /* FTLExceptionTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLExceptionTarget.h; path = ftl/FTLExceptionTarget.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9D4C0E1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLPatchpointExceptionHandle.cpp; path = ftl/FTLPatchpointExceptionHandle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9D4C0F1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLPatchpointExceptionHandle.h; path = ftl/FTLPatchpointExceptionHandle.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierInsertionPhase.cpp; path = dfg/DFGStoreBarrierInsertionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierInsertionPhase.h; path = dfg/DFGStoreBarrierInsertionPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4544,6 +4552,8 @@
</span><span class="cx">                                 0F9C5E5D18E35F5E00D431C3 /* FTLDWARFRegister.h */,
</span><span class="cx">                                 79DF66AE1BF26A570001CF11 /* FTLExceptionHandlerManager.cpp */,
</span><span class="cx">                                 79DF66AF1BF26A570001CF11 /* FTLExceptionHandlerManager.h */,
</span><ins>+                                0F9D4C0A1C3E1C11006CD984 /* FTLExceptionTarget.cpp */,
+                                0F9D4C0B1C3E1C11006CD984 /* FTLExceptionTarget.h */,
</ins><span class="cx">                                 0F235BBD17178E1C00690C7F /* FTLExitArgument.cpp */,
</span><span class="cx">                                 0F235BBE17178E1C00690C7F /* FTLExitArgument.h */,
</span><span class="cx">                                 0F235BBF17178E1C00690C7F /* FTLExitArgumentForOperand.cpp */,
</span><span class="lines">@@ -4602,6 +4612,8 @@
</span><span class="cx">                                 0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */,
</span><span class="cx">                                 0FEA0A291709629600BB722C /* FTLOutput.cpp */,
</span><span class="cx">                                 0FEA0A06170513DB00BB722C /* FTLOutput.h */,
</span><ins>+                                0F9D4C0E1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.cpp */,
+                                0F9D4C0F1C3E2C74006CD984 /* FTLPatchpointExceptionHandle.h */,
</ins><span class="cx">                                 0F485325187DFDEC0083B687 /* FTLRecoveryOpcode.cpp */,
</span><span class="cx">                                 0F485326187DFDEC0083B687 /* FTLRecoveryOpcode.h */,
</span><span class="cx">                                 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */,
</span><span class="lines">@@ -7127,6 +7139,7 @@
</span><span class="cx">                                 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
</span><span class="cx">                                 0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */,
</span><span class="cx">                                 0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */,
</span><ins>+                                0F9D4C111C3E2C74006CD984 /* FTLPatchpointExceptionHandle.h in Headers */,
</ins><span class="cx">                                 0F38B01A17CFE75500B144D3 /* DFGCompilationMode.h in Headers */,
</span><span class="cx">                                 0F3B3A1B153E68F4003ED0FF /* DFGConstantFoldingPhase.h in Headers */,
</span><span class="cx">                                 0FED67BA1B26256D0066CE15 /* DFGConstantHoistingPhase.h in Headers */,
</span><span class="lines">@@ -7827,6 +7840,7 @@
</span><span class="cx">                                 E33637A61B63220200EE0840 /* ReflectObject.h in Headers */,
</span><span class="cx">                                 996B73231BDA08EF00331B84 /* ReflectObject.lut.h in Headers */,
</span><span class="cx">                                 0FA7A8EC18B413C80052371D /* Reg.h in Headers */,
</span><ins>+                                0F9D4C0D1C3E1C11006CD984 /* FTLExceptionTarget.h in Headers */,
</ins><span class="cx">                                 BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */,
</span><span class="cx">                                 A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */,
</span><span class="cx">                                 BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */,
</span><span class="lines">@@ -9072,6 +9086,7 @@
</span><span class="cx">                                 1428083A107EC0750013E7B2 /* JSStack.cpp in Sources */,
</span><span class="cx">                                 147F39D5107EC37600427A48 /* JSString.cpp in Sources */,
</span><span class="cx">                                 70EC0EC21AA0D7DA00B6AAFA /* JSStringIterator.cpp in Sources */,
</span><ins>+                                0F9D4C101C3E2C74006CD984 /* FTLPatchpointExceptionHandle.cpp in Sources */,
</ins><span class="cx">                                 2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */,
</span><span class="cx">                                 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */,
</span><span class="cx">                                 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */,
</span><span class="lines">@@ -9176,6 +9191,7 @@
</span><span class="cx">                                 0F190CAC189D82F6000AE5F0 /* ProfilerJettisonReason.cpp in Sources */,
</span><span class="cx">                                 0FF729B3166AD35C000F5BA3 /* ProfilerOrigin.cpp in Sources */,
</span><span class="cx">                                 0FF729B4166AD35C000F5BA3 /* ProfilerOriginStack.cpp in Sources */,
</span><ins>+                                0F9D4C0C1C3E1C11006CD984 /* FTLExceptionTarget.cpp in Sources */,
</ins><span class="cx">                                 0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
</span><span class="cx">                                 0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
</span><span class="cx">                                 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3StackmapValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3StackmapValue.h (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3StackmapValue.h        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/b3/B3StackmapValue.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -77,12 +77,19 @@
</span><span class="cx">             append(value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Helper for appending a bunch of values with some ValueRep.
+    template&lt;typename VectorType&gt;
+    void appendVectorWithRep(const VectorType&amp; vector, const ValueRep&amp; rep)
+    {
+        for (Value* value : vector)
+            append(value, rep);
+    }
+
</ins><span class="cx">     // Helper for appending cold any's. This often used by clients to implement OSR.
</span><span class="cx">     template&lt;typename VectorType&gt;
</span><span class="cx">     void appendColdAnys(const VectorType&amp; vector)
</span><span class="cx">     {
</span><del>-        for (Value* value : vector)
-            append(ConstrainedValue(value, ValueRep::ColdAny));
</del><ins>+        appendVectorWithRep(vector, ValueRep::ColdAny);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // This is a helper for something you might do a lot of: append a value that should be constrained
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueRepcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueRep.cpp (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueRep.cpp        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/b3/B3ValueRep.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,6 +33,34 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><ins>+void ValueRep::addUsedRegistersTo(RegisterSet&amp; set) const
+{
+    switch (m_kind) {
+    case WarmAny:
+    case ColdAny:
+    case LateColdAny:
+    case SomeRegister:
+    case Constant:
+        return;
+    case Register:
+        set.set(reg());
+        return;
+    case Stack:
+    case StackArgument:
+        set.set(MacroAssembler::stackPointerRegister);
+        set.set(GPRInfo::callFrameRegister);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+RegisterSet ValueRep::usedRegisters() const
+{
+    RegisterSet result;
+    addUsedRegistersTo(result);
+    return result;
+}
+
</ins><span class="cx"> void ValueRep::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(m_kind);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueReph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueRep.h (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueRep.h        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/b3/B3ValueRep.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;Reg.h&quot;
</span><ins>+#include &quot;RegisterSet.h&quot;
</ins><span class="cx"> #include &quot;ValueRecovery.h&quot;
</span><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -207,7 +208,7 @@
</span><span class="cx">         return bitwise_cast&lt;double&gt;(value());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ValueRep withOffset(intptr_t offset)
</del><ins>+    ValueRep withOffset(intptr_t offset) const
</ins><span class="cx">     {
</span><span class="cx">         switch (kind()) {
</span><span class="cx">         case Stack:
</span><span class="lines">@@ -219,6 +220,20 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void addUsedRegistersTo(RegisterSet&amp;) const;
+    
+    RegisterSet usedRegisters() const;
+
+    // Get the used registers for a vector of ValueReps.
+    template&lt;typename VectorType&gt;
+    static RegisterSet usedRegisters(const VectorType&amp; vector)
+    {
+        RegisterSet result;
+        for (const ValueRep&amp; value : vector)
+            value.addUsedRegistersTo(result);
+        return result;
+    }
+
</ins><span class="cx">     JS_EXPORT_PRIVATE void dump(PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx">     // This has a simple contract: it emits code to restore the value into the given register. This
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Compilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -112,6 +112,18 @@
</span><span class="cx">     CCallHelpers jit(&amp;vm, codeBlock);
</span><span class="cx">     B3::generate(*state.proc, jit);
</span><span class="cx"> 
</span><ins>+    // Emit the exception handler.
+    *state.exceptionHandler = jit.label();
+    jit.copyCalleeSavesToVMCalleeSavesBuffer();
+    jit.move(MacroAssembler::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0);
+    jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+    CCallHelpers::Call call = jit.call();
+    jit.jumpToExceptionHandler();
+    jit.addLinkTask(
+        [=] (LinkBuffer&amp; linkBuffer) {
+            linkBuffer.link(call, FunctionPtr(lookupExceptionHandler));
+        });
+
</ins><span class="cx">     state.finalizer-&gt;b3CodeLinkBuffer = std::make_unique&lt;LinkBuffer&gt;(
</span><span class="cx">         vm, jit, codeBlock, JITCompilationCanFail);
</span><span class="cx">     if (state.finalizer-&gt;b3CodeLinkBuffer-&gt;didFailToAllocate()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -410,21 +410,6 @@
</span><span class="cx"> 
</span><span class="cx">     void unreachable() { m_block-&gt;appendNew&lt;B3::ControlValue&gt;(m_proc, B3::Oops, origin()); }
</span><span class="cx"> 
</span><del>-    template&lt;typename Functor&gt;
-    void speculate(LValue value, const StackmapArgumentList&amp; arguments, const Functor&amp; functor)
-    {
-        B3::CheckValue* check = speculate(value, arguments);
-        check-&gt;setGenerator(functor);
-    }
-
-    B3::CheckValue* speculate(LValue value, const StackmapArgumentList&amp; arguments)
-    {
-        B3::CheckValue* check = speculate(value);
-        for (LValue value : arguments)
-            check-&gt;append(B3::ConstrainedValue(value));
-        return check;
-    }
-
</del><span class="cx">     B3::CheckValue* speculate(LValue value)
</span><span class="cx">     {
</span><span class="cx">         return m_block-&gt;appendNew&lt;B3::CheckValue&gt;(m_proc, B3::Check, origin(), value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExceptionTargetcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.cpp (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;FTLExceptionTarget.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;FTLState.h&quot;
+
+namespace JSC { namespace FTL {
+
+ExceptionTarget::~ExceptionTarget()
+{
+}
+
+CodeLocationLabel ExceptionTarget::label(LinkBuffer&amp; linkBuffer)
+{
+    if (m_isDefaultHandler)
+        return linkBuffer.locationOf(*m_defaultHandler);
+    return linkBuffer.locationOf(m_handle-&gt;label);
+}
+
+Box&lt;CCallHelpers::JumpList&gt; ExceptionTarget::jumps(CCallHelpers&amp; jit)
+{
+    Box&lt;CCallHelpers::JumpList&gt; result = Box&lt;CCallHelpers::JumpList&gt;::create();
+    if (m_isDefaultHandler) {
+        Box&lt;CCallHelpers::Label&gt; defaultHandler = m_defaultHandler;
+        jit.addLinkTask(
+            [=] (LinkBuffer&amp; linkBuffer) {
+                linkBuffer.link(*result, linkBuffer.locationOf(*defaultHandler));
+            });
+    } else {
+        RefPtr&lt;OSRExitHandle&gt; handle = m_handle;
+        jit.addLinkTask(
+            [=] (LinkBuffer&amp; linkBuffer) {
+                linkBuffer.link(*result, linkBuffer.locationOf(handle-&gt;label));
+            });
+    }
+    return result;
+}
+
+ExceptionTarget::ExceptionTarget(
+    bool isDefaultHandler, Box&lt;CCallHelpers::Label&gt; defaultHandler, RefPtr&lt;OSRExitHandle&gt; handle)
+    : m_isDefaultHandler(isDefaultHandler)
+    , m_defaultHandler(defaultHandler)
+    , m_handle(handle)
+{
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExceptionTargeth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.h (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLExceptionTarget.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+/*
+ * Copyright (C) 2016 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 FTLExceptionTarget_h
+#define FTLExceptionTarget_h
+
+#include &quot;DFGCommon.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;CCallHelpers.h&quot;
+#include &quot;FTLOSRExitHandle.h&quot;
+#include &lt;wtf/Box.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+
+namespace JSC { namespace FTL {
+
+class State;
+
+class ExceptionTarget : public ThreadSafeRefCounted&lt;ExceptionTarget&gt; {
+public:
+    ~ExceptionTarget();
+
+    // It's OK to call this during linking, but not any sooner.
+    CodeLocationLabel label(LinkBuffer&amp;);
+
+    // Or, you can get a JumpList at any time. Anything you add to this JumpList will be linked to
+    // the target's label.
+    Box&lt;CCallHelpers::JumpList&gt; jumps(CCallHelpers&amp;);
+    
+private:
+    friend class PatchpointExceptionHandle;
+
+    ExceptionTarget(bool isDefaultHandler, Box&lt;CCallHelpers::Label&gt;, RefPtr&lt;OSRExitHandle&gt;);
+    
+    bool m_isDefaultHandler;
+    Box&lt;CCallHelpers::Label&gt; m_defaultHandler;
+    RefPtr&lt;OSRExitHandle&gt; m_handle;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#endif // FTLExceptionTarget_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -168,7 +168,13 @@
</span><span class="cx"> RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex callSiteIndex)
</span><span class="cx"> {
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    UNUSED_PARAM(callSiteIndex);
</del><ins>+    for (OSRExit&amp; exit : osrExit) {
+        if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
+            RELEASE_ASSERT(exit.m_isExceptionHandler);
+            RELEASE_ASSERT(exit.m_isUnwindHandler);
+            return ValueRep::usedRegisters(exit.m_valueReps);
+        }
+    }
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">     for (OSRExit&amp; exit : osrExit) {
</span><span class="cx">         if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include &quot;FTLAbstractHeapRepository.h&quot;
</span><span class="cx"> #include &quot;FTLAvailableRecovery.h&quot;
</span><span class="cx"> #include &quot;FTLB3Output.h&quot;
</span><ins>+#include &quot;FTLExceptionTarget.h&quot;
</ins><span class="cx"> #include &quot;FTLForOSREntryJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLFormattedValue.h&quot;
</span><span class="cx"> #include &quot;FTLInlineCacheSize.h&quot;
</span><span class="lines">@@ -49,6 +50,7 @@
</span><span class="cx"> #include &quot;FTLLoweredNodeValue.h&quot;
</span><span class="cx"> #include &quot;FTLOperations.h&quot;
</span><span class="cx"> #include &quot;FTLOutput.h&quot;
</span><ins>+#include &quot;FTLPatchpointExceptionHandle.h&quot;
</ins><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;FTLWeightedTarget.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><span class="lines">@@ -138,6 +140,8 @@
</span><span class="cx">     
</span><span class="cx">     void lower()
</span><span class="cx">     {
</span><ins>+        State* state = &amp;m_ftlState;
+        
</ins><span class="cx">         CString name;
</span><span class="cx">         if (verboseCompilationEnabled()) {
</span><span class="cx">             name = toCString(
</span><span class="lines">@@ -149,16 +153,16 @@
</span><span class="cx">         m_graph.ensureDominators();
</span><span class="cx"> 
</span><span class="cx"> #if !FTL_USES_B3
</span><del>-        m_ftlState.module =
-            moduleCreateWithNameInContext(name.data(), m_ftlState.context);
</del><ins>+        state-&gt;module =
+            moduleCreateWithNameInContext(name.data(), state-&gt;context);
</ins><span class="cx">         
</span><del>-        m_ftlState.function = addFunction(
-            m_ftlState.module, name.data(), functionType(m_out.int64));
-        setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
</del><ins>+        state-&gt;function = addFunction(
+            state-&gt;module, name.data(), functionType(m_out.int64));
+        setFunctionCallingConv(state-&gt;function, LLVMCCallConv);
</ins><span class="cx">         if (isX86() &amp;&amp; Options::llvmDisallowAVX()) {
</span><span class="cx">             // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x
</span><span class="cx">             // slower. It should be disabled.
</span><del>-            addTargetDependentFunctionAttr(m_ftlState.function, &quot;target-features&quot;, &quot;-avx&quot;);
</del><ins>+            addTargetDependentFunctionAttr(state-&gt;function, &quot;target-features&quot;, &quot;-avx&quot;);
</ins><span class="cx">         }
</span><span class="cx"> #endif // !FTL_USES_B3
</span><span class="cx">         
</span><span class="lines">@@ -168,7 +172,7 @@
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">         m_out.initialize(m_heaps);
</span><span class="cx"> #else
</span><del>-        m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
</del><ins>+        m_out.initialize(state-&gt;module, state-&gt;function, m_heaps);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">         // We use prologue frequency for all of the initialization code.
</span><span class="lines">@@ -201,7 +205,7 @@
</span><span class="cx">         size_t sizeOfCaptured = sizeof(JSValue) * m_graph.m_nextMachineLocal;
</span><span class="cx">         B3::StackSlotValue* capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
</span><span class="cx">         m_captured = m_out.add(capturedBase, m_out.constIntPtr(sizeOfCaptured));
</span><del>-        m_ftlState.capturedValue = capturedBase;
</del><ins>+        state-&gt;capturedValue = capturedBase;
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">         LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
</span><span class="cx">         
</span><span class="lines">@@ -209,9 +213,9 @@
</span><span class="cx">             m_out.ptrToInt(capturedAlloca, m_out.intPtr),
</span><span class="cx">             m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register)));
</span><span class="cx">         
</span><del>-        m_ftlState.capturedStackmapID = m_stackmapIDs++;
</del><ins>+        state-&gt;capturedStackmapID = m_stackmapIDs++;
</ins><span class="cx">         m_out.call(
</span><del>-            m_out.voidType, m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
</del><ins>+            m_out.voidType, m_out.stackmapIntrinsic(), m_out.constInt64(state-&gt;capturedStackmapID),
</ins><span class="cx">             m_out.int32Zero, capturedAlloca);
</span><span class="cx"> #endif // FTL_USE_B3
</span><span class="cx"> 
</span><span class="lines">@@ -286,10 +290,10 @@
</span><span class="cx">         if (hasVarargs) {
</span><span class="cx">             LValue varargsSpillSlots = m_out.alloca(
</span><span class="cx">                 arrayType(m_out.int64, JSCallVarargs::numSpillSlotsNeeded()));
</span><del>-            m_ftlState.varargsSpillSlotsStackmapID = m_stackmapIDs++;
</del><ins>+            state-&gt;varargsSpillSlotsStackmapID = m_stackmapIDs++;
</ins><span class="cx">             m_out.call(
</span><span class="cx">                 m_out.voidType, m_out.stackmapIntrinsic(),
</span><del>-                m_out.constInt64(m_ftlState.varargsSpillSlotsStackmapID),
</del><ins>+                m_out.constInt64(state-&gt;varargsSpillSlotsStackmapID),
</ins><span class="cx">                 m_out.int32Zero, varargsSpillSlots);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -300,10 +304,10 @@
</span><span class="cx"> 
</span><span class="cx">             LValue exceptionHandlingVolatileRegistersSpillSlots = m_out.alloca(
</span><span class="cx">                 arrayType(m_out.int64, maxNumberOfCatchSpills));
</span><del>-            m_ftlState.exceptionHandlingSpillSlotStackmapID = m_stackmapIDs++;
</del><ins>+            state-&gt;exceptionHandlingSpillSlotStackmapID = m_stackmapIDs++;
</ins><span class="cx">             m_out.call(
</span><span class="cx">                 m_out.voidType, m_out.stackmapIntrinsic(),
</span><del>-                m_out.constInt64(m_ftlState.exceptionHandlingSpillSlotStackmapID),
</del><ins>+                m_out.constInt64(state-&gt;exceptionHandlingSpillSlotStackmapID),
</ins><span class="cx">                 m_out.int32Zero, exceptionHandlingVolatileRegistersSpillSlots);
</span><span class="cx">         }
</span><span class="cx"> #endif // !FTL_USES_B3
</span><span class="lines">@@ -337,21 +341,30 @@
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">         // FIXME
</span><span class="cx"> #else
</span><del>-        m_ftlState.handleStackOverflowExceptionStackmapID = m_stackmapIDs++;
</del><ins>+        state-&gt;handleStackOverflowExceptionStackmapID = m_stackmapIDs++;
</ins><span class="cx">         m_out.call(
</span><span class="cx">             m_out.voidType, m_out.stackmapIntrinsic(),
</span><del>-            m_out.constInt64(m_ftlState.handleStackOverflowExceptionStackmapID),
</del><ins>+            m_out.constInt64(state-&gt;handleStackOverflowExceptionStackmapID),
</ins><span class="cx">             m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
</span><span class="cx"> #endif
</span><span class="cx">         m_out.unreachable();
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(m_handleExceptions, checkArguments);
</span><span class="cx"> #if FTL_USES_B3
</span><del>-        // FIXME
</del><ins>+        PatchpointValue* patchpoint = m_out.patchpoint(Void);
+        Box&lt;CCallHelpers::Label&gt; exceptionHandler = state-&gt;exceptionHandler;
+        patchpoint-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp;) {
+                CCallHelpers::Jump jump = jit.jump();
+                jit.addLinkTask(
+                    [=] (LinkBuffer&amp; linkBuffer) {
+                        linkBuffer.link(jump, linkBuffer.locationOf(*exceptionHandler));
+                    });
+            });
</ins><span class="cx"> #else
</span><del>-        m_ftlState.handleExceptionStackmapID = m_stackmapIDs++;
</del><ins>+        state-&gt;handleExceptionStackmapID = m_stackmapIDs++;
</ins><span class="cx">         m_out.call(
</span><del>-            m_out.voidType, m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID),
</del><ins>+            m_out.voidType, m_out.stackmapIntrinsic(), m_out.constInt64(state-&gt;handleExceptionStackmapID),
</ins><span class="cx">             m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
</span><span class="cx"> #endif
</span><span class="cx">         m_out.unreachable();
</span><span class="lines">@@ -418,11 +431,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if !FTL_USES_B3
</span><span class="cx">         if (Options::dumpLLVMIR())
</span><del>-            dumpModule(m_ftlState.module);
</del><ins>+            dumpModule(state-&gt;module);
</ins><span class="cx">         if (verboseCompilationEnabled())
</span><del>-            m_ftlState.dumpState(&quot;after lowering&quot;);
</del><ins>+            state-&gt;dumpState(&quot;after lowering&quot;);
</ins><span class="cx">         if (validationEnabled())
</span><del>-            verifyModule(m_ftlState.module);
</del><ins>+            verifyModule(state-&gt;module);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1656,7 +1669,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><del>-            B3::CheckValue* result =
</del><ins>+            CheckValue* result =
</ins><span class="cx">                 isSub ? m_out.speculateSub(left, right) : m_out.speculateAdd(left, right);
</span><span class="cx">             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
</span><span class="cx">             setInt32(result);
</span><span class="lines">@@ -1712,7 +1725,7 @@
</span><span class="cx">             LValue left = lowInt52(m_node-&gt;child1());
</span><span class="cx">             LValue right = lowInt52(m_node-&gt;child2());
</span><span class="cx"> #if FTL_USES_B3
</span><del>-            B3::CheckValue* result =
</del><ins>+            CheckValue* result =
</ins><span class="cx">                 isSub ? m_out.speculateSub(left, right) : m_out.speculateAdd(left, right);
</span><span class="cx">             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
</span><span class="cx">             setInt52(result);
</span><span class="lines">@@ -1803,7 +1816,7 @@
</span><span class="cx">                 result = m_out.mul(left, right);
</span><span class="cx">             else {
</span><span class="cx"> #if FTL_USES_B3
</span><del>-                B3::CheckValue* speculation = m_out.speculateMul(left, right);
</del><ins>+                CheckValue* speculation = m_out.speculateMul(left, right);
</ins><span class="cx">                 blessSpeculation(speculation, Overflow, noValue(), nullptr, m_origin);
</span><span class="cx">                 result = speculation;
</span><span class="cx"> #else // FTL_USES_B3
</span><span class="lines">@@ -1837,7 +1850,7 @@
</span><span class="cx">             LValue right = lowInt52(m_node-&gt;child2(), opposite(kind));
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><del>-            B3::CheckValue* result = m_out.speculateMul(left, right);
</del><ins>+            CheckValue* result = m_out.speculateMul(left, right);
</ins><span class="cx">             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
</span><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">             LValue overflowResult = m_out.mulWithOverflow64(left, right);
</span><span class="lines">@@ -2643,8 +2656,8 @@
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=151686
</span><span class="cx"> 
</span><span class="cx">         B3::PatchpointValue* patchpoint = m_out.patchpoint(Void);
</span><del>-        patchpoint-&gt;append(base, ValueRep::SomeRegister);
-        patchpoint-&gt;append(value, ValueRep::SomeRegister);
</del><ins>+        patchpoint-&gt;appendSomeRegister(base);
+        patchpoint-&gt;appendSomeRegister(value);
</ins><span class="cx">         patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
</span><span class="cx"> 
</span><span class="cx">         State* state = &amp;m_ftlState;
</span><span class="lines">@@ -4291,7 +4304,7 @@
</span><span class="cx">         for (unsigned i = 1; i &lt; numKids; ++i) {
</span><span class="cx">             flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags));
</span><span class="cx"> #if FTL_USES_B3
</span><del>-            B3::CheckValue* lengthCheck = m_out.speculateAdd(
</del><ins>+            CheckValue* lengthCheck = m_out.speculateAdd(
</ins><span class="cx">                 length, m_out.load32(kids[i], m_heaps.JSString_length));
</span><span class="cx">             blessSpeculation(lengthCheck, Uncountable, noValue(), nullptr, m_origin);
</span><span class="cx">             length = lengthCheck;
</span><span class="lines">@@ -5268,8 +5281,8 @@
</span><span class="cx">         // Append the forms of the arguments that we will use before any clobbering happens.
</span><span class="cx">         patchpoint-&gt;append(jsCallee, ValueRep::reg(GPRInfo::regT0));
</span><span class="cx">         if (jsArguments)
</span><del>-            patchpoint-&gt;append(jsArguments, ValueRep::SomeRegister);
-        patchpoint-&gt;append(thisArg, ValueRep::SomeRegister);
</del><ins>+            patchpoint-&gt;appendSomeRegister(jsArguments);
+        patchpoint-&gt;appendSomeRegister(thisArg);
</ins><span class="cx"> 
</span><span class="cx">         if (!forwarding) {
</span><span class="cx">             // Now append them again for after clobbering. Note that the compiler may ask us to use a
</span><span class="lines">@@ -6126,7 +6139,7 @@
</span><span class="cx">                 UniquedStringImpl* str = bitwise_cast&lt;UniquedStringImpl*&gt;(string-&gt;tryGetValueImpl());
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">                 B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
</span><del>-                patchpoint-&gt;append(cell, ValueRep::SomeRegister);
</del><ins>+                patchpoint-&gt;appendSomeRegister(cell);
</ins><span class="cx">                 patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
</span><span class="cx"> 
</span><span class="cx">                 State* state = &amp;m_ftlState;
</span><span class="lines">@@ -7205,21 +7218,38 @@
</span><span class="cx">         UniquedStringImpl* uid = m_graph.identifiers()[node-&gt;identifierNumber()];
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><del>-        // FIXME: Make this do exceptions.
-        // https://bugs.webkit.org/show_bug.cgi?id=151686
</del><ins>+        B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint-&gt;appendSomeRegister(base);
+
+        // FIXME: If this is a GetByIdFlush, we might get some performance boost if we claim that it
+        // clobbers volatile registers late. It's not necessary for correctness, though, since the
+        // IC code is super smart about saving registers.
+        // https://bugs.webkit.org/show_bug.cgi?id=152848
</ins><span class="cx">         
</span><del>-        B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
-        patchpoint-&gt;append(base, ValueRep::SomeRegister);
</del><span class="cx">         patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
</span><span class="cx"> 
</span><ins>+        RefPtr&lt;PatchpointExceptionHandle&gt; exceptionHandle =
+            preparePatchpointForExceptions(patchpoint);
+
</ins><span class="cx">         State* state = &amp;m_ftlState;
</span><span class="cx">         patchpoint-&gt;setGenerator(
</span><span class="cx">             [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
</span><span class="cx">                 AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="cx"> 
</span><ins>+                CallSiteIndex callSiteIndex =
+                    state-&gt;jitCode-&gt;common.addUniqueCallSiteIndex(node-&gt;origin.semantic);
+
+                // This is the direct exit target for operation calls.
+                Box&lt;CCallHelpers::JumpList&gt; exceptions =
+                    exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
+
+                // This is the exit for call IC's created by the getById for getters. We don't have
+                // to do anything weird other than call this, since it will associate the exit with
+                // the callsite index.
+                exceptionHandle-&gt;scheduleExitCreationForUnwind(params, callSiteIndex);
+
</ins><span class="cx">                 auto generator = Box&lt;JITGetByIdGenerator&gt;::create(
</span><del>-                    jit.codeBlock(), node-&gt;origin.semantic,
-                    state-&gt;jitCode-&gt;common.addUniqueCallSiteIndex(node-&gt;origin.semantic),
</del><ins>+                    jit.codeBlock(), node-&gt;origin.semantic, callSiteIndex,
</ins><span class="cx">                     params.unavailableRegisters(), JSValueRegs(params[1].gpr()),
</span><span class="cx">                     JSValueRegs(params[0].gpr()));
</span><span class="cx"> 
</span><span class="lines">@@ -7229,15 +7259,12 @@
</span><span class="cx">                 params.addLatePath(
</span><span class="cx">                     [=] (CCallHelpers&amp; jit) {
</span><span class="cx">                         AllowMacroScratchRegisterUsage allowScratch(jit);
</span><del>-                        
-                        // FIXME: Make this do something.
-                        CCallHelpers::JumpList exceptions;
</del><span class="cx"> 
</span><span class="cx">                         generator-&gt;slowPathJump().link(&amp;jit);
</span><span class="cx">                         CCallHelpers::Label slowPathBegin = jit.label();
</span><span class="cx">                         CCallHelpers::Call slowPathCall = callOperation(
</span><span class="cx">                             *state, params.unavailableRegisters(), jit, node-&gt;origin.semantic,
</span><del>-                            &amp;exceptions, operationGetByIdOptimize, params[0].gpr(),
</del><ins>+                            exceptions.get(), operationGetByIdOptimize, params[0].gpr(),
</ins><span class="cx">                             CCallHelpers::TrustedImmPtr(generator-&gt;stubInfo()), params[1].gpr(),
</span><span class="cx">                             CCallHelpers::TrustedImmPtr(uid)).call();
</span><span class="cx">                         jit.jump().linkTo(done, &amp;jit);
</span><span class="lines">@@ -7524,8 +7551,8 @@
</span><span class="cx">         SnippetOperand rightOperand(m_state.forNode(node-&gt;child2()).resultType());
</span><span class="cx">             
</span><span class="cx">         PatchpointValue* patchpoint = m_out.patchpoint(Int64);
</span><del>-        patchpoint-&gt;append(left, ValueRep::SomeRegister);
-        patchpoint-&gt;append(right, ValueRep::SomeRegister);
</del><ins>+        patchpoint-&gt;appendSomeRegister(left);
+        patchpoint-&gt;appendSomeRegister(right);
</ins><span class="cx">         patchpoint-&gt;append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
</span><span class="cx">         patchpoint-&gt;append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
</span><span class="cx">         patchpoint-&gt;numGPScratchRegisters = 1;
</span><span class="lines">@@ -7582,8 +7609,8 @@
</span><span class="cx">         SnippetOperand rightOperand(m_state.forNode(node-&gt;child2()).resultType());
</span><span class="cx">             
</span><span class="cx">         PatchpointValue* patchpoint = m_out.patchpoint(Int64);
</span><del>-        patchpoint-&gt;append(left, ValueRep::SomeRegister);
-        patchpoint-&gt;append(right, ValueRep::SomeRegister);
</del><ins>+        patchpoint-&gt;appendSomeRegister(left);
+        patchpoint-&gt;appendSomeRegister(right);
</ins><span class="cx">         patchpoint-&gt;append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
</span><span class="cx">         patchpoint-&gt;append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
</span><span class="cx">         patchpoint-&gt;numGPScratchRegisters = 1;
</span><span class="lines">@@ -7634,8 +7661,8 @@
</span><span class="cx">         SnippetOperand rightOperand(m_state.forNode(node-&gt;child2()).resultType());
</span><span class="cx">             
</span><span class="cx">         PatchpointValue* patchpoint = m_out.patchpoint(Int64);
</span><del>-        patchpoint-&gt;append(left, ValueRep::SomeRegister);
-        patchpoint-&gt;append(right, ValueRep::SomeRegister);
</del><ins>+        patchpoint-&gt;appendSomeRegister(left);
+        patchpoint-&gt;appendSomeRegister(right);
</ins><span class="cx">         patchpoint-&gt;append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
</span><span class="cx">         patchpoint-&gt;append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
</span><span class="cx">         patchpoint-&gt;numGPScratchRegisters = 1;
</span><span class="lines">@@ -10132,7 +10159,43 @@
</span><span class="cx">         m_out.appendTo(continuation);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#if !FTL_USES_B3
</del><ins>+#if FTL_USES_B3
+    RefPtr&lt;PatchpointExceptionHandle&gt; preparePatchpointForExceptions(PatchpointValue* value)
+    {
+        CodeOrigin opCatchOrigin;
+        HandlerInfo* exceptionHandler;
+        bool willCatchException = m_graph.willCatchExceptionInMachineFrame(m_origin.forExit, opCatchOrigin, exceptionHandler);
+        if (!willCatchException)
+            return PatchpointExceptionHandle::defaultHandle(m_ftlState);
+
+        if (verboseCompilationEnabled()) {
+            dataLog(&quot;    Patchpoint exception OSR exit #&quot;, m_ftlState.jitCode-&gt;osrExitDescriptors.size(), &quot; with availability: &quot;, availabilityMap(), &quot;\n&quot;);
+            if (!m_availableRecoveries.isEmpty())
+                dataLog(&quot;        Available recoveries: &quot;, listDump(m_availableRecoveries), &quot;\n&quot;);
+        }
+
+        bool exitOK = true;
+        NodeOrigin origin = m_origin.withForExitAndExitOK(opCatchOrigin, exitOK);
+
+        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(noValue(), nullptr);
+
+        // Compute the offset into the StackmapGenerationParams where we will find the exit arguments
+        // we are about to append. We need to account for both the children we've already added, and
+        // for the possibility of a result value if the patchpoint is not void.
+        unsigned offset = value-&gt;numChildren();
+        if (value-&gt;type() != Void)
+            offset++;
+
+        // Use LateColdAny to ensure that the stackmap arguments interfere with the patchpoint's
+        // result and with any late-clobbered registers.
+        value-&gt;appendVectorWithRep(
+            buildExitArguments(exitDescriptor, opCatchOrigin, noValue()),
+            ValueRep::LateColdAny);
+
+        return PatchpointExceptionHandle::create(
+            m_ftlState, exitDescriptor, origin, offset, *exceptionHandler);
+    }
+#else // FTL_USES_B3
</ins><span class="cx">     void appendOSRExitArgumentsForPatchpointIfWillCatchException(StackmapArgumentList&amp; arguments, ExceptionType exceptionType, unsigned offsetOfExitArguments)
</span><span class="cx">     {
</span><span class="cx">         CodeOrigin opCatchOrigin;
</span><span class="lines">@@ -10153,7 +10216,7 @@
</span><span class="cx">             buildExitArguments(exitDescriptor, exitDescriptorImpl.m_codeOrigin, noValue(), offsetOfExitArguments);
</span><span class="cx">         arguments.appendVector(freshList);
</span><span class="cx">     }
</span><del>-#endif // !FTL_USES_B3
</del><ins>+#endif // FTL_USES_B3
</ins><span class="cx"> 
</span><span class="cx">     LBasicBlock lowBlock(DFG::BasicBlock* block)
</span><span class="cx">     {
</span><span class="lines">@@ -10245,7 +10308,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    void blessSpeculation(B3::CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
</del><ins>+    void blessSpeculation(CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
</ins><span class="cx">     {
</span><span class="cx">         OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(lowValue, highValue);
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLPatchpointExceptionHandlecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,123 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;FTLPatchpointExceptionHandle.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;B3StackmapGenerationParams.h&quot;
+#include &quot;FTLExceptionTarget.h&quot;
+#include &quot;FTLOSRExit.h&quot;
+#include &quot;FTLOSRExitHandle.h&quot;
+#include &quot;FTLState.h&quot;
+
+namespace JSC { namespace FTL {
+
+using namespace DFG;
+
+RefPtr&lt;PatchpointExceptionHandle&gt; PatchpointExceptionHandle::create(
+    State&amp; state, OSRExitDescriptor* descriptor, NodeOrigin origin, unsigned offset,
+    const HandlerInfo&amp; handler)
+{
+    return adoptRef(new PatchpointExceptionHandle(state, descriptor, origin, offset, handler));
+}
+
+RefPtr&lt;PatchpointExceptionHandle&gt; PatchpointExceptionHandle::defaultHandle(State&amp; state)
+{
+    if (!state.defaultExceptionHandle) {
+        state.defaultExceptionHandle = adoptRef(
+            new PatchpointExceptionHandle(state, nullptr, NodeOrigin(), 0, HandlerInfo()));
+    }
+    return state.defaultExceptionHandle;
+}
+
+PatchpointExceptionHandle::~PatchpointExceptionHandle()
+{
+}
+
+RefPtr&lt;ExceptionTarget&gt; PatchpointExceptionHandle::scheduleExitCreation(
+    const B3::StackmapGenerationParams&amp; params)
+{
+    if (!m_descriptor) {
+        // NOTE: This object could be a singleton, however usually we toss the ExceptionHandler
+        // object shortly after creation.
+        bool isDefaultHandler = true;
+        return adoptRef(
+            new ExceptionTarget(isDefaultHandler, m_state.exceptionHandler, nullptr));
+    }
+    bool isDefaultHandler = false;
+    return adoptRef(new ExceptionTarget(isDefaultHandler, { }, createHandle(params)));
+}
+
+void PatchpointExceptionHandle::scheduleExitCreationForUnwind(
+    const B3::StackmapGenerationParams&amp; params, CallSiteIndex callSiteIndex)
+{
+    if (!m_descriptor)
+        return;
+    
+    RefPtr&lt;OSRExitHandle&gt; handle = createHandle(params);
+
+    handle-&gt;exit.m_isUnwindHandler = true;
+    handle-&gt;exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
+
+    HandlerInfo handler = m_handler;
+    params.addLatePath(
+        [handle, handler, callSiteIndex] (CCallHelpers&amp; jit) {
+            CodeBlock* codeBlock = jit.codeBlock();
+            jit.addLinkTask(
+                [=] (LinkBuffer&amp; linkBuffer) {
+                    HandlerInfo newHandler = handler;
+                    newHandler.start = callSiteIndex.bits();
+                    newHandler.end = callSiteIndex.bits() + 1;
+                    newHandler.nativeCode = linkBuffer.locationOf(handle-&gt;label);
+                    codeBlock-&gt;appendExceptionHandler(newHandler);
+                });
+        });
+}
+
+PatchpointExceptionHandle::PatchpointExceptionHandle(
+    State&amp; state, OSRExitDescriptor* descriptor, NodeOrigin origin, unsigned offset,
+    const HandlerInfo&amp; handler)
+    : m_state(state)
+    , m_descriptor(descriptor)
+    , m_origin(origin)
+    , m_offset(offset)
+    , m_handler(handler)
+{
+}
+
+RefPtr&lt;OSRExitHandle&gt; PatchpointExceptionHandle::createHandle(
+    const B3::StackmapGenerationParams&amp; params)
+{
+    bool isExceptionHandler = true;
+    return m_descriptor-&gt;emitOSRExitLater(
+        m_state, Uncountable, m_origin, params, m_offset, isExceptionHandler);
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLPatchpointExceptionHandleh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,105 @@
</span><ins>+/*
+ * Copyright (C) 2016 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 FTLPatchpointExceptionHandle_h
+#define FTLPatchpointExceptionHandle_h
+
+#include &quot;DFGCommon.h&quot;
+
+#if ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#include &quot;DFGNodeOrigin.h&quot;
+#include &quot;HandlerInfo.h&quot;
+#include &lt;wtf/Ref.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+
+namespace JSC {
+
+namespace B3 {
+class StackmapGenerationParams;
+} // namespace B3
+
+namespace FTL {
+
+class ExceptionTarget;
+class State;
+struct OSRExitDescriptor;
+struct OSRExitHandle;
+
+class PatchpointExceptionHandle : public ThreadSafeRefCounted&lt;PatchpointExceptionHandle&gt; {
+public:
+    static RefPtr&lt;PatchpointExceptionHandle&gt; create(
+        State&amp;, OSRExitDescriptor*, DFG::NodeOrigin, unsigned offset, const HandlerInfo&amp;);
+
+    static RefPtr&lt;PatchpointExceptionHandle&gt; defaultHandle(State&amp;);
+    
+    ~PatchpointExceptionHandle();
+
+    // Note that you can use this handle to schedule any number of exits. This capability is here for
+    // two reasons:
+    // 
+    // - B3 code duplication. B3 could take a patchpoint and turn it into multiple patchpoints if it
+    //   duplicates code. Duplicating code is legal since you can do it without changing the behavior
+    //   of the program. One example is tail duplication. Another is jump threading. Yet another is
+    //   path specialization. You will have one PatchpointExceptionHandle per patchpoint you create
+    //   during DFG-&gt;B3 lowering, and that patchpoint will have a generator that calls
+    //   handle-&gt;scheduleBlah(). That generator will be called multiple times if your patchpoint got
+    //   duplicated.
+    //
+    // - Combination of unwind and non-unwind exception handlers inside one patchpoint. A GetById may
+    //   need both an exception handler that serves as an unwind target and an exception handler that
+    //   is branched to directly for operation calls emitted inside the patchpoint. In that case,
+    //   you'll call both scheduleExitCreation() and scheduleExitCreationForUnwind() on the same
+    //   handle.
+
+    // Schedules the creation of an OSR exit jump destination. You don't know when this will be
+    // created, but it will happen before linking. You can link jumps to it during link time. That's
+    // why this returns an ExceptionTarget. That will contain the jump destination (target-&gt;label())
+    // at link time.
+    RefPtr&lt;ExceptionTarget&gt; scheduleExitCreation(const B3::StackmapGenerationParams&amp;);
+
+    // Schedules the creation of an OSR exit jump destination, and ensures that it gets associated
+    // with the handler for some callsite index.
+    void scheduleExitCreationForUnwind(const B3::StackmapGenerationParams&amp;, CallSiteIndex);
+
+private:
+    PatchpointExceptionHandle(
+        State&amp;, OSRExitDescriptor*, DFG::NodeOrigin, unsigned offset, const HandlerInfo&amp;);
+
+    RefPtr&lt;OSRExitHandle&gt; createHandle(const B3::StackmapGenerationParams&amp;);
+
+    State&amp; m_state;
+    OSRExitDescriptor* m_descriptor;
+    DFG::NodeOrigin m_origin;
+    unsigned m_offset;
+    HandlerInfo m_handler;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) &amp;&amp; FTL_USES_B3
+
+#endif // FTLPatchpointExceptionHandle_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLState.cpp (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLState.cpp        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLState.cpp        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;FTLForOSREntryJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLJITFinalizer.h&quot;
</span><ins>+#include &quot;FTLPatchpointExceptionHandle.h&quot;
</ins><span class="cx"> #include &lt;llvm/InitializeLLVM.h&gt;
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLState.h (194715 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLState.h        2016-01-07 21:17:01 UTC (rev 194715)
+++ trunk/Source/JavaScriptCore/ftl/FTLState.h        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;FTLJSCallVarargs.h&quot;
</span><span class="cx"> #include &quot;FTLJSTailCall.h&quot;
</span><span class="cx"> #include &quot;FTLStackMaps.h&quot;
</span><ins>+#include &lt;wtf/Box.h&gt;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -51,6 +52,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace FTL {
</span><span class="cx"> 
</span><ins>+class PatchpointExceptionHandle;
+
</ins><span class="cx"> inline bool verboseCompilationEnabled()
</span><span class="cx"> {
</span><span class="cx">     return DFG::verboseCompilationEnabled(DFG::FTLMode);
</span><span class="lines">@@ -82,8 +85,10 @@
</span><span class="cx">     GeneratedFunction generatedFunction;
</span><span class="cx">     JITFinalizer* finalizer;
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    B3::PatchpointValue* handleStackOverflowExceptionValue { nullptr };
-    B3::PatchpointValue* handleExceptionValue { nullptr };
</del><ins>+    // Top-level exception handler. Jump here if you know that you have to genericUnwind() and there
+    // are no applicable catch blocks anywhere in the Graph.
+    RefPtr&lt;PatchpointExceptionHandle&gt; defaultExceptionHandle;
+    Box&lt;CCallHelpers::Label&gt; exceptionHandler { Box&lt;CCallHelpers::Label&gt;::create() };
</ins><span class="cx">     B3::StackSlotValue* capturedValue { nullptr };
</span><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">     unsigned handleStackOverflowExceptionStackmapID { UINT_MAX };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptioninterestinglivestatejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-interesting-live-state.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    var pf = p.g;
+    try {
+        x = 102;
+        pf++;
+        result = o.f;
+        o = 104;
+        pf++;
+        x = 106;
+    } catch (e) {
+        return {outcome: &quot;exception&quot;, values: [o, pf, x, result]};
+    }
+    return {outcome: &quot;return&quot;, values: [o, pf, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects and getters.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        return 107;
+    });
+    if (i &amp; 1)
+        o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o, {g:200});
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 202)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var o = {};
+o.__defineGetter__(&quot;f&quot;, function() {
+    throw &quot;Error42&quot;;
+});
+var result = foo(o, {g:300});
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+if (result.values.length !== 4)
+    throw &quot;Error at end: bad number of values: &quot; + result.values.length;
+if (result.values[0] !== o)
+    throw &quot;Error at end: bad values[0]: &quot; + result.values[0];
+if (result.values[1] !== 301)
+    throw &quot;Error at end: bad values[1]: &quot; + result.values[1];
+if (result.values[2] !== 102)
+    throw &quot;Error at end: bad values[2]: &quot; + result.values[2];
+if (result.values[3] !== 101)
+    throw &quot;Error at end: bad values[3]: &quot; + result.values[3];
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptionnocatchjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-no-catch.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-no-catch.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception-no-catch.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    x = 102;
+    p = 103;
+    result = o.f;
+    o = 104;
+    p = 105;
+    x = 106;
+    return {outcome: &quot;return&quot;, values: [o, p, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects and getters.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        return 107;
+    });
+    if (i &amp; 1)
+        o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o);
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 105)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var result;
+try {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        throw &quot;Error42&quot;;
+    });
+    result = foo(o, 108);
+} catch (e) {
+    if (e != &quot;Error42&quot;)
+        throw &quot;Error at end: bad exception: &quot; + e;
+    result = {outcome: &quot;exception&quot;};
+}
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidgetterexceptionjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-getter-exception.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    try {
+        x = 102;
+        p = 103;
+        result = o.f;
+        o = 104;
+        p = 105;
+        x = 106;
+    } catch (e) {
+        return {outcome: &quot;exception&quot;, values: [o, p, x, result]};
+    }
+    return {outcome: &quot;return&quot;, values: [o, p, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects and getters.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        return 107;
+    });
+    if (i &amp; 1)
+        o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o);
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 105)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var o = {};
+o.__defineGetter__(&quot;f&quot;, function() {
+    throw &quot;Error42&quot;;
+});
+var result = foo(o, 108);
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+if (result.values.length !== 4)
+    throw &quot;Error at end: bad number of values: &quot; + result.values.length;
+if (result.values[0] !== o)
+    throw &quot;Error at end: bad values[0]: &quot; + result.values[0];
+if (result.values[1] !== 103)
+    throw &quot;Error at end: bad values[1]: &quot; + result.values[1];
+if (result.values[2] !== 102)
+    throw &quot;Error at end: bad values[2]: &quot; + result.values[2];
+if (result.values[3] !== 101)
+    throw &quot;Error at end: bad values[3]: &quot; + result.values[3];
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptioninterestinglivestatejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-interesting-live-state.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    var pf = p.g;
+    try {
+        x = 102;
+        pf++;
+        result = o.f;
+        o = 104;
+        pf++;
+        x = 106;
+    } catch (e) {
+        return {outcome: &quot;exception&quot;, values: [o, pf, x, result]};
+    }
+    return {outcome: &quot;return&quot;, values: [o, pf, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o;
+    o = {f:107};
+    o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o, {g:200});
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 202)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var o = {};
+o.__defineGetter__(&quot;f&quot;, function() {
+    throw &quot;Error42&quot;;
+});
+var result = foo(o, {g:300});
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+if (result.values.length !== 4)
+    throw &quot;Error at end: bad number of values: &quot; + result.values.length;
+if (result.values[0] !== o)
+    throw &quot;Error at end: bad values[0]: &quot; + result.values[0];
+if (result.values[1] !== 301)
+    throw &quot;Error at end: bad values[1]: &quot; + result.values[1];
+if (result.values[2] !== 102)
+    throw &quot;Error at end: bad values[2]: &quot; + result.values[2];
+if (result.values[3] !== 101)
+    throw &quot;Error at end: bad values[3]: &quot; + result.values[3];
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptionnocatchjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-no-catch.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-no-catch.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception-no-catch.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    x = 102;
+    p = 103;
+    result = o.f;
+    o = 104;
+    p = 105;
+    x = 106;
+    return {outcome: &quot;return&quot;, values: [o, p, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o;
+    o = {f:107};
+    o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o);
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 105)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var result;
+try {
+    var o = {};
+    o.__defineGetter__(&quot;f&quot;, function() {
+        throw &quot;Error42&quot;;
+    });
+    result = foo(o, 108);
+} catch (e) {
+    if (e != &quot;Error42&quot;)
+        throw &quot;Error at end: bad exception: &quot; + e;
+    result = {outcome: &quot;exception&quot;};
+}
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlgetbyidslowexceptionjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-get-by-id-slow-exception.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    try {
+        x = 102;
+        p = 103;
+        result = o.f;
+        o = 104;
+        p = 105;
+        x = 106;
+    } catch (e) {
+        return {outcome: &quot;exception&quot;, values: [o, p, x, result]};
+    }
+    return {outcome: &quot;return&quot;, values: [o, p, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o;
+    o = {f:107};
+    o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    var result = foo(o);
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 105)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (result.values[3] !== 107)
+        throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+}
+
+// Now throw an exception.
+var o = {};
+o.__defineGetter__(&quot;f&quot;, function() {
+    throw &quot;Error42&quot;;
+});
+var result = foo(o, 108);
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+if (result.values.length !== 4)
+    throw &quot;Error at end: bad number of values: &quot; + result.values.length;
+if (result.values[0] !== o)
+    throw &quot;Error at end: bad values[0]: &quot; + result.values[0];
+if (result.values[1] !== 103)
+    throw &quot;Error at end: bad values[1]: &quot; + result.values[1];
+if (result.values[2] !== 102)
+    throw &quot;Error at end: bad values[2]: &quot; + result.values[2];
+if (result.values[3] !== 101)
+    throw &quot;Error at end: bad values[3]: &quot; + result.values[3];
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftloperationexceptioninterestinglivestatejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-interesting-live-state.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-interesting-live-state.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-interesting-live-state.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    var pf = p.g;
+    try {
+        x = 102;
+        pf++;
+        result = o.f;
+        o = 104;
+        pf++;
+        x = 106;
+    } catch (e) {
+        return {outcome: &quot;exception&quot;, values: [o, pf, x, result]};
+    }
+    return {outcome: &quot;return&quot;, values: [o, pf, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects and non-object types.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o;
+    var isObject = i &amp; 1;
+    if (isObject) {
+        o = {f:107};
+        o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    } else
+        o = 42;
+    var result = foo(o, {g:200});
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 202)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (isObject) {
+        if (result.values[3] !== 107)
+            throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+    } else {
+        if (result.values[3] !== void 0)
+            throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+    }
+}
+
+// Now throw an exception.
+var result = foo(null, {g:300});
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
+if (result.values.length !== 4)
+    throw &quot;Error at end: bad number of values: &quot; + result.values.length;
+if (result.values[0] !== null)
+    throw &quot;Error at end: bad values[0]: &quot; + result.values[0];
+if (result.values[1] !== 301)
+    throw &quot;Error at end: bad values[1]: &quot; + result.values[1];
+if (result.values[2] !== 102)
+    throw &quot;Error at end: bad values[2]: &quot; + result.values[2];
+if (result.values[3] !== 101)
+    throw &quot;Error at end: bad values[3]: &quot; + result.values[3];
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftloperationexceptionnocatchjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-no-catch.js (0 => 194716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-no-catch.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-operation-exception-no-catch.js        2016-01-07 21:20:37 UTC (rev 194716)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+function foo(o, p) {
+    var x = 100;
+    var result = 101;
+    x = 102;
+    p = 103;
+    result = o.f;
+    o = 104;
+    p = 105;
+    x = 106;
+    return {outcome: &quot;return&quot;, values: [o, p, x, result]};
+}
+
+noInline(foo);
+
+// Warm up foo() with polymorphic objects and non-object types.
+for (var i = 0; i &lt; 100000; ++i) {
+    var o;
+    var isObject = i &amp; 1;
+    if (isObject) {
+        o = {f:107};
+        o[&quot;i&quot; + i] = i; // Make it polymorphic.
+    } else
+        o = 42;
+    var result = foo(o);
+    if (result.outcome !== &quot;return&quot;)
+        throw &quot;Error in loop: bad outcome: &quot; + result.outcome;
+    if (result.values.length !== 4)
+        throw &quot;Error in loop: bad number of values: &quot; + result.values.length;
+    if (result.values[0] !== 104)
+        throw &quot;Error in loop: bad values[0]: &quot; + result.values[0];
+    if (result.values[1] !== 105)
+        throw &quot;Error in loop: bad values[1]: &quot; + result.values[1];
+    if (result.values[2] !== 106)
+        throw &quot;Error in loop: bad values[2]: &quot; + result.values[2];
+    if (isObject) {
+        if (result.values[3] !== 107)
+            throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+    } else {
+        if (result.values[3] !== void 0)
+            throw &quot;Error in loop: bad values[3]: &quot; + result.values[3];
+    }
+}
+
+// Now throw an exception.
+var result;
+try {
+    result = foo(null, 108);
+} catch (e) {
+    result = {outcome: &quot;exception&quot;};
+}
+if (result.outcome !== &quot;exception&quot;)
+    throw &quot;Error at end: bad outcome: &quot; + result.outcome;
</ins></span></pre>
</div>
</div>

</body>
</html>