FTL::OSRExitDescriptor should use less memory by having a companion object that dies...
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Dec 2015 21:09:41 +0000 (21:09 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Dec 2015 21:09:41 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=151795

Reviewed by Geoffrey Garen.

There were a few fields on FTL::OSRExitDescriptor that are only
needed during compilation. This patch introduces OSRExitDescriptorImpl
which is a struct that we create for each OSRExitDescriptor. The difference is
that OSRExitDescriptorImpl lives off of FTL::State so it dies after we compile.
This way no unnecessary fields persist after the compilation.

* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLExceptionHandlerManager.cpp:
(JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
(JSC::FTL::ExceptionHandlerManager::getCallOSRExitCommon):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
(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):
* ftl/FTLOSRExit.cpp:
(JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
(JSC::FTL::OSRExitDescriptor::validateReferences):
(JSC::FTL::OSRExitDescriptor::emitOSRExit):
(JSC::FTL::OSRExitDescriptor::emitOSRExitLater):
(JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
(JSC::FTL::OSRExit::OSRExit):
(JSC::FTL::OSRExit::codeLocationForRepatch):
(JSC::FTL::OSRExit::gatherRegistersToSpillForCallIfException):
(JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
(JSC::FTL::exceptionTypeWillArriveAtOSRExitFromGenericUnwind):
(JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind):
(JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
(JSC::FTL::OSRExitDescriptor::isExceptionHandler): Deleted.
* ftl/FTLOSRExit.h:
(JSC::FTL::OSRExitDescriptorImpl::OSRExitDescriptorImpl):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileFTLOSRExit):
* ftl/FTLState.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@193371 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/ftl/FTLCompile.cpp
Source/JavaScriptCore/ftl/FTLExceptionHandlerManager.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLOSRExit.cpp
Source/JavaScriptCore/ftl/FTLOSRExit.h
Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
Source/JavaScriptCore/ftl/FTLState.h

index f72c085..1620bb2 100644 (file)
@@ -1,3 +1,49 @@
+2015-12-03  Saam barati  <sbarati@apple.com>
+
+        FTL::OSRExitDescriptor should use less memory by having a companion object that dies after compilation
+        https://bugs.webkit.org/show_bug.cgi?id=151795
+
+        Reviewed by Geoffrey Garen.
+
+        There were a few fields on FTL::OSRExitDescriptor that are only
+        needed during compilation. This patch introduces OSRExitDescriptorImpl 
+        which is a struct that we create for each OSRExitDescriptor. The difference is 
+        that OSRExitDescriptorImpl lives off of FTL::State so it dies after we compile.
+        This way no unnecessary fields persist after the compilation.
+
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::mmAllocateDataSection):
+        * ftl/FTLExceptionHandlerManager.cpp:
+        (JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
+        (JSC::FTL::ExceptionHandlerManager::getCallOSRExitCommon):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
+        (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):
+        * ftl/FTLOSRExit.cpp:
+        (JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
+        (JSC::FTL::OSRExitDescriptor::validateReferences):
+        (JSC::FTL::OSRExitDescriptor::emitOSRExit):
+        (JSC::FTL::OSRExitDescriptor::emitOSRExitLater):
+        (JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
+        (JSC::FTL::OSRExit::OSRExit):
+        (JSC::FTL::OSRExit::codeLocationForRepatch):
+        (JSC::FTL::OSRExit::gatherRegistersToSpillForCallIfException):
+        (JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
+        (JSC::FTL::exceptionTypeWillArriveAtOSRExitFromGenericUnwind):
+        (JSC::FTL::OSRExit::willArriveAtOSRExitFromGenericUnwind):
+        (JSC::FTL::OSRExit::willArriveAtOSRExitFromCallOperation):
+        (JSC::FTL::OSRExitDescriptor::isExceptionHandler): Deleted.
+        * ftl/FTLOSRExit.h:
+        (JSC::FTL::OSRExitDescriptorImpl::OSRExitDescriptorImpl):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileFTLOSRExit):
+        * ftl/FTLState.h:
+
 2015-12-03  Alex Christensen  <achristensen@webkit.org>
 
         Fix 64-bit Windows build after r193125.
index 6c44229..024aabe 100644 (file)
@@ -482,23 +482,28 @@ static void fixFunctionBasedOnStackMaps(
     }
 
     RELEASE_ASSERT(state.jitCode->osrExit.size() == 0);
+    HashMap<OSRExitDescriptor*, OSRExitDescriptorImpl*> genericUnwindOSRExitDescriptors;
     for (unsigned i = 0; i < state.jitCode->osrExitDescriptors.size(); i++) {
-        OSRExitDescriptor& exitDescriptor = state.jitCode->osrExitDescriptors[i];
-        auto iter = recordMap.find(exitDescriptor.m_stackmapID);
+        OSRExitDescriptor* exitDescriptor = &state.jitCode->osrExitDescriptors[i];
+        auto iter = recordMap.find(exitDescriptor->m_stackmapID);
         if (iter == recordMap.end()) {
             // It was optimized out.
             continue;
         }
 
-        for (unsigned j = exitDescriptor.m_values.size(); j--;)
-            exitDescriptor.m_values[j] = exitDescriptor.m_values[j].withLocalsOffset(localsOffset);
-        for (ExitTimeObjectMaterialization* materialization : exitDescriptor.m_materializations)
+        OSRExitDescriptorImpl& exitDescriptorImpl = state.osrExitDescriptorImpls[i];
+        if (exceptionTypeWillArriveAtOSRExitFromGenericUnwind(exitDescriptorImpl.m_exceptionType))
+            genericUnwindOSRExitDescriptors.add(exitDescriptor, &exitDescriptorImpl);
+
+        for (unsigned j = exitDescriptor->m_values.size(); j--;)
+            exitDescriptor->m_values[j] = exitDescriptor->m_values[j].withLocalsOffset(localsOffset);
+        for (ExitTimeObjectMaterialization* materialization : exitDescriptor->m_materializations)
             materialization->accountForLocalsOffset(localsOffset);
 
         for (unsigned j = 0; j < iter->value.size(); j++) {
             {
                 uint32_t stackmapRecordIndex = iter->value[j].index;
-                OSRExit exit(&exitDescriptor, stackmapRecordIndex);
+                OSRExit exit(exitDescriptor, exitDescriptorImpl, stackmapRecordIndex);
                 state.jitCode->osrExit.append(exit);
                 state.finalizer->osrExit.append(OSRExitCompilationInfo());
             }
@@ -506,29 +511,29 @@ static void fixFunctionBasedOnStackMaps(
             OSRExit& exit = state.jitCode->osrExit.last();
             if (exit.willArriveAtExitFromIndirectExceptionCheck()) {
                 StackMaps::Record& record = iter->value[j].record;
-                RELEASE_ASSERT(exit.m_descriptor->m_semanticCodeOriginForCallFrameHeader.isSet());
-                CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor->m_semanticCodeOriginForCallFrameHeader);
+                RELEASE_ASSERT(exitDescriptorImpl.m_semanticCodeOriginForCallFrameHeader.isSet());
+                CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exitDescriptorImpl.m_semanticCodeOriginForCallFrameHeader);
                 exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
 
                 OSRExit* callOperationExit = nullptr;
-                if (exitDescriptor.m_exceptionType == ExceptionType::BinaryOpGenerator) {
+                if (exitDescriptorImpl.m_exceptionType == ExceptionType::BinaryOpGenerator) {
                     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) {
+                if (exitDescriptorImpl.m_exceptionType == ExceptionType::GetById || exitDescriptorImpl.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)
+                    OSRExit exit(exitDescriptor, exitDescriptorImpl, stackmapRecordIndex);
+                    if (exitDescriptorImpl.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);
+                    CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exitDescriptorImpl.m_semanticCodeOriginForCallFrameHeader);
                     exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
 
                     state.jitCode->osrExit.append(exit);
@@ -543,19 +548,19 @@ static void fixFunctionBasedOnStackMaps(
                 //
                 // We set the registers needing spillage here because they need to be set
                 // before we generate OSR exits so the exit knows to do the proper recovery.
-                if (exitDescriptor.m_exceptionType == ExceptionType::JSCall) {
+                if (exitDescriptorImpl.m_exceptionType == ExceptionType::JSCall) {
                     // Call patchpoints might have values we want to do value recovery
                     // on inside volatile registers. We need to collect the volatile
                     // registers we want to do value recovery on here because they must
                     // be preserved to the stack before the call, that way the OSR exit
                     // exception handler can recover them into the proper registers.
                     exit.gatherRegistersToSpillForCallIfException(stackmaps, record);
-                } else if (exitDescriptor.m_exceptionType == ExceptionType::GetById) {
+                } else if (exitDescriptorImpl.m_exceptionType == ExceptionType::GetById) {
                     GPRReg result = record.locations[0].directGPR();
                     GPRReg base = record.locations[1].directGPR();
                     if (base == result)
                         callOperationExit->registersToPreserveForCallThatMightThrow.set(base);
-                } else if (exitDescriptor.m_exceptionType == ExceptionType::BinaryOpGenerator) {
+                } else if (exitDescriptorImpl.m_exceptionType == ExceptionType::BinaryOpGenerator) {
                     GPRReg result = record.locations[0].directGPR();
                     GPRReg left = record.locations[1].directGPR();
                     GPRReg right = record.locations[2].directGPR();
@@ -592,7 +597,7 @@ static void fixFunctionBasedOnStackMaps(
             exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
 
             if (exit.willArriveAtOSRExitFromGenericUnwind()) {
-                HandlerInfo newHandler = exit.m_descriptor->m_baselineExceptionHandler;
+                HandlerInfo newHandler = genericUnwindOSRExitDescriptors.get(exit.m_descriptor)->m_baselineExceptionHandler;
                 newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
                 newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
                 newHandler.nativeCode = info.m_thunkAddress;
index d79111a..11db48c 100644 (file)
@@ -82,7 +82,7 @@ CodeLocationLabel ExceptionHandlerManager::lazySlowPathExceptionTarget(uint32_t
         return CodeLocationLabel();
 
     size_t osrExitIndex = findResult->value;
-    RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_descriptor->m_exceptionType == ExceptionType::LazySlowPath);
+    RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_exceptionType == ExceptionType::LazySlowPath);
     OSRExitCompilationInfo& info = m_state.finalizer->osrExit[osrExitIndex];
     RELEASE_ASSERT(info.m_thunkLabel.isSet());
     return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_thunkLabel);
@@ -109,7 +109,7 @@ OSRExit* ExceptionHandlerManager::getCallOSRExitCommon(uint32_t stackmapRecordIn
         return nullptr;
     size_t osrExitIndex = findResult->value;
     OSRExit* exit = &m_state.jitCode->osrExit[osrExitIndex];
-    RELEASE_ASSERT(exit->m_descriptor->m_exceptionType == ExceptionType::JSCall);
+    RELEASE_ASSERT(exit->m_exceptionType == ExceptionType::JSCall);
     return exit; 
 }
 
index dbc6336..77787d1 100644 (file)
@@ -5376,7 +5376,7 @@ private:
 
         OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(UncountableInvalidation, ExceptionType::None, noValue(), nullptr, m_origin);
         
-        StackmapArgumentList arguments = buildExitArguments(exitDescriptor, FormattedValue());
+        StackmapArgumentList arguments = buildExitArguments(exitDescriptor, m_ftlState.osrExitDescriptorImpls.last(), FormattedValue());
         callStackmap(exitDescriptor, arguments);
         
         exitDescriptor->m_isInvalidationPoint = true;
@@ -9265,13 +9265,16 @@ private:
         if (!willCatchException)
             return;
 
-        OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
-        exitDescriptor->m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
-        exitDescriptor->m_baselineExceptionHandler = *exceptionHandler;
+        appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
+        OSRExitDescriptor* exitDescriptor = &m_ftlState.jitCode->osrExitDescriptors.last();
         exitDescriptor->m_stackmapID = m_stackmapIDs - 1;
 
+        OSRExitDescriptorImpl& exitDescriptorImpl = m_ftlState.osrExitDescriptorImpls.last();
+        exitDescriptorImpl.m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
+        exitDescriptorImpl.m_baselineExceptionHandler = *exceptionHandler;
+
         StackmapArgumentList freshList =
-            buildExitArguments(exitDescriptor, noValue(), offsetOfExitArguments);
+            buildExitArguments(exitDescriptor, exitDescriptorImpl, noValue(), offsetOfExitArguments);
         arguments.appendVector(freshList);
     }
 
@@ -9294,11 +9297,13 @@ private:
 
     OSRExitDescriptor* appendOSRExitDescriptor(ExitKind kind, ExceptionType exceptionType, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
     {
-        return &m_ftlState.jitCode->osrExitDescriptors.alloc(
-            kind, exceptionType, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
-            origin.forExit, origin.semantic,
+        OSRExitDescriptor& result = m_ftlState.jitCode->osrExitDescriptors.alloc(
+            lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
             availabilityMap().m_locals.numberOfArguments(),
             availabilityMap().m_locals.numberOfLocals());
+        m_ftlState.osrExitDescriptorImpls.alloc(
+            kind, origin.forExit, origin.semantic, exceptionType);
+        return &result;
     }
     
     void appendOSRExit(
@@ -9370,14 +9375,15 @@ private:
         OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(
             kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue,
             highValue, origin);
+        OSRExitDescriptorImpl* exitDescriptorImpl = &m_ftlState.osrExitDescriptorImpls.last();
         
         unsigned offset = value->numChildren();
-        value->appendAnys(buildExitArguments(exitDescriptor, lowValue));
+        value->appendAnys(buildExitArguments(exitDescriptor, m_ftlState.osrExitDescriptorImpls.last(), lowValue));
 
         State* state = &m_ftlState;
         value->setGenerator(
             [=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
-                exitDescriptor->emitOSRExit(*state, jit, params, offset);
+                exitDescriptor->emitOSRExit(*state, exitDescriptorImpl, jit, params, offset);
             });
     }
 #endif
@@ -9385,29 +9391,29 @@ private:
 #if !FTL_USES_B3
     void emitOSRExitCall(OSRExitDescriptor* exitDescriptor, FormattedValue lowValue)
     {
-        callStackmap(exitDescriptor, buildExitArguments(exitDescriptor, lowValue));
+        callStackmap(exitDescriptor, buildExitArguments(exitDescriptor, m_ftlState.osrExitDescriptorImpls.last(), lowValue));
     }
 #endif
 
     StackmapArgumentList buildExitArguments(
-        OSRExitDescriptor* exitDescriptor, FormattedValue lowValue,
+        OSRExitDescriptor* exitDescriptor, OSRExitDescriptorImpl& exitDescriptorImpl, FormattedValue lowValue,
         unsigned offsetOfExitArgumentsInStackmapLocations = 0)
     {
         StackmapArgumentList result;
         buildExitArguments(
-            exitDescriptor, result, lowValue, offsetOfExitArgumentsInStackmapLocations);
+            exitDescriptor, exitDescriptorImpl, result, lowValue, offsetOfExitArgumentsInStackmapLocations);
         return result;
     }
     
     void buildExitArguments(
-        OSRExitDescriptor* exitDescriptor, StackmapArgumentList& arguments, FormattedValue lowValue,
+        OSRExitDescriptor* exitDescriptor, OSRExitDescriptorImpl& exitDescriptorImpl, StackmapArgumentList& arguments, FormattedValue lowValue,
         unsigned offsetOfExitArgumentsInStackmapLocations = 0)
     {
         if (!!lowValue)
             arguments.append(lowValue.value());
         
         AvailabilityMap availabilityMap = this->availabilityMap();
-        availabilityMap.pruneByLiveness(m_graph, exitDescriptor->m_codeOrigin);
+        availabilityMap.pruneByLiveness(m_graph, exitDescriptorImpl.m_codeOrigin);
         
         HashMap<Node*, ExitTimeObjectMaterialization*> map;
         availabilityMap.forEachAvailability(
@@ -9434,7 +9440,7 @@ private:
             if (Options::validateFTLOSRExitLiveness()) {
                 DFG_ASSERT(
                     m_graph, m_node,
-                    (!(availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptor->m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
+                    (!(availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptorImpl.m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
             }
             ExitValue exitValue = exitValueForAvailability(arguments, map, availability);
             if (exitValue.hasIndexInStackmapLocations())
index 5aba1f6..0284d8c 100644 (file)
@@ -45,26 +45,15 @@ using namespace B3;
 using namespace DFG;
 
 OSRExitDescriptor::OSRExitDescriptor(
-    ExitKind exitKind, ExceptionType exceptionType, DataFormat profileDataFormat,
-    MethodOfGettingAValueProfile valueProfile, CodeOrigin codeOrigin,
-    CodeOrigin originForProfile, unsigned numberOfArguments,
-    unsigned numberOfLocals)
-    : m_kind(exitKind)
-    , m_exceptionType(exceptionType)
-    , m_codeOrigin(codeOrigin)
-    , m_codeOriginForExitProfile(originForProfile)
-    , m_profileDataFormat(profileDataFormat)
+    DataFormat profileDataFormat, MethodOfGettingAValueProfile valueProfile,
+    unsigned numberOfArguments, unsigned numberOfLocals)
+    : m_profileDataFormat(profileDataFormat)
     , m_valueProfile(valueProfile)
     , m_values(numberOfArguments, numberOfLocals)
     , m_isInvalidationPoint(false)
 {
 }
 
-bool OSRExitDescriptor::isExceptionHandler() const
-{
-    return m_exceptionType != ExceptionType::None;
-}
-
 void OSRExitDescriptor::validateReferences(const TrackedReferences& trackedReferences)
 {
     for (unsigned i = m_values.size(); i--;)
@@ -76,17 +65,17 @@ void OSRExitDescriptor::validateReferences(const TrackedReferences& trackedRefer
 
 #if FTL_USES_B3
 RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExit(
-    State& state, CCallHelpers& jit, const StackmapGenerationParams& params, unsigned offset)
+    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, CCallHelpers& jit, const StackmapGenerationParams& params, unsigned offset)
 {
-    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, params, offset);
+    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, exitDescriptorImpl, params, offset);
     handle->emitExitThunk(jit);
     return handle;
 }
 
 RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExitLater(
-    State& state, const StackmapGenerationParams& params, unsigned offset)
+    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, const StackmapGenerationParams& params, unsigned offset)
 {
-    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, params, offset);
+    RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, exitDescriptorImpl, params, offset);
     params.context->latePaths.append(
         createSharedTask<Air::GenerationContext::LatePathFunction>(
             [handle] (CCallHelpers& jit, Air::GenerationContext&) {
@@ -96,11 +85,11 @@ RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExitLater(
 }
 
 RefPtr<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
-    State& state, const StackmapGenerationParams& params, unsigned offset)
+    State& state, OSRExitDescriptorImpl* exitDescriptorImpl, const StackmapGenerationParams& params, unsigned offset)
 {
     unsigned index = state.jitCode->osrExit.size();
     RefPtr<OSRExitHandle> handle = adoptRef(
-        new OSRExitHandle(index, state.jitCode->osrExit.alloc(this)));
+        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();
@@ -109,19 +98,19 @@ RefPtr<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
 #endif // FTL_USES_B3
 
 OSRExit::OSRExit(
-    OSRExitDescriptor* descriptor
+    OSRExitDescriptor* descriptor, OSRExitDescriptorImpl& exitDescriptorImpl
 #if !FTL_USES_B3
     , uint32_t stackmapRecordIndex
 #endif // !FTL_USES_B3
     )
-    : OSRExitBase(descriptor->m_kind, descriptor->m_codeOrigin, descriptor->m_codeOriginForExitProfile)
+    : 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(descriptor->m_exceptionType)
+    , m_exceptionType(exitDescriptorImpl.m_exceptionType)
 {
-    m_isExceptionHandler = descriptor->isExceptionHandler();
+    m_isExceptionHandler = exitDescriptorImpl.m_exceptionType != ExceptionType::None;
 }
 
 CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const
@@ -140,7 +129,7 @@ CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const
 #if !FTL_USES_B3
 void OSRExit::gatherRegistersToSpillForCallIfException(StackMaps& stackmaps, StackMaps::Record& record)
 {
-    RELEASE_ASSERT(m_descriptor->m_exceptionType == ExceptionType::JSCall);
+    RELEASE_ASSERT(m_exceptionType == ExceptionType::JSCall);
 
     RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall();
 
@@ -226,9 +215,9 @@ bool OSRExit::willArriveAtExitFromIndirectExceptionCheck() const
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-bool OSRExit::willArriveAtOSRExitFromGenericUnwind() const
+bool exceptionTypeWillArriveAtOSRExitFromGenericUnwind(ExceptionType exceptionType)
 {
-    switch (m_exceptionType) {
+    switch (exceptionType) {
     case ExceptionType::JSCall:
     case ExceptionType::GetById:
     case ExceptionType::PutById:
@@ -239,6 +228,11 @@ bool OSRExit::willArriveAtOSRExitFromGenericUnwind() const
     RELEASE_ASSERT_NOT_REACHED();
 }
 
+bool OSRExit::willArriveAtOSRExitFromGenericUnwind() const
+{
+    return exceptionTypeWillArriveAtOSRExitFromGenericUnwind(m_exceptionType);
+}
+
 bool OSRExit::willArriveAtOSRExitFromCallOperation() const
 {
     switch (m_exceptionType) {
index 0b35cbb..800a78e 100644 (file)
@@ -60,6 +60,7 @@ struct GenerationContext;
 namespace FTL {
 
 class State;
+struct OSRExitDescriptorImpl;
 
 enum class ExceptionType : uint8_t {
     None,
@@ -73,20 +74,13 @@ enum class ExceptionType : uint8_t {
     BinaryOpGenerator,
 };
 
+bool exceptionTypeWillArriveAtOSRExitFromGenericUnwind(ExceptionType);
+
 struct OSRExitDescriptor {
     OSRExitDescriptor(
-        ExitKind, ExceptionType, DataFormat profileDataFormat, MethodOfGettingAValueProfile,
-        CodeOrigin, CodeOrigin originForProfile,
+        DataFormat profileDataFormat, MethodOfGettingAValueProfile,
         unsigned numberOfArguments, unsigned numberOfLocals);
 
-    bool isExceptionHandler() const;
-
-    ExitKind m_kind;
-    ExceptionType m_exceptionType;
-    CodeOrigin m_codeOrigin;
-    CodeOrigin m_codeOriginForExitProfile;
-    CodeOrigin m_semanticCodeOriginForCallFrameHeader;
-    
     // The first argument to the exit call may be a value we wish to profile.
     // If that's the case, the format will be not Invalid and we'll have a
     // method of getting a value profile. Note that all of the ExitArgument's
@@ -99,7 +93,6 @@ struct OSRExitDescriptor {
     Bag<ExitTimeObjectMaterialization> m_materializations;
     
     uint32_t m_stackmapID;
-    HandlerInfo m_baselineExceptionHandler;
     bool m_isInvalidationPoint;
     
     void validateReferences(const TrackedReferences&);
@@ -112,7 +105,7 @@ struct OSRExitDescriptor {
     // on the ground. It contains information that is mostly not useful if you use this API, since after
     // this call, the OSRExit is simply ready to go.
     RefPtr<OSRExitHandle> emitOSRExit(
-        State&, CCallHelpers&, const B3::StackmapGenerationParams&, unsigned offset);
+        State&, OSRExitDescriptorImpl*, CCallHelpers&, const B3::StackmapGenerationParams&, unsigned offset);
 
     // 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
@@ -123,19 +116,36 @@ struct OSRExitDescriptor {
     // have a place to jump to for OSR exit. It doesn't care where that OSR exit is emitted so long as it
     // eventually gets access to its label.
     RefPtr<OSRExitHandle> emitOSRExitLater(
-        State&, const B3::StackmapGenerationParams&, unsigned offset);
+        State&, OSRExitDescriptorImpl*, const B3::StackmapGenerationParams&, unsigned offset);
 
     // 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&, const B3::StackmapGenerationParams&, unsigned offset);
+        State&, OSRExitDescriptorImpl*, const B3::StackmapGenerationParams&, unsigned offset);
 #endif // FTL_USES_B3
 };
 
+struct OSRExitDescriptorImpl {
+    OSRExitDescriptorImpl(ExitKind kind, CodeOrigin exitOrigin, CodeOrigin forExitProfile, ExceptionType exceptionType)
+        : m_kind(kind)
+        , m_codeOrigin(exitOrigin)
+        , m_codeOriginForExitProfile(forExitProfile)
+        , m_exceptionType(exceptionType)
+    {
+    }
+
+    ExitKind m_kind;
+    CodeOrigin m_codeOrigin;
+    CodeOrigin m_codeOriginForExitProfile;
+    ExceptionType m_exceptionType;
+    CodeOrigin m_semanticCodeOriginForCallFrameHeader;
+    HandlerInfo m_baselineExceptionHandler;
+};
+
 struct OSRExit : public DFG::OSRExitBase {
     OSRExit(
-        OSRExitDescriptor*
+        OSRExitDescriptor*, OSRExitDescriptorImpl&
 #if !FTL_USES_B3
         , uint32_t stackmapRecordIndex
 #endif // !FTL_USES_B3
@@ -175,6 +185,7 @@ struct OSRExit : public DFG::OSRExitBase {
     bool needsRegisterRecoveryOnGenericUnwindOSRExitPath() const;
 };
 
+
 } } // namespace JSC::FTL
 
 #endif // ENABLE(FTL_JIT)
index f4edfed..8ceab6f 100644 (file)
@@ -584,7 +584,7 @@ extern "C" void* compileFTLOSRExit(ExecState* exec, unsigned exitID)
         dataLog("    Current call site index: ", exec->callSiteIndex().bits(), "\n");
         dataLog("    Exit is exception handler: ", exit.m_isExceptionHandler,
             " will arrive at exit from genericUnwind(): ", exit.willArriveAtOSRExitFromGenericUnwind(), 
-            " will arrive at exit from lazy slow path: ", exit.m_descriptor->m_exceptionType == ExceptionType::LazySlowPath, "\n");
+            " will arrive at exit from lazy slow path: ", exit.m_exceptionType == ExceptionType::LazySlowPath, "\n");
         dataLog("    Exit values: ", exit.m_descriptor->m_values, "\n");
         if (!exit.m_descriptor->m_materializations.isEmpty()) {
             dataLog("    Materializations:\n");
index b606f3c..92bfcb6 100644 (file)
@@ -101,6 +101,7 @@ public:
     Vector<JSTailCall> jsTailCalls;
     Vector<CString> codeSectionNames;
     Vector<CString> dataSectionNames;
+    SegmentedVector<OSRExitDescriptorImpl> osrExitDescriptorImpls;
     void* unwindDataSection;
     size_t unwindDataSectionSize;
     RefPtr<DataSection> stackmapsSection;