Exits from exceptions shouldn't jettison code
https://bugs.webkit.org/show_bug.cgi?id=153564
Reviewed by Geoffrey Garen.
Source/JavaScriptCore:
We create two new exit kinds for exception-handling
OSRExits:
- ExceptionCheck: an exception check after a C call.
- GenericUnwind: an OSR exit executes because it's jumped to from genericUnwind machinery.
Having these two new exit kinds allows us to remove fields from
various OSRExit variants that store booleans indicating
if the exit is an exception handler, and if so, what kind
of exception handler. Most of this patch is just removing
those old fields and adding new equivalent functions.
This patch also implements the policy that we should never consider jettisoning
code from exits that happen from an exception check to an op_catch (it might be worth
considering a similar policy for 'throw'). We're choosing this policy because
it will almost never be more expensive, in total, to execute the OSR exit than
to execute the baseline variant of the code. When an exception is thrown, we do
really expensive work, like call through to genericUnwind, and also create an error
object with a stack trace. The cost of OSR exiting here is small in comparison to
those other operations. And penalizing a CodeBlock for OSR exiting from an exception
is silly because the basis of our implementation of exception handling in the
upper tiers is to OSR exit on a caught exception. So we used to penalize
ourselves for having an implementation that is correct w.r.t our design goals.
I've verified this hypothesis with on v8-raytrace by adding a new
benchmark that throws with very high frequency. Implementing
this policy on that benchmark results in about a 4-5% speed up.
* bytecode/ExitKind.cpp:
(JSC::exitKindToString):
(JSC::exitKindMayJettison):
(JSC::exitKindIsCountable): Deleted.
* bytecode/ExitKind.h:
* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::noticeOSREntry):
(JSC::DFG::JITCompiler::appendExceptionHandlingOSRExit):
(JSC::DFG::JITCompiler::exceptionCheck):
(JSC::DFG::JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded):
* dfg/DFGJITCompiler.h:
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::OSRExit):
* dfg/DFGOSRExit.h:
(JSC::DFG::OSRExit::considerAddingAsFrequentExitSite):
* dfg/DFGOSRExitBase.h:
(JSC::DFG::OSRExitBase::OSRExitBase):
(JSC::DFG::OSRExitBase::isExceptionHandler):
(JSC::DFG::OSRExitBase::isGenericUnwindHandler):
(JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSite):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::handleExitCounts):
(JSC::DFG::osrWriteBarrier):
(JSC::DFG::adjustAndJumpToTarget):
* dfg/DFGOSRExitCompilerCommon.h:
(JSC::DFG::adjustFrameAndStackInOSRExitCompilerThunk):
* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLExitThunkGenerator.cpp:
(JSC::FTL::ExitThunkGenerator::emitThunk):
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
* ftl/FTLOSRExit.cpp:
(JSC::FTL::OSRExitDescriptor::emitOSRExit):
(JSC::FTL::OSRExitDescriptor::emitOSRExitLater):
(JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
(JSC::FTL::OSRExit::OSRExit):
(JSC::FTL::OSRExit::spillRegistersToSpillSlot):
(JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
(JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
(JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
(JSC::FTL::exceptionTypeWillArriveAtOSRExitFromGenericUnwind): Deleted.
(JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind): Deleted.
* ftl/FTLOSRExit.h:
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
(JSC::FTL::compileFTLOSRExit):
* ftl/FTLPatchpointExceptionHandle.cpp:
(JSC::FTL::PatchpointExceptionHandle::scheduleExitCreation):
(JSC::FTL::PatchpointExceptionHandle::scheduleExitCreationForUnwind):
(JSC::FTL::PatchpointExceptionHandle::PatchpointExceptionHandle):
(JSC::FTL::PatchpointExceptionHandle::createHandle):
* ftl/FTLPatchpointExceptionHandle.h:
LayoutTests:
* js/regress/script-tests/v8-raytrace-with-try-catch-high-frequency-throws.js: Added.
(randomException):
(Class.create):
(Object.extend):
(Flog.RayTracer.Color.prototype.initialize):
(Flog.RayTracer.Color.prototype.add):
(Flog.RayTracer.Color.prototype.addScalar):
(Flog.RayTracer.Color.prototype.subtract):
(Flog.RayTracer.Color.prototype.multiply):
(Flog.RayTracer.Color.prototype.multiplyScalar):
(Flog.RayTracer.Color.prototype.divideFactor):
(Flog.RayTracer.Color.prototype.limit):
(Flog.RayTracer.Color.prototype.distance):
(Flog.RayTracer.Color.prototype.blend):
(Flog.RayTracer.Color.prototype.brightness):
(Flog.RayTracer.Color.prototype.toString):
(Flog.RayTracer.Light.prototype.initialize):
(Flog.RayTracer.Light.prototype.toString):
(Flog.RayTracer.Vector.prototype.initialize):
(Flog.RayTracer.Vector.prototype.copy):
(Flog.RayTracer.Vector.prototype.normalize):
(Flog.RayTracer.Vector.prototype.magnitude):
(Flog.RayTracer.Vector.prototype.cross):
(Flog.RayTracer.Vector.prototype.dot):
(Flog.RayTracer.Vector.prototype.add):
(Flog.RayTracer.Vector.prototype.subtract):
(Flog.RayTracer.Vector.prototype.multiplyVector):
(Flog.RayTracer.Vector.prototype.multiplyScalar):
(Flog.RayTracer.Vector.prototype.toString):
(Flog.RayTracer.Ray.prototype.initialize):
(Flog.RayTracer.Ray.prototype.toString):
(Flog.RayTracer.Scene.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.getColor):
(Flog.RayTracer.Material.BaseMaterial.prototype.wrapUp):
(Flog.RayTracer.Material.BaseMaterial.prototype.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Shape.Sphere.prototype.initialize):
(Flog.RayTracer.Shape.Sphere.prototype.intersect):
(Flog.RayTracer.Shape.Sphere.prototype.toString):
(Flog.RayTracer.Shape.Plane.prototype.initialize):
(Flog.RayTracer.Shape.Plane.prototype.intersect):
(Flog.RayTracer.Shape.Plane.prototype.toString):
(Flog.RayTracer.IntersectionInfo.prototype.initialize):
(Flog.RayTracer.IntersectionInfo.prototype.toString):
(Flog.RayTracer.Camera.prototype.initialize):
(Flog.RayTracer.Camera.prototype.getRay):
(Flog.RayTracer.Camera.prototype.toString):
(Flog.RayTracer.Background.prototype.initialize):
(Flog.RayTracer.Engine.prototype.initialize):
(Flog.RayTracer.Engine.prototype.setPixel):
(Flog.RayTracer.Engine.prototype.renderScene):
(Flog.RayTracer.Engine.prototype.getPixelColor):
(Flog.RayTracer.Engine.prototype.testIntersection):
(Flog.RayTracer.Engine.prototype.getReflectionRay):
(Flog.RayTracer.Engine.prototype.rayTrace):
(renderScene):
* js/regress/v8-raytrace-with-try-catch-high-frequency-throws-expected.txt: Added.
* js/regress/v8-raytrace-with-try-catch-high-frequency-throws.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@195831 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 3b1c750..dc59fae 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,103 @@
+2016-01-29 Saam barati <sbarati@apple.com>
+
+ Exits from exceptions shouldn't jettison code
+ https://bugs.webkit.org/show_bug.cgi?id=153564
+
+ Reviewed by Geoffrey Garen.
+
+ We create two new exit kinds for exception-handling
+ OSRExits:
+ - ExceptionCheck: an exception check after a C call.
+ - GenericUnwind: an OSR exit executes because it's jumped to from genericUnwind machinery.
+
+ Having these two new exit kinds allows us to remove fields from
+ various OSRExit variants that store booleans indicating
+ if the exit is an exception handler, and if so, what kind
+ of exception handler. Most of this patch is just removing
+ those old fields and adding new equivalent functions.
+
+ This patch also implements the policy that we should never consider jettisoning
+ code from exits that happen from an exception check to an op_catch (it might be worth
+ considering a similar policy for 'throw'). We're choosing this policy because
+ it will almost never be more expensive, in total, to execute the OSR exit than
+ to execute the baseline variant of the code. When an exception is thrown, we do
+ really expensive work, like call through to genericUnwind, and also create an error
+ object with a stack trace. The cost of OSR exiting here is small in comparison to
+ those other operations. And penalizing a CodeBlock for OSR exiting from an exception
+ is silly because the basis of our implementation of exception handling in the
+ upper tiers is to OSR exit on a caught exception. So we used to penalize
+ ourselves for having an implementation that is correct w.r.t our design goals.
+
+ I've verified this hypothesis with on v8-raytrace by adding a new
+ benchmark that throws with very high frequency. Implementing
+ this policy on that benchmark results in about a 4-5% speed up.
+
+ * bytecode/ExitKind.cpp:
+ (JSC::exitKindToString):
+ (JSC::exitKindMayJettison):
+ (JSC::exitKindIsCountable): Deleted.
+ * bytecode/ExitKind.h:
+ * dfg/DFGJITCode.cpp:
+ (JSC::DFG::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::noticeOSREntry):
+ (JSC::DFG::JITCompiler::appendExceptionHandlingOSRExit):
+ (JSC::DFG::JITCompiler::exceptionCheck):
+ (JSC::DFG::JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded):
+ * dfg/DFGJITCompiler.h:
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (JSC::DFG::OSRExit::considerAddingAsFrequentExitSite):
+ * dfg/DFGOSRExitBase.h:
+ (JSC::DFG::OSRExitBase::OSRExitBase):
+ (JSC::DFG::OSRExitBase::isExceptionHandler):
+ (JSC::DFG::OSRExitBase::isGenericUnwindHandler):
+ (JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSite):
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompilerCommon.cpp:
+ (JSC::DFG::handleExitCounts):
+ (JSC::DFG::osrWriteBarrier):
+ (JSC::DFG::adjustAndJumpToTarget):
+ * dfg/DFGOSRExitCompilerCommon.h:
+ (JSC::DFG::adjustFrameAndStackInOSRExitCompilerThunk):
+ * ftl/FTLCompile.cpp:
+ (JSC::FTL::mmAllocateDataSection):
+ * ftl/FTLExitThunkGenerator.cpp:
+ (JSC::FTL::ExitThunkGenerator::emitThunk):
+ * ftl/FTLJITCode.cpp:
+ (JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
+ (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
+ (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
+ (JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
+ * ftl/FTLOSRExit.cpp:
+ (JSC::FTL::OSRExitDescriptor::emitOSRExit):
+ (JSC::FTL::OSRExitDescriptor::emitOSRExitLater):
+ (JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
+ (JSC::FTL::OSRExit::OSRExit):
+ (JSC::FTL::OSRExit::spillRegistersToSpillSlot):
+ (JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
+ (JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
+ (JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
+ (JSC::FTL::exceptionTypeWillArriveAtOSRExitFromGenericUnwind): Deleted.
+ (JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind): Deleted.
+ * ftl/FTLOSRExit.h:
+ * ftl/FTLOSRExitCompiler.cpp:
+ (JSC::FTL::compileStub):
+ (JSC::FTL::compileFTLOSRExit):
+ * ftl/FTLPatchpointExceptionHandle.cpp:
+ (JSC::FTL::PatchpointExceptionHandle::scheduleExitCreation):
+ (JSC::FTL::PatchpointExceptionHandle::scheduleExitCreationForUnwind):
+ (JSC::FTL::PatchpointExceptionHandle::PatchpointExceptionHandle):
+ (JSC::FTL::PatchpointExceptionHandle::createHandle):
+ * ftl/FTLPatchpointExceptionHandle.h:
+
2016-01-28 Yusuke Suzuki <utatane.tea@gmail.com>
[B3] REGRESSION(r195395): testComplex(64, 128) asserts on Linux with GCC
diff --git a/Source/JavaScriptCore/bytecode/ExitKind.cpp b/Source/JavaScriptCore/bytecode/ExitKind.cpp
index 30c5e64..84ff57b 100644
--- a/Source/JavaScriptCore/bytecode/ExitKind.cpp
+++ b/Source/JavaScriptCore/bytecode/ExitKind.cpp
@@ -84,25 +84,27 @@
return "WatchdogTimerFired";
case DebuggerEvent:
return "DebuggerEvent";
+ case ExceptionCheck:
+ return "ExceptionCheck";
+ case GenericUnwind:
+ return "GenericUnwind";
}
RELEASE_ASSERT_NOT_REACHED();
return "Unknown";
}
-bool exitKindIsCountable(ExitKind kind)
+bool exitKindMayJettison(ExitKind kind)
{
switch (kind) {
- case ExitKindUnset:
- RELEASE_ASSERT_NOT_REACHED();
- case BadType:
- case Uncountable:
- case LoadFromHole: // Already counted directly by the baseline JIT.
- case StoreToHole: // Already counted directly by the baseline JIT.
- case OutOfBounds: // Already counted directly by the baseline JIT.
+ case ExceptionCheck:
+ case GenericUnwind:
return false;
default:
return true;
}
+
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/ExitKind.h b/Source/JavaScriptCore/bytecode/ExitKind.h
index 700d388..22a54a1 100644
--- a/Source/JavaScriptCore/bytecode/ExitKind.h
+++ b/Source/JavaScriptCore/bytecode/ExitKind.h
@@ -53,11 +53,13 @@
Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
UncountableInvalidation, // We exited because the code block was invalidated; this means that we've already counted the reasons why the code block was invalidated.
WatchdogTimerFired, // We exited because we need to service the watchdog timer.
- DebuggerEvent // We exited because we need to service the debugger.
+ DebuggerEvent, // We exited because we need to service the debugger.
+ ExceptionCheck, // We exited because a direct exception check showed that we threw an exception from a C call.
+ GenericUnwind, // We exited because a we arrived at this OSR exit from genericUnwind.
};
const char* exitKindToString(ExitKind);
-bool exitKindIsCountable(ExitKind);
+bool exitKindMayJettison(ExitKind);
} // namespace JSC
diff --git a/Source/JavaScriptCore/dfg/DFGJITCode.cpp b/Source/JavaScriptCore/dfg/DFGJITCode.cpp
index 48217d3..b4c27bb 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCode.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCode.cpp
@@ -90,7 +90,7 @@
RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock* codeBlock, CallSiteIndex callSiteIndex)
{
for (OSRExit& exit : osrExit) {
- if (exit.m_isExceptionHandler && exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
+ if (exit.isExceptionHandler() && exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
Operands<ValueRecovery> valueRecoveries;
reconstruct(codeBlock, exit.m_codeOrigin, exit.m_streamIndex, valueRecoveries);
RegisterSet liveAtOSRExit;
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index ff399e8..3b91e6f 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -541,11 +541,9 @@
entry->m_reshufflings.shrinkToFit();
}
-void JITCompiler::appendExceptionHandlingOSRExit(unsigned eventStreamIndex, CodeOrigin opCatchOrigin, HandlerInfo* exceptionHandler, CallSiteIndex callSite, MacroAssembler::JumpList jumpsToFail)
+void JITCompiler::appendExceptionHandlingOSRExit(ExitKind kind, unsigned eventStreamIndex, CodeOrigin opCatchOrigin, HandlerInfo* exceptionHandler, CallSiteIndex callSite, MacroAssembler::JumpList jumpsToFail)
{
- OSRExit exit(Uncountable, JSValueRegs(), graph().methodOfGettingAValueProfileFor(nullptr), m_speculative.get(), eventStreamIndex);
- exit.m_willArriveAtOSRExitFromGenericUnwind = jumpsToFail.empty(); // If jumps are empty, we're going to jump here from genericUnwind from a child call frame.
- exit.m_isExceptionHandler = true;
+ OSRExit exit(kind, JSValueRegs(), graph().methodOfGettingAValueProfileFor(nullptr), m_speculative.get(), eventStreamIndex);
exit.m_codeOrigin = opCatchOrigin;
exit.m_exceptionHandlerCallSiteIndex = callSite;
OSRExitCompilationInfo& exitInfo = appendExitInfo(jumpsToFail);
@@ -582,7 +580,7 @@
unsigned streamIndex = m_speculative->m_outOfLineStreamIndex != UINT_MAX ? m_speculative->m_outOfLineStreamIndex : m_speculative->m_stream->size();
MacroAssembler::Jump hadException = emitNonPatchableExceptionCheck();
// We assume here that this is called after callOpeartion()/appendCall() is called.
- appendExceptionHandlingOSRExit(streamIndex, opCatchOrigin, exceptionHandler, m_jitCode->common.lastCallSite(), hadException);
+ appendExceptionHandlingOSRExit(ExceptionCheck, streamIndex, opCatchOrigin, exceptionHandler, m_jitCode->common.lastCallSite(), hadException);
} else
m_exceptionChecks.append(emitExceptionCheck());
}
@@ -594,7 +592,7 @@
bool willCatchException = m_graph.willCatchExceptionInMachineFrame(callSiteCodeOrigin, opCatchOrigin, exceptionHandler);
CallSiteIndex callSite = addCallSite(callSiteCodeOrigin);
if (willCatchException)
- appendExceptionHandlingOSRExit(eventStreamIndex, opCatchOrigin, exceptionHandler, callSite);
+ appendExceptionHandlingOSRExit(GenericUnwind, eventStreamIndex, opCatchOrigin, exceptionHandler, callSite);
return callSite;
}
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index 258dfa3..4476fe8 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -279,7 +279,7 @@
void linkOSRExits();
void disassemble(LinkBuffer&);
- void appendExceptionHandlingOSRExit(unsigned eventStreamIndex, CodeOrigin, HandlerInfo* exceptionHandler, CallSiteIndex, MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList());
+ void appendExceptionHandlingOSRExit(ExitKind, unsigned eventStreamIndex, CodeOrigin, HandlerInfo* exceptionHandler, CallSiteIndex, MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList());
// The dataflow graph currently being generated.
Graph& m_graph;
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
index 2e1e51c..b95d409 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
@@ -43,7 +43,6 @@
, m_patchableCodeOffset(0)
, m_recoveryIndex(recoveryIndex)
, m_streamIndex(streamIndex)
- , m_willArriveAtOSRExitFromGenericUnwind(false)
{
bool canExit = jit->m_origin.exitOK;
if (!canExit && jit->m_currentNode) {
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.h b/Source/JavaScriptCore/dfg/DFGOSRExit.h
index bde57aa..a14d54f 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.h
@@ -100,7 +100,6 @@
void correctJump(LinkBuffer&);
unsigned m_streamIndex;
- bool m_willArriveAtOSRExitFromGenericUnwind : 1;
void considerAddingAsFrequentExitSite(CodeBlock* profiledCodeBlock)
{
OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromDFG);
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitBase.h b/Source/JavaScriptCore/dfg/DFGOSRExitBase.h
index eafd9c7..78510c1 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitBase.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitBase.h
@@ -45,7 +45,6 @@
, m_count(0)
, m_codeOrigin(origin)
, m_codeOriginForExitProfile(originForProfile)
- , m_isExceptionHandler(false)
{
ASSERT(m_codeOrigin.isSet());
ASSERT(m_codeOriginForExitProfile.isSet());
@@ -58,7 +57,18 @@
CodeOrigin m_codeOriginForExitProfile;
CallSiteIndex m_exceptionHandlerCallSiteIndex;
- bool m_isExceptionHandler : 1;
+ ALWAYS_INLINE bool isExceptionHandler() const
+ {
+ return m_kind == ExceptionCheck || m_kind == GenericUnwind;
+ }
+
+ // True if this exit is used as an exception handler for unwinding. This happens to only be set when
+ // isExceptionHandler is true, but all this actually means is that the OSR exit will assume that the
+ // machine state is as it would be coming out of genericUnwind.
+ ALWAYS_INLINE bool isGenericUnwindHandler() const
+ {
+ return m_kind == GenericUnwind;
+ }
protected:
void considerAddingAsFrequentExitSite(CodeBlock* profiledCodeBlock, ExitingJITType jitType)
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
index 5f94132..1f3f98b 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
@@ -131,8 +131,8 @@
OSRExit& exit = codeBlock->jitCode()->dfg()->osrExit[exitIndex];
if (vm->callFrameForCatch)
- ASSERT(exit.m_willArriveAtOSRExitFromGenericUnwind);
- if (exit.m_isExceptionHandler)
+ ASSERT(exit.m_kind == GenericUnwind);
+ if (exit.isExceptionHandler())
ASSERT(!!vm->exception());
@@ -150,7 +150,7 @@
CCallHelpers jit(vm, codeBlock);
OSRExitCompiler exitCompiler(jit);
- if (exit.m_willArriveAtOSRExitFromGenericUnwind) {
+ if (exit.m_kind == GenericUnwind) {
// We are acting as a defacto op_catch because we arrive here from genericUnwind().
// So, we must restore our call frame and stack pointer.
jit.restoreCalleeSavesFromVMCalleeSavesBuffer();
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
index 01b8518..e419941 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
@@ -248,7 +248,7 @@
m_jit.emitRestoreCalleeSaves();
m_jit.emitSaveCalleeSavesFor(m_jit.baselineCodeBlock());
- if (exit.m_isExceptionHandler)
+ if (exit.isExceptionHandler())
m_jit.copyCalleeSavesToVMCalleeSavesBuffer();
// Do all data format conversions and store the results into the stack.
@@ -397,7 +397,7 @@
reifyInlinedCallFrames(m_jit, exit);
// And finish.
- adjustAndJumpToTarget(m_jit, exit, exit.m_isExceptionHandler);
+ adjustAndJumpToTarget(m_jit, exit);
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
index b223812..6999e5c 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
@@ -261,7 +261,7 @@
// The tag registers are needed to materialize recoveries below.
m_jit.emitMaterializeTagCheckRegisters();
- if (exit.m_isExceptionHandler)
+ if (exit.isExceptionHandler())
m_jit.copyCalleeSavesToVMCalleeSavesBuffer();
// Do all data format conversions and store the results into the stack.
@@ -387,7 +387,7 @@
reifyInlinedCallFrames(m_jit, exit);
// And finish.
- adjustAndJumpToTarget(m_jit, exit, exit.m_isExceptionHandler);
+ adjustAndJumpToTarget(m_jit, exit);
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
index e8479e8..f716e76 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
@@ -39,6 +39,9 @@
void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit)
{
jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count));
+
+ if (!exitKindMayJettison(exit.m_kind))
+ return;
jit.move(AssemblyHelpers::TrustedImmPtr(jit.codeBlock()), GPRInfo::regT0);
@@ -264,7 +267,7 @@
ownerIsRememberedOrInEden.link(&jit);
}
-void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit, bool isExitingToOpCatch)
+void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit)
{
jit.move(
AssemblyHelpers::TrustedImmPtr(
@@ -302,7 +305,7 @@
void* jumpTarget = codeBlockForExit->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset);
jit.addPtr(AssemblyHelpers::TrustedImm32(JIT::stackPointerOffsetFor(codeBlockForExit) * sizeof(Register)), GPRInfo::callFrameRegister, AssemblyHelpers::stackPointerRegister);
- if (isExitingToOpCatch) {
+ if (exit.isExceptionHandler()) {
// Since we're jumping to op_catch, we need to set callFrameForCatch.
jit.storePtr(GPRInfo::callFrameRegister, jit.vm()->addressOfCallFrameForCatch());
}
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h
index 6824bf0..bbb22e0 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h
@@ -39,7 +39,7 @@
void handleExitCounts(CCallHelpers&, const OSRExitBase&);
void reifyInlinedCallFrames(CCallHelpers&, const OSRExitBase&);
-void adjustAndJumpToTarget(CCallHelpers&, const OSRExitBase&, bool isExitingToOpCatch);
+void adjustAndJumpToTarget(CCallHelpers&, const OSRExitBase&);
template <typename JITCodeType>
void adjustFrameAndStackInOSRExitCompilerThunk(MacroAssembler& jit, VM* vm, JITCode::JITType jitType)
diff --git a/Source/JavaScriptCore/ftl/FTLCompile.cpp b/Source/JavaScriptCore/ftl/FTLCompile.cpp
index a790855..490e609 100644
--- a/Source/JavaScriptCore/ftl/FTLCompile.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCompile.cpp
@@ -492,7 +492,7 @@
}
OSRExitDescriptorImpl& exitDescriptorImpl = state.osrExitDescriptorImpls[i];
- if (exceptionTypeWillArriveAtOSRExitFromGenericUnwind(exitDescriptorImpl.m_exceptionType))
+ if (exitDescriptorImpl.m_kind == GenericUnwind)
genericUnwindOSRExitDescriptors.add(exitDescriptor, &exitDescriptorImpl);
for (unsigned j = exitDescriptor->m_values.size(); j--;)
@@ -503,7 +503,7 @@
for (unsigned j = 0; j < iter->value.size(); j++) {
{
uint32_t stackmapRecordIndex = iter->value[j].index;
- OSRExit exit(exitDescriptor, exitDescriptorImpl, stackmapRecordIndex);
+ OSRExit exit(exitDescriptor, exitDescriptorImpl.m_kind, exitDescriptorImpl, stackmapRecordIndex);
state.jitCode->osrExit.append(exit);
state.finalizer->osrExit.append(OSRExitCompilationInfo());
}
@@ -528,7 +528,7 @@
// 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, exitDescriptorImpl, stackmapRecordIndex);
+ OSRExit exit(exitDescriptor, ExceptionCheck, exitDescriptorImpl, stackmapRecordIndex);
if (exitDescriptorImpl.m_exceptionType == ExceptionType::GetById)
exit.m_exceptionType = ExceptionType::GetByIdCallOperation;
else
@@ -590,7 +590,7 @@
info.m_thunkAddress = linkBuffer->locationOf(info.m_thunkLabel);
exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
- if (exit.willArriveAtOSRExitFromGenericUnwind()) {
+ if (exit.isGenericUnwindHandler()) {
HandlerInfo newHandler = genericUnwindOSRExitDescriptors.get(exit.m_descriptor)->m_baselineExceptionHandler;
newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
diff --git a/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp b/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
index 0778268..d1bb2db 100644
--- a/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
@@ -49,7 +49,7 @@
void ExitThunkGenerator::emitThunk(unsigned index)
{
OSRExit& exit = m_state.jitCode->osrExit[index];
- ASSERT_UNUSED(exit, !(exit.willArriveAtOSRExitFromGenericUnwind() && exit.willArriveAtOSRExitFromCallOperation()));
+ ASSERT_UNUSED(exit, !(exit.isGenericUnwindHandler() && exit.willArriveAtOSRExitFromCallOperation()));
OSRExitCompilationInfo& info = m_state.finalizer->osrExit[index];
info.m_thunkLabel = label();
diff --git a/Source/JavaScriptCore/ftl/FTLJITCode.cpp b/Source/JavaScriptCore/ftl/FTLJITCode.cpp
index 13fb0e6..2c50b15 100644
--- a/Source/JavaScriptCore/ftl/FTLJITCode.cpp
+++ b/Source/JavaScriptCore/ftl/FTLJITCode.cpp
@@ -170,15 +170,15 @@
#if FTL_USES_B3
for (OSRExit& exit : osrExit) {
if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
- RELEASE_ASSERT(exit.m_isExceptionHandler);
- RELEASE_ASSERT(exit.m_isUnwindHandler);
+ RELEASE_ASSERT(exit.isExceptionHandler());
+ RELEASE_ASSERT(exit.isGenericUnwindHandler());
return ValueRep::usedRegisters(exit.m_valueReps);
}
}
#else // FTL_USES_B3
for (OSRExit& exit : osrExit) {
if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
- RELEASE_ASSERT(exit.m_isExceptionHandler);
+ RELEASE_ASSERT(exit.isExceptionHandler());
return stackmaps.records[exit.m_stackmapRecordIndex].usedRegisterSet();
}
}
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
index 5604840..412026a 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
@@ -10186,7 +10186,7 @@
bool exitOK = true;
bool isExceptionHandler = true;
appendOSRExit(
- Uncountable, noValue(), nullptr, hadException,
+ ExceptionCheck, noValue(), nullptr, hadException,
m_origin.withForExitAndExitOK(opCatchOrigin, exitOK), isExceptionHandler);
return;
}
@@ -10244,7 +10244,22 @@
if (!willCatchException)
return;
- appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
+ ExitKind exitKind;
+ switch (exceptionType) {
+ case ExceptionType::JSCall:
+ case ExceptionType::GetById:
+ case ExceptionType::PutById:
+ exitKind = GenericUnwind;
+ break;
+ case ExceptionType::LazySlowPath:
+ case ExceptionType::BinaryOpGenerator:
+ exitKind = ExceptionCheck;
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ appendOSRExitDescriptor(exitKind, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
OSRExitDescriptor* exitDescriptor = &m_ftlState.jitCode->osrExitDescriptors.last();
exitDescriptor->m_stackmapID = m_stackmapIDs - 1;
@@ -10320,7 +10335,7 @@
#if FTL_USES_B3
blessSpeculation(
- m_out.speculate(failCondition), kind, lowValue, highValue, origin, isExceptionHandler);
+ m_out.speculate(failCondition), kind, lowValue, highValue, origin);
#else // FTL_USES_B3
OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
@@ -10348,7 +10363,7 @@
}
#if FTL_USES_B3
- void blessSpeculation(CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
+ void blessSpeculation(CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
{
OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(lowValue, highValue);
@@ -10358,7 +10373,7 @@
value->setGenerator(
[=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
exitDescriptor->emitOSRExit(
- *state, kind, origin, jit, params, 0, isExceptionHandler);
+ *state, kind, origin, jit, params, 0);
});
}
#endif
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExit.cpp b/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
index 59e1f44..ffbb637 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
@@ -69,20 +69,20 @@
#if FTL_USES_B3
RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExit(
State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin, CCallHelpers& jit,
- const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
+ const StackmapGenerationParams& params, unsigned offset)
{
RefPtr<OSRExitHandle> handle =
- prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset, isExceptionHandler);
+ prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset);
handle->emitExitThunk(state, jit);
return handle;
}
RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExitLater(
State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin,
- const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
+ const StackmapGenerationParams& params, unsigned offset)
{
RefPtr<OSRExitHandle> handle =
- prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset, isExceptionHandler);
+ prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset);
params.addLatePath(
[handle, &state] (CCallHelpers& jit) {
handle->emitExitThunk(state, jit);
@@ -92,11 +92,11 @@
RefPtr<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin,
- const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
+ const StackmapGenerationParams& params, unsigned offset)
{
unsigned index = state.jitCode->osrExit.size();
OSRExit& exit = state.jitCode->osrExit.alloc(
- this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic, isExceptionHandler);
+ this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic);
RefPtr<OSRExitHandle> handle = adoptRef(new OSRExitHandle(index, exit));
for (unsigned i = offset; i < params.size(); ++i)
exit.m_valueReps.append(params[i]);
@@ -108,23 +108,20 @@
#if FTL_USES_B3
OSRExit::OSRExit(
OSRExitDescriptor* descriptor,
- ExitKind exitKind, CodeOrigin codeOrigin, CodeOrigin codeOriginForExitProfile,
- bool isExceptionHandler)
+ ExitKind exitKind, CodeOrigin codeOrigin, CodeOrigin codeOriginForExitProfile)
: OSRExitBase(exitKind, codeOrigin, codeOriginForExitProfile)
, m_descriptor(descriptor)
{
- m_isExceptionHandler = isExceptionHandler;
}
#else // FTL_USES_B3
OSRExit::OSRExit(
- OSRExitDescriptor* descriptor, OSRExitDescriptorImpl& exitDescriptorImpl,
+ OSRExitDescriptor* descriptor, ExitKind exitKind, OSRExitDescriptorImpl& exitDescriptorImpl,
uint32_t stackmapRecordIndex)
- : OSRExitBase(exitDescriptorImpl.m_kind, exitDescriptorImpl.m_codeOrigin, exitDescriptorImpl.m_codeOriginForExitProfile)
+ : OSRExitBase(exitKind, exitDescriptorImpl.m_codeOrigin, exitDescriptorImpl.m_codeOriginForExitProfile)
, m_descriptor(descriptor)
, m_stackmapRecordIndex(stackmapRecordIndex)
, m_exceptionType(exitDescriptorImpl.m_exceptionType)
{
- m_isExceptionHandler = exitDescriptorImpl.m_exceptionType != ExceptionType::None;
}
#endif // FTL_USES_B3
@@ -178,7 +175,7 @@
void OSRExit::spillRegistersToSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
{
- RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
+ RELEASE_ASSERT(isGenericUnwindHandler() || willArriveAtOSRExitFromCallOperation());
unsigned count = 0;
for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
if (registersToPreserveForCallThatMightThrow.get(reg)) {
@@ -196,7 +193,7 @@
void OSRExit::recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
{
- RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
+ RELEASE_ASSERT(isGenericUnwindHandler() || willArriveAtOSRExitFromCallOperation());
unsigned count = 0;
for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
if (registersToPreserveForCallThatMightThrow.get(reg)) {
@@ -229,24 +226,6 @@
RELEASE_ASSERT_NOT_REACHED();
}
-bool exceptionTypeWillArriveAtOSRExitFromGenericUnwind(ExceptionType exceptionType)
-{
- switch (exceptionType) {
- case ExceptionType::JSCall:
- case ExceptionType::GetById:
- case ExceptionType::PutById:
- return true;
- default:
- return false;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-bool OSRExit::willArriveAtOSRExitFromGenericUnwind() const
-{
- return exceptionTypeWillArriveAtOSRExitFromGenericUnwind(m_exceptionType);
-}
-
bool OSRExit::willArriveAtOSRExitFromCallOperation() const
{
switch (m_exceptionType) {
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExit.h b/Source/JavaScriptCore/ftl/FTLOSRExit.h
index b45aa0c..bb05d08 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExit.h
+++ b/Source/JavaScriptCore/ftl/FTLOSRExit.h
@@ -80,8 +80,6 @@
LazySlowPath,
BinaryOpGenerator,
};
-
-bool exceptionTypeWillArriveAtOSRExitFromGenericUnwind(ExceptionType);
#endif // !FTL_USES_B3
struct OSRExitDescriptor {
@@ -116,7 +114,7 @@
// this call, the OSRExit is simply ready to go.
RefPtr<OSRExitHandle> emitOSRExit(
State&, ExitKind, const DFG::NodeOrigin&, CCallHelpers&, const B3::StackmapGenerationParams&,
- unsigned offset = 0, bool isExceptionHandler = false);
+ unsigned offset = 0);
// In some cases you want an OSRExit to come into existence, but you don't want to emit it right now.
// This will emit the OSR exit in a late path. You can't be sure exactly when that will happen, but
@@ -128,14 +126,15 @@
// eventually gets access to its label.
RefPtr<OSRExitHandle> emitOSRExitLater(
State&, ExitKind, const DFG::NodeOrigin&, const B3::StackmapGenerationParams&,
- unsigned offset = 0, bool isExceptionHandler = false);
+ unsigned offset = 0);
+private:
// This is the low-level interface. It will create a handle representing the desire to emit code for
// an OSR exit. You can call OSRExitHandle::emitExitThunk() once you have a place to emit it. Note
// that the above two APIs are written in terms of this and OSRExitHandle::emitExitThunk().
RefPtr<OSRExitHandle> prepareOSRExitHandle(
State&, ExitKind, const DFG::NodeOrigin&, const B3::StackmapGenerationParams&,
- unsigned offset = 0, bool isExceptionHandler = false);
+ unsigned offset = 0);
#endif // FTL_USES_B3
};
@@ -160,9 +159,9 @@
struct OSRExit : public DFG::OSRExitBase {
OSRExit(
- OSRExitDescriptor*,
+ OSRExitDescriptor*, ExitKind,
#if FTL_USES_B3
- ExitKind, CodeOrigin, CodeOrigin codeOriginForExitProfile, bool isExceptionHandler
+ CodeOrigin, CodeOrigin codeOriginForExitProfile
#else // FTL_USES_B3
OSRExitDescriptorImpl&, uint32_t stackmapRecordIndex
#endif // FTL_USES_B3
@@ -174,10 +173,6 @@
// This tells us where to place a jump.
CodeLocationJump m_patchableJump;
Vector<B3::ValueRep> m_valueReps;
- // True if this exit is used as an exception handler for unwinding. This happens to only be set when
- // isExceptionHandler is true, but all this actually means is that the OSR exit will assume that the
- // machine state is as it would be coming out of genericUnwind.
- bool m_isUnwindHandler { false };
#else // FTL_USES_B3
// Offset within the exit stubs of the stub for this exit.
unsigned m_patchableCodeOffset;
@@ -198,7 +193,6 @@
void spillRegistersToSpillSlot(CCallHelpers&, int32_t stackSpillSlot);
void recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot);
- bool willArriveAtOSRExitFromGenericUnwind() const;
bool willArriveAtExitFromIndirectExceptionCheck() const;
bool willArriveAtOSRExitFromCallOperation() const;
bool needsRegisterRecoveryOnGenericUnwindOSRExitPath() const;
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
index 8c9194c..0bbae18 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
@@ -207,13 +207,7 @@
CCallHelpers jit(vm, codeBlock);
// The first thing we need to do is restablish our frame in the case of an exception.
- if (
-#if FTL_USES_B3
- exit.m_isUnwindHandler
-#else // FTL_USES_B3
- exit.willArriveAtOSRExitFromGenericUnwind()
-#endif // FTL_USES_B3
- ) {
+ if (exit.isGenericUnwindHandler()) {
RELEASE_ASSERT(vm->callFrameForCatch); // The first time we hit this exit, like at all other times, this field should be non-null.
jit.restoreCalleeSavesFromVMCalleeSavesBuffer();
jit.loadPtr(vm->addressOfCallFrameForCatch(), MacroAssembler::framePointerRegister);
@@ -488,19 +482,19 @@
RegisterAtOffsetList* baselineCalleeSaves = baselineCodeBlock->calleeSaveRegisters();
RegisterAtOffsetList* vmCalleeSaves = vm->getAllCalleeSaveRegisterOffsets();
RegisterSet vmCalleeSavesToSkip = RegisterSet::stackRegisters();
- if (exit.m_isExceptionHandler)
+ if (exit.isExceptionHandler())
jit.move(CCallHelpers::TrustedImmPtr(vm->calleeSaveRegistersBuffer), GPRInfo::regT1);
for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
if (!allFTLCalleeSaves.get(reg)) {
- if (exit.m_isExceptionHandler)
+ if (exit.isExceptionHandler())
RELEASE_ASSERT(!vmCalleeSaves->find(reg));
continue;
}
unsigned unwindIndex = codeBlock->calleeSaveRegisters()->indexOf(reg);
RegisterAtOffset* baselineRegisterOffset = baselineCalleeSaves->find(reg);
RegisterAtOffset* vmCalleeSave = nullptr;
- if (exit.m_isExceptionHandler)
+ if (exit.isExceptionHandler())
vmCalleeSave = vmCalleeSaves->find(reg);
if (reg.isGPR()) {
@@ -540,7 +534,7 @@
}
}
- if (exit.m_isExceptionHandler) {
+ if (exit.isExceptionHandler()) {
RegisterAtOffset* vmCalleeSave = vmCalleeSaves->find(GPRInfo::tagTypeNumberRegister);
jit.store64(GPRInfo::tagTypeNumberRegister, MacroAssembler::Address(GPRInfo::regT1, vmCalleeSave->offset()));
@@ -564,7 +558,7 @@
handleExitCounts(jit, exit);
reifyInlinedCallFrames(jit, exit);
- adjustAndJumpToTarget(jit, exit, exit.m_isExceptionHandler);
+ adjustAndJumpToTarget(jit, exit);
LinkBuffer patchBuffer(*vm, jit, codeBlock);
#if FTL_USES_B3
@@ -622,13 +616,11 @@
dataLog(" Exit stackmap ID: ", exit.m_descriptor->m_stackmapID, "\n");
#endif // !FTL_USES_B3
dataLog(" Current call site index: ", exec->callSiteIndex().bits(), "\n");
- dataLog(" Exit is exception handler: ", exit.m_isExceptionHandler, "\n");
-#if FTL_USES_B3
- dataLog(" Is unwind handler: ", exit.m_isUnwindHandler, "\n");
-#else // FTL_USES_B3
- dataLog(" Will arrive at exit from genericUnwind(): ", exit.willArriveAtOSRExitFromGenericUnwind(), "\n");
+ dataLog(" Exit is exception handler: ", exit.isExceptionHandler(), "\n");
+ dataLog(" Is unwind handler: ", exit.isGenericUnwindHandler(), "\n");
+#if !FTL_USES_B3
dataLog(" Will arrive at exit from lazy slow path: ", exit.m_exceptionType == ExceptionType::LazySlowPath, "\n");
-#endif // FTL_USES_B3
+#endif // !FTL_USES_B3
dataLog(" Exit values: ", exit.m_descriptor->m_values, "\n");
#if FTL_USES_B3
dataLog(" Value reps: ", listDump(exit.m_valueReps), "\n");
diff --git a/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp b/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp
index 4ca014e..a3033cc 100644
--- a/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp
+++ b/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.cpp
@@ -69,7 +69,7 @@
new ExceptionTarget(isDefaultHandler, m_state.exceptionHandler, nullptr));
}
bool isDefaultHandler = false;
- return adoptRef(new ExceptionTarget(isDefaultHandler, { }, createHandle(params)));
+ return adoptRef(new ExceptionTarget(isDefaultHandler, { }, createHandle(ExceptionCheck, params)));
}
void PatchpointExceptionHandle::scheduleExitCreationForUnwind(
@@ -78,9 +78,8 @@
if (!m_descriptor)
return;
- RefPtr<OSRExitHandle> handle = createHandle(params);
+ RefPtr<OSRExitHandle> handle = createHandle(GenericUnwind, params);
- handle->exit.m_isUnwindHandler = true;
handle->exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
HandlerInfo handler = m_handler;
@@ -110,11 +109,10 @@
}
RefPtr<OSRExitHandle> PatchpointExceptionHandle::createHandle(
- const B3::StackmapGenerationParams& params)
+ ExitKind kind, const B3::StackmapGenerationParams& params)
{
- bool isExceptionHandler = true;
return m_descriptor->emitOSRExitLater(
- m_state, Uncountable, m_origin, params, m_offset, isExceptionHandler);
+ m_state, kind, m_origin, params, m_offset);
}
} } // namespace JSC::FTL
diff --git a/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h b/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h
index f9f0aef..75a03a0 100644
--- a/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h
+++ b/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h
@@ -31,6 +31,7 @@
#if ENABLE(FTL_JIT) && FTL_USES_B3
#include "DFGNodeOrigin.h"
+#include "ExitKind.h"
#include "HandlerInfo.h"
#include <wtf/Ref.h>
#include <wtf/ThreadSafeRefCounted.h>
@@ -88,7 +89,7 @@
PatchpointExceptionHandle(
State&, OSRExitDescriptor*, DFG::NodeOrigin, unsigned offset, const HandlerInfo&);
- RefPtr<OSRExitHandle> createHandle(const B3::StackmapGenerationParams&);
+ RefPtr<OSRExitHandle> createHandle(ExitKind, const B3::StackmapGenerationParams&);
State& m_state;
OSRExitDescriptor* m_descriptor;