FTL lazy slow paths should work with B3
https://bugs.webkit.org/show_bug.cgi?id=151667
Reviewed by Geoffrey Garen.
This adds all of the glue necessary to make FTL::LazySlowPath work with B3. The B3 approach
allows us to put all of the code in FTL::LowerDFGToLLVM, instead of having supporting data
structures on the side and a bunch of complex code in FTLCompile.cpp.
* b3/B3CheckSpecial.cpp:
(JSC::B3::CheckSpecial::generate):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::run):
* b3/B3PatchpointSpecial.cpp:
(JSC::B3::PatchpointSpecial::generate):
* b3/B3StackmapValue.h:
* ftl/FTLJSTailCall.cpp:
(JSC::FTL::DFG::recoveryFor):
(JSC::FTL::JSTailCall::emit):
* ftl/FTLLazySlowPath.cpp:
(JSC::FTL::LazySlowPath::LazySlowPath):
(JSC::FTL::LazySlowPath::generate):
* ftl/FTLLazySlowPath.h:
(JSC::FTL::LazySlowPath::createGenerator):
(JSC::FTL::LazySlowPath::patchableJump):
(JSC::FTL::LazySlowPath::done):
(JSC::FTL::LazySlowPath::patchpoint):
(JSC::FTL::LazySlowPath::usedRegisters):
(JSC::FTL::LazySlowPath::callSiteIndex):
(JSC::FTL::LazySlowPath::stub):
* ftl/FTLLocation.cpp:
(JSC::FTL::Location::forValueRep):
(JSC::FTL::Location::forStackmaps):
(JSC::FTL::Location::dump):
(JSC::FTL::Location::isGPR):
(JSC::FTL::Location::gpr):
(JSC::FTL::Location::isFPR):
(JSC::FTL::Location::fpr):
(JSC::FTL::Location::restoreInto):
* ftl/FTLLocation.h:
(JSC::FTL::Location::Location):
(JSC::FTL::Location::forRegister):
(JSC::FTL::Location::forIndirect):
(JSC::FTL::Location::forConstant):
(JSC::FTL::Location::kind):
(JSC::FTL::Location::hasReg):
(JSC::FTL::Location::reg):
(JSC::FTL::Location::hasOffset):
(JSC::FTL::Location::offset):
(JSC::FTL::Location::hash):
(JSC::FTL::Location::hasDwarfRegNum): Deleted.
(JSC::FTL::Location::dwarfRegNum): Deleted.
(JSC::FTL::Location::hasDwarfReg): Deleted.
(JSC::FTL::Location::dwarfReg): Deleted.
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::LowerDFGToLLVM):
(JSC::FTL::DFG::LowerDFGToLLVM::lazySlowPath):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::stubUnavailableRegisters):
(JSC::RegisterSet::macroScratchRegisters):
(JSC::RegisterSet::calleeSaveRegisters):
* jit/RegisterSet.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@192856 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
index 3ef2c55..4adc1aa 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
@@ -28,6 +28,8 @@
#if ENABLE(FTL_JIT)
+#include "AirGenerationContext.h"
+#include "AllowMacroScratchRegisterUsage.h"
#include "CodeBlockWithJITType.h"
#include "DFGAbstractInterpreterInlines.h"
#include "DFGDominators.h"
@@ -100,6 +102,7 @@
} while (false)
class LowerDFGToLLVM {
+ WTF_MAKE_NONCOPYABLE(LowerDFGToLLVM);
public:
LowerDFGToLLVM(State& state)
: m_graph(state.graph)
@@ -7835,14 +7838,78 @@
LValue lazySlowPath(const Functor& functor, const Vector<LValue>& userArguments)
{
#if FTL_USES_B3
- UNUSED_PARAM(functor);
-
+ CodeOrigin origin = m_node->origin.semantic;
+
B3::PatchpointValue* result = m_out.patchpoint(B3::Int64);
for (LValue arg : userArguments)
- result->append(ConstrainedValue(arg, ValueRep::SomeRegister));
+ result->append(ConstrainedValue(arg, B3::ValueRep::SomeRegister));
+
+ // FIXME: As part of handling exceptions, we need to append OSR exit state here.
+
+ result->clobber(RegisterSet::macroScratchRegisters());
+ State* state = &m_ftlState;
+
result->setGenerator(
- [&] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
- jit.oops();
+ [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ Vector<Location> locations;
+ for (const B3::ValueRep& rep : params.reps)
+ locations.append(Location::forValueRep(rep));
+
+ RefPtr<LazySlowPath::Generator> generator = functor(locations);
+
+ CCallHelpers::PatchableJump patchableJump = jit.patchableJump();
+ CCallHelpers::Label done = jit.label();
+
+ RegisterSet usedRegisters = params.usedRegisters;
+
+ // FIXME: As part of handling exceptions, we need to create a concrete OSRExit here.
+ // Doing so should automagically register late paths that emit exit thunks.
+
+ params.context->latePaths.append(
+ createSharedTask<Air::GenerationContext::LatePathFunction>(
+ [=] (CCallHelpers& jit, Air::GenerationContext&) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+ patchableJump.m_jump.link(&jit);
+ unsigned index = state->jitCode->lazySlowPaths.size();
+ state->jitCode->lazySlowPaths.append(nullptr);
+ jit.pushToSaveImmediateWithoutTouchingRegisters(
+ CCallHelpers::TrustedImm32(index));
+ CCallHelpers::Jump generatorJump = jit.jump();
+
+ // Note that so long as we're here, we don't really know if our late path
+ // runs before or after any other late paths that we might depend on, like
+ // the exception thunk.
+
+ RefPtr<JITCode> jitCode = state->jitCode;
+ VM* vm = &state->graph.m_vm;
+
+ jit.addLinkTask(
+ [=] (LinkBuffer& linkBuffer) {
+ linkBuffer.link(
+ generatorJump, CodeLocationLabel(
+ vm->getCTIStub(
+ lazySlowPathGenerationThunkGenerator).code()));
+
+ CodeLocationJump linkedPatchableJump = CodeLocationJump(
+ linkBuffer.locationOf(patchableJump));
+ CodeLocationLabel linkedDone = linkBuffer.locationOf(done);
+
+ // FIXME: Need a story for exceptions in FTL-B3. That basically means
+ // doing a lookup of the exception entrypoint here. We will have an
+ // OSR exit data structure of some sort.
+ // https://bugs.webkit.org/show_bug.cgi?id=151686
+ CodeLocationLabel exceptionTarget;
+ CallSiteIndex callSiteIndex =
+ jitCode->common.addUniqueCallSiteIndex(origin);
+
+ std::unique_ptr<LazySlowPath> lazySlowPath =
+ std::make_unique<LazySlowPath>(
+ linkedPatchableJump, linkedDone, exceptionTarget,
+ usedRegisters, callSiteIndex, generator);
+
+ jitCode->lazySlowPaths[index] = WTF::move(lazySlowPath);
+ });
+ }));
});
return result;
#else