FTL B3 should be able to make JS->JS calls
https://bugs.webkit.org/show_bug.cgi?id=151901

Reviewed by Saam Barati.

This adds support for the Call and InvalidationPoint opcodes in DFG IR. This required doing some
clean-up in the OSR exit code. We don't want the B3 FTL to use a bunch of vectors to hold
side-state, so the use of OSRExitDescriptorImpl is not right. It makes sense in the LLVM FTL
because that code needs some way of saving some state from LowerDFGToLLVM to compile(), but
that's not how B3 FTL works. It turns out that for B3 FTL, there isn't anything in
OSRExitDescriptorImpl that the code in LowerDFGToLLVM can't just capture in a lambda.

This also simplifies some stackmap-related APIs, since I got tired of writing boilerplate.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::replaceWithAddressComputation):
(JSC::AbstractMacroAssembler::addLinkTask):
* b3/B3CheckSpecial.cpp:
(JSC::B3::CheckSpecial::generate):
* b3/B3Effects.h:
* b3/B3PatchpointSpecial.cpp:
(JSC::B3::PatchpointSpecial::generate):
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::addDataSection):
(JSC::B3::Procedure::callArgAreaSize):
(JSC::B3::Procedure::requestCallArgAreaSize):
(JSC::B3::Procedure::frameSize):
* b3/B3Procedure.h:
(JSC::B3::Procedure::releaseByproducts):
(JSC::B3::Procedure::code):
* b3/B3StackmapGenerationParams.cpp: Added.
(JSC::B3::StackmapGenerationParams::usedRegisters):
(JSC::B3::StackmapGenerationParams::proc):
(JSC::B3::StackmapGenerationParams::StackmapGenerationParams):
* b3/B3StackmapGenerationParams.h: Added.
(JSC::B3::StackmapGenerationParams::value):
(JSC::B3::StackmapGenerationParams::reps):
(JSC::B3::StackmapGenerationParams::size):
(JSC::B3::StackmapGenerationParams::at):
(JSC::B3::StackmapGenerationParams::operator[]):
(JSC::B3::StackmapGenerationParams::begin):
(JSC::B3::StackmapGenerationParams::end):
(JSC::B3::StackmapGenerationParams::context):
(JSC::B3::StackmapGenerationParams::addLatePath):
* b3/B3StackmapValue.h:
* b3/B3ValueRep.h:
(JSC::B3::ValueRep::doubleValue):
(JSC::B3::ValueRep::withOffset):
* b3/air/AirGenerationContext.h:
* b3/testb3.cpp:
(JSC::B3::testSimplePatchpoint):
(JSC::B3::testSimplePatchpointWithoutOuputClobbersGPArgs):
(JSC::B3::testSimplePatchpointWithOuputClobbersGPArgs):
(JSC::B3::testSimplePatchpointWithoutOuputClobbersFPArgs):
(JSC::B3::testSimplePatchpointWithOuputClobbersFPArgs):
(JSC::B3::testPatchpointWithEarlyClobber):
(JSC::B3::testPatchpointCallArg):
(JSC::B3::testPatchpointFixedRegister):
(JSC::B3::testPatchpointAny):
(JSC::B3::testPatchpointLotsOfLateAnys):
(JSC::B3::testPatchpointAnyImm):
(JSC::B3::testPatchpointManyImms):
(JSC::B3::testPatchpointWithRegisterResult):
(JSC::B3::testPatchpointWithStackArgumentResult):
(JSC::B3::testPatchpointWithAnyResult):
(JSC::B3::testSimpleCheck):
(JSC::B3::testCheckLessThan):
(JSC::B3::testCheckMegaCombo):
(JSC::B3::testCheckAddImm):
(JSC::B3::testCheckAddImmCommute):
(JSC::B3::testCheckAddImmSomeRegister):
(JSC::B3::testCheckAdd):
(JSC::B3::testCheckAdd64):
(JSC::B3::testCheckSubImm):
(JSC::B3::testCheckSubBadImm):
(JSC::B3::testCheckSub):
(JSC::B3::testCheckSub64):
(JSC::B3::testCheckNeg):
(JSC::B3::testCheckNeg64):
(JSC::B3::testCheckMul):
(JSC::B3::testCheckMulMemory):
(JSC::B3::testCheckMul2):
(JSC::B3::testCheckMul64):
(JSC::B3::genericTestCompare):
* ftl/FTLExceptionHandlerManager.cpp:
* ftl/FTLExceptionHandlerManager.h:
* ftl/FTLJSCall.cpp:
* ftl/FTLJSCall.h:
* ftl/FTLJSCallBase.cpp:
(JSC::FTL::JSCallBase::emit):
* ftl/FTLJSCallBase.h:
* ftl/FTLJSCallVarargs.cpp:
* ftl/FTLJSCallVarargs.h:
* ftl/FTLJSTailCall.cpp:
(JSC::FTL::DFG::getRegisterWithAddend):
(JSC::FTL::JSTailCall::emit):
(JSC::FTL::JSTailCall::JSTailCall): Deleted.
* ftl/FTLJSTailCall.h:
(JSC::FTL::JSTailCall::stackmapID):
(JSC::FTL::JSTailCall::estimatedSize):
(JSC::FTL::JSTailCall::operator<):
(JSC::FTL::JSTailCall::patchpoint): Deleted.
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):
(JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
(JSC::FTL::DFG::LowerDFGToLLVM::lazySlowPath):
(JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
(JSC::FTL::DFG::LowerDFGToLLVM::emitBranchToOSRExitIfWillCatchException):
(JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitDescriptor):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
(JSC::FTL::DFG::LowerDFGToLLVM::emitOSRExitCall):
(JSC::FTL::DFG::LowerDFGToLLVM::buildExitArguments):
(JSC::FTL::DFG::LowerDFGToLLVM::exitValueForNode):
* ftl/FTLOSRExit.cpp:
(JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
(JSC::FTL::OSRExitDescriptor::emitOSRExit):
(JSC::FTL::OSRExitDescriptor::emitOSRExitLater):
(JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
(JSC::FTL::OSRExit::OSRExit):
(JSC::FTL::OSRExit::codeLocationForRepatch):
(JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
(JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
(JSC::FTL::OSRExit::needsRegisterRecoveryOnGenericUnwindOSRExitPath):
* ftl/FTLOSRExit.h:
(JSC::FTL::OSRExitDescriptorImpl::OSRExitDescriptorImpl):
(JSC::FTL::OSRExit::considerAddingAsFrequentExitSite):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
(JSC::FTL::compileFTLOSRExit):
* ftl/FTLState.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@193640 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExit.cpp b/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
index 0284d8c..9327f86 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOSRExit.cpp
@@ -29,6 +29,7 @@
 #if ENABLE(FTL_JIT)
 
 #include "AirGenerationContext.h"
+#include "B3StackmapGenerationParams.h"
 #include "B3StackmapValue.h"
 #include "CodeBlock.h"
 #include "DFGBasicBlock.h"
@@ -50,7 +51,9 @@
     : m_profileDataFormat(profileDataFormat)
     , m_valueProfile(valueProfile)
     , m_values(numberOfArguments, numberOfLocals)
+#if !FTL_USES_B3
     , m_isInvalidationPoint(false)
+#endif // !FTL_USES_B3
 {
 }
 
@@ -65,53 +68,65 @@
 
 #if FTL_USES_B3
 RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExit(
-    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, CCallHelpers& jit, const StackmapGenerationParams& params, unsigned offset)
+    State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin, CCallHelpers& jit,
+    const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
 {
-    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, exitDescriptorImpl, params, offset);
+    RefPtr<OSRExitHandle> handle =
+        prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset, isExceptionHandler);
     handle->emitExitThunk(jit);
     return handle;
 }
 
 RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExitLater(
-    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, const StackmapGenerationParams& params, unsigned offset)
+    State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin,
+    const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
 {
-    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, exitDescriptorImpl, params, offset);
-    params.context->latePaths.append(
-        createSharedTask<Air::GenerationContext::LatePathFunction>(
-            [handle] (CCallHelpers& jit, Air::GenerationContext&) {
-                handle->emitExitThunk(jit);
-            }));
+    RefPtr<OSRExitHandle> handle =
+        prepareOSRExitHandle(state, exitKind, nodeOrigin, params, offset, isExceptionHandler);
+    params.addLatePath(
+        [handle] (CCallHelpers& jit) {
+            handle->emitExitThunk(jit);
+        });
     return handle;
 }
 
 RefPtr<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
-    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, const StackmapGenerationParams& params, unsigned offset)
+    State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin,
+    const StackmapGenerationParams& params, unsigned offset, bool isExceptionHandler)
 {
     unsigned index = state.jitCode->osrExit.size();
-    RefPtr<OSRExitHandle> handle = adoptRef(
-        new OSRExitHandle(index, state.jitCode->osrExit.alloc(this, *exitDescriptorImpl)));
-    for (unsigned i = offset; i < params.reps.size(); ++i)
-        handle->exit.m_valueReps.append(params.reps[i]);
-    handle->exit.m_valueReps.shrinkToFit();
+    OSRExit& exit = state.jitCode->osrExit.alloc(
+        this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic, isExceptionHandler);
+    RefPtr<OSRExitHandle> handle = adoptRef(new OSRExitHandle(index, exit));
+    for (unsigned i = offset; i < params.size(); ++i)
+        exit.m_valueReps.append(params[i]);
+    exit.m_valueReps.shrinkToFit();
     return handle;
 }
 #endif // FTL_USES_B3
 
+#if FTL_USES_B3
 OSRExit::OSRExit(
-    OSRExitDescriptor* descriptor, OSRExitDescriptorImpl& exitDescriptorImpl
-#if !FTL_USES_B3
-    , uint32_t stackmapRecordIndex
-#endif // !FTL_USES_B3
-    )
+    OSRExitDescriptor* descriptor,
+    ExitKind exitKind, CodeOrigin codeOrigin, CodeOrigin codeOriginForExitProfile,
+    bool isExceptionHandler)
+    : OSRExitBase(exitKind, codeOrigin, codeOriginForExitProfile)
+    , m_descriptor(descriptor)
+{
+    m_isExceptionHandler = isExceptionHandler;
+}
+#else // FTL_USES_B3
+OSRExit::OSRExit(
+    OSRExitDescriptor* descriptor, OSRExitDescriptorImpl& exitDescriptorImpl,
+    uint32_t stackmapRecordIndex)
     : OSRExitBase(exitDescriptorImpl.m_kind, exitDescriptorImpl.m_codeOrigin, exitDescriptorImpl.m_codeOriginForExitProfile)
     , m_descriptor(descriptor)
-#if !FTL_USES_B3
     , m_stackmapRecordIndex(stackmapRecordIndex)
-#endif // !FTL_USES_B3
     , m_exceptionType(exitDescriptorImpl.m_exceptionType)
 {
     m_isExceptionHandler = exitDescriptorImpl.m_exceptionType != ExceptionType::None;
 }
+#endif // FTL_USES_B3
 
 CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const
 {
@@ -196,7 +211,6 @@
         }
     }
 }
-#endif // !FTL_USES_B3
 
 bool OSRExit::willArriveAtExitFromIndirectExceptionCheck() const
 {
@@ -260,6 +274,7 @@
     // recover the spilled registers.
     return m_exceptionType == ExceptionType::JSCall;
 }
+#endif // !FTL_USES_B3
 
 } } // namespace JSC::FTL