<!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>[192845] 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/192845">192845</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2015-11-30 16:55:32 -0800 (Mon, 30 Nov 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>FTL OSR Exits that are exception handlers should not have two different entrances. Instead, we should have two discrete OSR exits that do different things.
https://bugs.webkit.org/show_bug.cgi?id=151404
Reviewed by Filip Pizlo.
* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLExceptionHandlerManager.cpp:
(JSC::FTL::ExceptionHandlerManager::addNewExit):
(JSC::FTL::ExceptionHandlerManager::addNewCallOperationExit):
(JSC::FTL::ExceptionHandlerManager::callOperationExceptionTarget):
(JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
(JSC::FTL::ExceptionHandlerManager::callOperationOSRExit):
(JSC::FTL::ExceptionHandlerManager::getByIdOSRExit): Deleted.
(JSC::FTL::ExceptionHandlerManager::subOSRExit): Deleted.
* ftl/FTLExceptionHandlerManager.h:
* ftl/FTLExitThunkGenerator.cpp:
(JSC::FTL::ExitThunkGenerator::emitThunk):
* ftl/FTLOSRExit.cpp:
(JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
(JSC::FTL::OSRExitDescriptor::isExceptionHandler):
(JSC::FTL::OSRExit::OSRExit):
(JSC::FTL::OSRExit::spillRegistersToSpillSlot):
(JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
(JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
(JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind):
(JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
(JSC::FTL::OSRExit::needsRegisterRecoveryOnGenericUnwindOSRExitPath):
(JSC::FTL::OSRExitDescriptor::willArriveAtExitFromIndirectExceptionCheck): Deleted.
(JSC::FTL::OSRExitDescriptor::mightArriveAtOSRExitFromGenericUnwind): Deleted.
(JSC::FTL::OSRExitDescriptor::mightArriveAtOSRExitFromCallOperation): Deleted.
(JSC::FTL::OSRExitDescriptor::needsRegisterRecoveryOnGenericUnwindOSRExitPath): Deleted.
* ftl/FTLOSRExit.h:
* ftl/FTLOSRExitCompilationInfo.h:
(JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileFTLOSRExit):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagercpp">trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagerh">trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorcpp">trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitcpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExith">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilationInfoh">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2015-11-30 Saam barati <sbarati@apple.com>
+
+ FTL OSR Exits that are exception handlers should not have two different entrances. Instead, we should have two discrete OSR exits that do different things.
+ https://bugs.webkit.org/show_bug.cgi?id=151404
+
+ Reviewed by Filip Pizlo.
+
+ * ftl/FTLCompile.cpp:
+ (JSC::FTL::mmAllocateDataSection):
+ * ftl/FTLExceptionHandlerManager.cpp:
+ (JSC::FTL::ExceptionHandlerManager::addNewExit):
+ (JSC::FTL::ExceptionHandlerManager::addNewCallOperationExit):
+ (JSC::FTL::ExceptionHandlerManager::callOperationExceptionTarget):
+ (JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
+ (JSC::FTL::ExceptionHandlerManager::callOperationOSRExit):
+ (JSC::FTL::ExceptionHandlerManager::getByIdOSRExit): Deleted.
+ (JSC::FTL::ExceptionHandlerManager::subOSRExit): Deleted.
+ * ftl/FTLExceptionHandlerManager.h:
+ * ftl/FTLExitThunkGenerator.cpp:
+ (JSC::FTL::ExitThunkGenerator::emitThunk):
+ * ftl/FTLOSRExit.cpp:
+ (JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
+ (JSC::FTL::OSRExitDescriptor::isExceptionHandler):
+ (JSC::FTL::OSRExit::OSRExit):
+ (JSC::FTL::OSRExit::spillRegistersToSpillSlot):
+ (JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
+ (JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
+ (JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind):
+ (JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
+ (JSC::FTL::OSRExit::needsRegisterRecoveryOnGenericUnwindOSRExitPath):
+ (JSC::FTL::OSRExitDescriptor::willArriveAtExitFromIndirectExceptionCheck): Deleted.
+ (JSC::FTL::OSRExitDescriptor::mightArriveAtOSRExitFromGenericUnwind): Deleted.
+ (JSC::FTL::OSRExitDescriptor::mightArriveAtOSRExitFromCallOperation): Deleted.
+ (JSC::FTL::OSRExitDescriptor::needsRegisterRecoveryOnGenericUnwindOSRExitPath): Deleted.
+ * ftl/FTLOSRExit.h:
+ * ftl/FTLOSRExitCompilationInfo.h:
+ (JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo):
+ * ftl/FTLOSRExitCompiler.cpp:
+ (JSC::FTL::compileFTLOSRExit):
+
</ins><span class="cx"> 2015-11-30 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Refactor the op_add, op_sub, and op_mul snippets to use the SnippetOperand class.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -643,13 +643,40 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> OSRExit& exit = state.jitCode->osrExit.last();
</span><del>- if (exitDescriptor.willArriveAtExitFromIndirectExceptionCheck()) {
</del><ins>+ if (exit.willArriveAtExitFromIndirectExceptionCheck()) {
</ins><span class="cx"> StackMaps::Record& record = iter->value[j].record;
</span><span class="cx"> RELEASE_ASSERT(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader.isSet());
</span><span class="cx"> CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
</span><span class="cx"> exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
</span><del>- exceptionHandlerManager.addNewExit(iter->value[j].index, state.jitCode->osrExit.size() - 1);
</del><span class="cx">
</span><ins>+ OSRExit* callOperationExit = nullptr;
+ if (exitDescriptor.m_exceptionType == ExceptionType::SubGenerator) {
+ exceptionHandlerManager.addNewCallOperationExit(iter->value[j].index, state.jitCode->osrExit.size() - 1);
+ callOperationExit = &exit;
+ } else
+ exceptionHandlerManager.addNewExit(iter->value[j].index, state.jitCode->osrExit.size() - 1);
+
+ if (exitDescriptor.m_exceptionType == ExceptionType::GetById || exitDescriptor.m_exceptionType == ExceptionType::PutById) {
+ // We create two different OSRExits for GetById and PutById.
+ // One exit that will be arrived at from the genericUnwind exception handler path,
+ // and the other that will be arrived at from the callOperation exception handler path.
+ // This code here generates the second callOperation variant.
+ uint32_t stackmapRecordIndex = iter->value[j].index;
+ OSRExit exit(exitDescriptor, stackmapRecordIndex);
+ if (exitDescriptor.m_exceptionType == ExceptionType::GetById)
+ exit.m_exceptionType = ExceptionType::GetByIdCallOperation;
+ else
+ exit.m_exceptionType = ExceptionType::PutByIdCallOperation;
+ CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
+ exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
+
+ state.jitCode->osrExit.append(exit);
+ state.finalizer->osrExit.append(OSRExitCompilationInfo());
+
+ exceptionHandlerManager.addNewCallOperationExit(iter->value[j].index, state.jitCode->osrExit.size() - 1);
+ callOperationExit = &state.jitCode->osrExit.last();
+ }
+
</ins><span class="cx"> // Subs and GetByIds have an interesting register preservation story,
</span><span class="cx"> // see comment below at GetById to read about it.
</span><span class="cx"> //
</span><span class="lines">@@ -666,13 +693,13 @@
</span><span class="cx"> GPRReg result = record.locations[0].directGPR();
</span><span class="cx"> GPRReg base = record.locations[1].directGPR();
</span><span class="cx"> if (base == result)
</span><del>- exit.registersToPreserveForCallThatMightThrow.set(base);
</del><ins>+ callOperationExit->registersToPreserveForCallThatMightThrow.set(base);
</ins><span class="cx"> } else if (exitDescriptor.m_exceptionType == ExceptionType::SubGenerator) {
</span><span class="cx"> GPRReg result = record.locations[0].directGPR();
</span><span class="cx"> GPRReg left = record.locations[1].directGPR();
</span><span class="cx"> GPRReg right = record.locations[2].directGPR();
</span><span class="cx"> if (result == left || result == right)
</span><del>- exit.registersToPreserveForCallThatMightThrow.set(result);
</del><ins>+ callOperationExit->registersToPreserveForCallThatMightThrow.set(result);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -703,7 +730,7 @@
</span><span class="cx"> info.m_thunkAddress = linkBuffer->locationOf(info.m_thunkLabel);
</span><span class="cx"> exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
</span><span class="cx">
</span><del>- if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind()) {
</del><ins>+ if (exit.willArriveAtOSRExitFromGenericUnwind()) {
</ins><span class="cx"> HandlerInfo newHandler = exit.m_descriptor.m_baselineExceptionHandler;
</span><span class="cx"> newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
</span><span class="cx"> newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
</span><span class="lines">@@ -781,7 +808,7 @@
</span><span class="cx"> // register that we would like to do value recovery on. We combat this situation from ever
</span><span class="cx"> // taking place by ensuring we spill the original base value and then recover it from
</span><span class="cx"> // the spill slot as the first step in OSR exit.
</span><del>- if (OSRExit* exit = exceptionHandlerManager.getByIdOSRExit(iter->value[i].index))
</del><ins>+ if (OSRExit* exit = exceptionHandlerManager.callOperationOSRExit(iter->value[i].index))
</ins><span class="cx"> exit->spillRegistersToSpillSlot(slowPathJIT, jsCallThatMightThrowSpillOffset);
</span><span class="cx"> }
</span><span class="cx"> MacroAssembler::Call call = callOperation(
</span><span class="lines">@@ -900,7 +927,7 @@
</span><span class="cx"> if (result == left || result == right) {
</span><span class="cx"> // This situation has a really interesting register preservation story.
</span><span class="cx"> // See comment above for GetByIds.
</span><del>- if (OSRExit* exit = exceptionHandlerManager.subOSRExit(iter->value[i].index))
</del><ins>+ if (OSRExit* exit = exceptionHandlerManager.callOperationOSRExit(iter->value[i].index))
</ins><span class="cx"> exit->spillRegistersToSpillSlot(slowPathJIT, jsCallThatMightThrowSpillOffset);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1099,7 +1126,7 @@
</span><span class="cx"> OSRExit& exit = jitCode->osrExit[exitIndex];
</span><span class="cx"> Vector<const void*> codeAddresses;
</span><span class="cx">
</span><del>- if (exit.m_descriptor.willArriveAtExitFromIndirectExceptionCheck()) // This jump doesn't happen directly from a patchpoint/stackmap we compile. It happens indirectly through an exception check somewhere.
</del><ins>+ if (exit.willArriveAtExitFromIndirectExceptionCheck()) // This jump doesn't happen directly from a patchpoint/stackmap we compile. It happens indirectly through an exception check somewhere.
</ins><span class="cx"> continue;
</span><span class="cx">
</span><span class="cx"> StackMaps::Record& record = jitCode->stackmaps.records[exit.m_stackmapRecordIndex];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -41,9 +41,16 @@
</span><span class="cx"> {
</span><span class="cx"> m_map.add(stackmapRecordIndex, osrExitIndex);
</span><span class="cx"> OSRExit& exit = m_state.jitCode->osrExit[osrExitIndex];
</span><del>- RELEASE_ASSERT(exit.m_descriptor.willArriveAtExitFromIndirectExceptionCheck());
</del><ins>+ RELEASE_ASSERT(exit.willArriveAtExitFromIndirectExceptionCheck());
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void ExceptionHandlerManager::addNewCallOperationExit(uint32_t stackmapRecordIndex, size_t osrExitIndex)
+{
+ m_callOperationMap.add(stackmapRecordIndex, osrExitIndex);
+ OSRExit& exit = m_state.jitCode->osrExit[osrExitIndex];
+ RELEASE_ASSERT(exit.willArriveAtExitFromIndirectExceptionCheck());
+}
+
</ins><span class="cx"> CodeLocationLabel ExceptionHandlerManager::callOperationExceptionTarget(uint32_t stackmapRecordIndex)
</span><span class="cx"> {
</span><span class="cx"> #if FTL_USES_B3
</span><span class="lines">@@ -51,15 +58,15 @@
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> return CodeLocationLabel();
</span><span class="cx"> #else // FTL_USES_B3
</span><del>- auto findResult = m_map.find(stackmapRecordIndex);
- if (findResult == m_map.end())
</del><ins>+ auto findResult = m_callOperationMap.find(stackmapRecordIndex);
+ if (findResult == m_callOperationMap.end())
</ins><span class="cx"> return CodeLocationLabel();
</span><span class="cx">
</span><span class="cx"> size_t osrExitIndex = findResult->value;
</span><del>- RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_descriptor.mightArriveAtOSRExitFromCallOperation());
</del><ins>+ RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].willArriveAtOSRExitFromCallOperation());
</ins><span class="cx"> OSRExitCompilationInfo& info = m_state.finalizer->osrExit[osrExitIndex];
</span><del>- RELEASE_ASSERT(info.m_callOperationExceptionOSRExitEntrance.isSet());
- return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_callOperationExceptionOSRExitEntrance);
</del><ins>+ RELEASE_ASSERT(info.m_thunkLabel.isSet());
+ return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_thunkLabel);
</ins><span class="cx"> #endif // FTL_USES_B3
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -82,28 +89,19 @@
</span><span class="cx"> #endif // FTL_USES_B3
</span><span class="cx"> }
</span><span class="cx">
</span><del>-OSRExit* ExceptionHandlerManager::getByIdOSRExit(uint32_t stackmapRecordIndex)
</del><ins>+OSRExit* ExceptionHandlerManager::callOperationOSRExit(uint32_t stackmapRecordIndex)
</ins><span class="cx"> {
</span><del>- auto findResult = m_map.find(stackmapRecordIndex);
- if (findResult == m_map.end())
</del><ins>+ auto findResult = m_callOperationMap.find(stackmapRecordIndex);
+ if (findResult == m_callOperationMap.end())
</ins><span class="cx"> return nullptr;
</span><span class="cx"> size_t osrExitIndex = findResult->value;
</span><span class="cx"> OSRExit* exit = &m_state.jitCode->osrExit[osrExitIndex];
</span><del>- RELEASE_ASSERT(exit->m_descriptor.m_exceptionType == ExceptionType::GetById);
</del><ins>+ // We may have more than one exit for the same stackmap record index (i.e, for GetByIds and PutByIds).
+ // Therefore we need to make sure this exit really is a callOperation OSR exit.
+ RELEASE_ASSERT(exit->willArriveAtOSRExitFromCallOperation());
</ins><span class="cx"> return exit;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-OSRExit* ExceptionHandlerManager::subOSRExit(uint32_t stackmapRecordIndex)
-{
- auto findResult = m_map.find(stackmapRecordIndex);
- if (findResult == m_map.end())
- return nullptr;
- size_t osrExitIndex = findResult->value;
- OSRExit* exit = &m_state.jitCode->osrExit[osrExitIndex];
- RELEASE_ASSERT(exit->m_descriptor.m_exceptionType == ExceptionType::SubGenerator);
- return exit;
-}
-
</del><span class="cx"> OSRExit* ExceptionHandlerManager::getCallOSRExitCommon(uint32_t stackmapRecordIndex)
</span><span class="cx"> {
</span><span class="cx"> auto findResult = m_map.find(stackmapRecordIndex);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExceptionHandlerManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.h (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.h        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.h        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -54,14 +54,14 @@
</span><span class="cx"> ExceptionHandlerManager(State& state);
</span><span class="cx">
</span><span class="cx"> void addNewExit(uint32_t stackmapRecordIndex, size_t osrExitIndex);
</span><ins>+ void addNewCallOperationExit(uint32_t stackmapRecordIndex, size_t osrExitIndex);
</ins><span class="cx">
</span><span class="cx"> // These functions only make sense to be called after we've generated the OSR
</span><span class="cx"> // exit thunks and allocated the OSR exit thunks' link buffer.
</span><span class="cx"> CodeLocationLabel callOperationExceptionTarget(uint32_t stackmapRecordIndex);
</span><span class="cx"> CodeLocationLabel lazySlowPathExceptionTarget(uint32_t stackmapRecordIndex);
</span><span class="cx">
</span><del>- OSRExit* getByIdOSRExit(uint32_t stackmapRecordIndex);
- OSRExit* subOSRExit(uint32_t stackmapRecordIndex);
</del><ins>+ OSRExit* callOperationOSRExit(uint32_t stackmapRecordIndex);
</ins><span class="cx"> OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSCall&);
</span><span class="cx"> OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSTailCall&);
</span><span class="cx"> OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSCallVarargs&);
</span><span class="lines">@@ -78,6 +78,7 @@
</span><span class="cx"> State& m_state;
</span><span class="cx"> typedef HashMap<uint32_t, size_t, WTF::IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> RecordIndexToOSRExitIndexMap;
</span><span class="cx"> RecordIndexToOSRExitIndexMap m_map;
</span><ins>+ RecordIndexToOSRExitIndexMap m_callOperationMap;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExitThunkGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -53,27 +53,18 @@
</span><span class="cx">
</span><span class="cx"> info.m_thunkLabel = label();
</span><span class="cx">
</span><del>- Jump jumpToPushIndexFromGenericUnwind;
- if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind()) {
</del><ins>+ ASSERT(!(exit.willArriveAtOSRExitFromGenericUnwind() && exit.willArriveAtOSRExitFromCallOperation()));
+ if (exit.willArriveAtOSRExitFromGenericUnwind()) {
</ins><span class="cx"> restoreCalleeSavesFromVMCalleeSavesBuffer();
</span><span class="cx"> loadPtr(vm()->addressOfCallFrameForCatch(), framePointerRegister);
</span><span class="cx"> addPtr(TrustedImm32(- static_cast<int64_t>(m_state.jitCode->stackmaps.stackSizeForLocals())),
</span><span class="cx"> framePointerRegister, stackPointerRegister);
</span><span class="cx">
</span><del>- if (exit.m_descriptor.needsRegisterRecoveryOnGenericUnwindOSRExitPath())
</del><ins>+ if (exit.needsRegisterRecoveryOnGenericUnwindOSRExitPath())
</ins><span class="cx"> exit.recoverRegistersFromSpillSlot(*this, osrExitFromGenericUnwindStackSpillSlot);
</span><del>-
- jumpToPushIndexFromGenericUnwind = jump();
- }
-
- if (exit.m_descriptor.mightArriveAtOSRExitFromCallOperation()) {
- info.m_callOperationExceptionOSRExitEntrance = label();
</del><ins>+ } else if (exit.willArriveAtOSRExitFromCallOperation())
</ins><span class="cx"> exit.recoverRegistersFromSpillSlot(*this, osrExitFromGenericUnwindStackSpillSlot);
</span><del>- }
</del><span class="cx">
</span><del>- if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind())
- jumpToPushIndexFromGenericUnwind.link(this);
-
</del><span class="cx"> pushToSaveImmediateWithoutTouchingRegisters(TrustedImm32(index));
</span><span class="cx"> info.m_thunkJump = patchableJump();
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -56,62 +56,6 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool OSRExitDescriptor::willArriveAtExitFromIndirectExceptionCheck() const
-{
- switch (m_exceptionType) {
- case ExceptionType::JSCall:
- case ExceptionType::GetById:
- case ExceptionType::PutById:
- case ExceptionType::LazySlowPath:
- case ExceptionType::SubGenerator:
- return true;
- default:
- return false;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-bool OSRExitDescriptor::mightArriveAtOSRExitFromGenericUnwind() const
-{
- switch (m_exceptionType) {
- case ExceptionType::JSCall:
- case ExceptionType::GetById:
- case ExceptionType::PutById:
- return true;
- default:
- return false;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-bool OSRExitDescriptor::mightArriveAtOSRExitFromCallOperation() const
-{
- switch (m_exceptionType) {
- case ExceptionType::GetById:
- case ExceptionType::PutById:
- case ExceptionType::SubGenerator:
- return true;
- default:
- return false;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-bool OSRExitDescriptor::needsRegisterRecoveryOnGenericUnwindOSRExitPath() const
-{
- // Calls/PutByIds/GetByIds all have a generic unwind osr exit paths.
- // But, GetById and PutById ICs will do register recovery themselves
- // because they're responsible for spilling necessary registers, so
- // they also must recover registers themselves.
- // Calls don't work this way. We compile Calls as patchpoints in LLVM.
- // A call patchpoint might pass us volatile registers for locations
- // we will do value recovery on. Therefore, before we make the call,
- // we must spill these registers. Otherwise, the call will clobber them.
- // Therefore, the corresponding OSR exit for the call will need to
- // recover the spilled registers.
- return m_exceptionType == ExceptionType::JSCall;
-}
-
</del><span class="cx"> bool OSRExitDescriptor::isExceptionHandler() const
</span><span class="cx"> {
</span><span class="cx"> return m_exceptionType != ExceptionType::None;
</span><span class="lines">@@ -131,6 +75,7 @@
</span><span class="cx"> : OSRExitBase(descriptor.m_kind, descriptor.m_codeOrigin, descriptor.m_codeOriginForExitProfile)
</span><span class="cx"> , m_descriptor(descriptor)
</span><span class="cx"> , m_stackmapRecordIndex(stackmapRecordIndex)
</span><ins>+ , m_exceptionType(descriptor.m_exceptionType)
</ins><span class="cx"> {
</span><span class="cx"> m_isExceptionHandler = descriptor.isExceptionHandler();
</span><span class="cx"> }
</span><span class="lines">@@ -186,7 +131,7 @@
</span><span class="cx">
</span><span class="cx"> void OSRExit::spillRegistersToSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_descriptor.mightArriveAtOSRExitFromGenericUnwind() || m_descriptor.mightArriveAtOSRExitFromCallOperation());
</del><ins>+ RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
</ins><span class="cx"> unsigned count = 0;
</span><span class="cx"> for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
</span><span class="cx"> if (registersToPreserveForCallThatMightThrow.get(reg)) {
</span><span class="lines">@@ -204,7 +149,7 @@
</span><span class="cx">
</span><span class="cx"> void OSRExit::recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_descriptor.mightArriveAtOSRExitFromGenericUnwind() || m_descriptor.mightArriveAtOSRExitFromCallOperation());
</del><ins>+ RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
</ins><span class="cx"> unsigned count = 0;
</span><span class="cx"> for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
</span><span class="cx"> if (registersToPreserveForCallThatMightThrow.get(reg)) {
</span><span class="lines">@@ -220,6 +165,64 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool OSRExit::willArriveAtExitFromIndirectExceptionCheck() const
+{
+ switch (m_exceptionType) {
+ case ExceptionType::JSCall:
+ case ExceptionType::GetById:
+ case ExceptionType::PutById:
+ case ExceptionType::LazySlowPath:
+ case ExceptionType::SubGenerator:
+ case ExceptionType::GetByIdCallOperation:
+ case ExceptionType::PutByIdCallOperation:
+ return true;
+ default:
+ return false;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool OSRExit::willArriveAtOSRExitFromGenericUnwind() const
+{
+ switch (m_exceptionType) {
+ case ExceptionType::JSCall:
+ case ExceptionType::GetById:
+ case ExceptionType::PutById:
+ return true;
+ default:
+ return false;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool OSRExit::willArriveAtOSRExitFromCallOperation() const
+{
+ switch (m_exceptionType) {
+ case ExceptionType::GetByIdCallOperation:
+ case ExceptionType::PutByIdCallOperation:
+ case ExceptionType::SubGenerator:
+ return true;
+ default:
+ return false;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool OSRExit::needsRegisterRecoveryOnGenericUnwindOSRExitPath() const
+{
+ // Calls/PutByIds/GetByIds all have a generic unwind osr exit paths.
+ // But, GetById and PutById ICs will do register recovery themselves
+ // because they're responsible for spilling necessary registers, so
+ // they also must recover registers themselves.
+ // Calls don't work this way. We compile Calls as patchpoints in LLVM.
+ // A call patchpoint might pass us volatile registers for locations
+ // we will do value recovery on. Therefore, before we make the call,
+ // we must spill these registers. Otherwise, the call will clobber them.
+ // Therefore, the corresponding OSR exit for the call will need to
+ // recover the spilled registers.
+ return m_exceptionType == ExceptionType::JSCall;
+}
+
</ins><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx">
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExith"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -136,14 +136,16 @@
</span><span class="cx"> // intrinsics (or meta-data, or something) to inform the backend that it's safe to
</span><span class="cx"> // make the predicate passed to 'exitIf()' more truthy.
</span><span class="cx">
</span><del>-enum class ExceptionType {
</del><ins>+enum class ExceptionType : uint8_t {
</ins><span class="cx"> None,
</span><span class="cx"> CCallException,
</span><span class="cx"> JSCall,
</span><span class="cx"> GetById,
</span><ins>+ GetByIdCallOperation,
</ins><span class="cx"> PutById,
</span><ins>+ PutByIdCallOperation,
</ins><span class="cx"> LazySlowPath,
</span><del>- SubGenerator
</del><ins>+ SubGenerator,
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> struct OSRExitDescriptor {
</span><span class="lines">@@ -152,10 +154,6 @@
</span><span class="cx"> CodeOrigin, CodeOrigin originForProfile,
</span><span class="cx"> unsigned numberOfArguments, unsigned numberOfLocals);
</span><span class="cx">
</span><del>- bool willArriveAtExitFromIndirectExceptionCheck() const;
- bool mightArriveAtOSRExitFromGenericUnwind() const;
- bool mightArriveAtOSRExitFromCallOperation() const;
- bool needsRegisterRecoveryOnGenericUnwindOSRExitPath() const;
</del><span class="cx"> bool isExceptionHandler() const;
</span><span class="cx">
</span><span class="cx"> ExitKind m_kind;
</span><span class="lines">@@ -191,6 +189,7 @@
</span><span class="cx"> unsigned m_patchableCodeOffset;
</span><span class="cx"> // Offset within Stackmap::records
</span><span class="cx"> uint32_t m_stackmapRecordIndex;
</span><ins>+ ExceptionType m_exceptionType;
</ins><span class="cx">
</span><span class="cx"> RegisterSet registersToPreserveForCallThatMightThrow;
</span><span class="cx">
</span><span class="lines">@@ -203,6 +202,11 @@
</span><span class="cx"> void gatherRegistersToSpillForCallIfException(StackMaps&, StackMaps::Record&);
</span><span class="cx"> void spillRegistersToSpillSlot(CCallHelpers&, int32_t stackSpillSlot);
</span><span class="cx"> void recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot);
</span><ins>+
+ bool willArriveAtOSRExitFromGenericUnwind() const;
+ bool willArriveAtExitFromIndirectExceptionCheck() const;
+ bool willArriveAtOSRExitFromCallOperation() const;
+ bool needsRegisterRecoveryOnGenericUnwindOSRExitPath() const;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilationInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -39,7 +39,6 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> MacroAssembler::Label m_thunkLabel;
</span><del>- MacroAssembler::Label m_callOperationExceptionOSRExitEntrance;
</del><span class="cx"> MacroAssembler::PatchableJump m_thunkJump;
</span><span class="cx"> CodeLocationLabel m_thunkAddress;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (192844 => 192845)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-12-01 00:55:32 UTC (rev 192845)
</span><span class="lines">@@ -547,7 +547,7 @@
</span><span class="cx"> dataLog(" Exit stackmap ID: ", exit.m_descriptor.m_stackmapID, "\n");
</span><span class="cx"> dataLog(" Current call site index: ", exec->callSiteIndex().bits(), "\n");
</span><span class="cx"> dataLog(" Exit is exception handler: ", exit.m_isExceptionHandler,
</span><del>- " might arrive at exit from genericUnwind(): ", exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind(),
</del><ins>+ " will arrive at exit from genericUnwind(): ", exit.willArriveAtOSRExitFromGenericUnwind(),
</ins><span class="cx"> " will arrive at exit from lazy slow path: ", exit.m_descriptor.m_exceptionType == ExceptionType::LazySlowPath, "\n");
</span><span class="cx"> dataLog(" Exit values: ", exit.m_descriptor.m_values, "\n");
</span><span class="cx"> if (!exit.m_descriptor.m_materializations.isEmpty()) {
</span></span></pre>
</div>
</div>
</body>
</html>