Title: [192845] trunk/Source/_javascript_Core
Revision
192845
Author
sbar...@apple.com
Date
2015-11-30 16:55:32 -0800 (Mon, 30 Nov 2015)

Log Message

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):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (192844 => 192845)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-01 00:55:32 UTC (rev 192845)
@@ -1,3 +1,43 @@
+2015-11-30  Saam barati  <sbar...@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):
+
 2015-11-30  Mark Lam  <mark....@apple.com>
 
         Refactor the op_add, op_sub, and op_mul snippets to use the SnippetOperand class.

Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2015-12-01 00:55:32 UTC (rev 192845)
@@ -643,13 +643,40 @@
             }
 
             OSRExit& exit = state.jitCode->osrExit.last();
-            if (exitDescriptor.willArriveAtExitFromIndirectExceptionCheck()) {
+            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);
                 exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
-                exceptionHandlerManager.addNewExit(iter->value[j].index, state.jitCode->osrExit.size() - 1);
 
+                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();
+                }
+
                 // Subs and GetByIds have an interesting register preservation story,
                 // see comment below at GetById to read about it.
                 //
@@ -666,13 +693,13 @@
                     GPRReg result = record.locations[0].directGPR();
                     GPRReg base = record.locations[1].directGPR();
                     if (base == result)
-                        exit.registersToPreserveForCallThatMightThrow.set(base);
+                        callOperationExit->registersToPreserveForCallThatMightThrow.set(base);
                 } else if (exitDescriptor.m_exceptionType == ExceptionType::SubGenerator) {
                     GPRReg result = record.locations[0].directGPR();
                     GPRReg left = record.locations[1].directGPR();
                     GPRReg right = record.locations[2].directGPR();
                     if (result == left || result == right)
-                        exit.registersToPreserveForCallThatMightThrow.set(result);
+                        callOperationExit->registersToPreserveForCallThatMightThrow.set(result);
                 }
             }
         }
@@ -703,7 +730,7 @@
             info.m_thunkAddress = linkBuffer->locationOf(info.m_thunkLabel);
             exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
 
-            if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind()) {
+            if (exit.willArriveAtOSRExitFromGenericUnwind()) {
                 HandlerInfo newHandler = exit.m_descriptor.m_baselineExceptionHandler;
                 newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
                 newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
@@ -781,7 +808,7 @@
                     // register that we would like to do value recovery on. We combat this situation from ever
                     // taking place by ensuring we spill the original base value and then recover it from
                     // the spill slot as the first step in OSR exit.
-                    if (OSRExit* exit = exceptionHandlerManager.getByIdOSRExit(iter->value[i].index))
+                    if (OSRExit* exit = exceptionHandlerManager.callOperationOSRExit(iter->value[i].index))
                         exit->spillRegistersToSpillSlot(slowPathJIT, jsCallThatMightThrowSpillOffset);
                 }
                 MacroAssembler::Call call = callOperation(
@@ -900,7 +927,7 @@
                 if (result == left || result == right) {
                     // This situation has a really interesting register preservation story.
                     // See comment above for GetByIds.
-                    if (OSRExit* exit = exceptionHandlerManager.subOSRExit(iter->value[i].index))
+                    if (OSRExit* exit = exceptionHandlerManager.callOperationOSRExit(iter->value[i].index))
                         exit->spillRegistersToSpillSlot(slowPathJIT, jsCallThatMightThrowSpillOffset);
                 }
 
@@ -1099,7 +1126,7 @@
         OSRExit& exit = jitCode->osrExit[exitIndex];
         Vector<const void*> codeAddresses;
 
-        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.
+        if (exit.willArriveAtExitFromIndirectExceptionCheck()) // This jump doesn't happen directly from a patchpoint/stackmap we compile. It happens indirectly through an exception check somewhere.
             continue;
         
         StackMaps::Record& record = jitCode->stackmaps.records[exit.m_stackmapRecordIndex];

Modified: trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp	2015-12-01 00:55:32 UTC (rev 192845)
@@ -41,9 +41,16 @@
 {
     m_map.add(stackmapRecordIndex, osrExitIndex);
     OSRExit& exit = m_state.jitCode->osrExit[osrExitIndex];
-    RELEASE_ASSERT(exit.m_descriptor.willArriveAtExitFromIndirectExceptionCheck());
+    RELEASE_ASSERT(exit.willArriveAtExitFromIndirectExceptionCheck());
 }
 
+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());
+}
+
 CodeLocationLabel ExceptionHandlerManager::callOperationExceptionTarget(uint32_t stackmapRecordIndex)
 {
 #if FTL_USES_B3
@@ -51,15 +58,15 @@
     RELEASE_ASSERT_NOT_REACHED();
     return CodeLocationLabel();
 #else // FTL_USES_B3
-    auto findResult = m_map.find(stackmapRecordIndex);
-    if (findResult == m_map.end())
+    auto findResult = m_callOperationMap.find(stackmapRecordIndex);
+    if (findResult == m_callOperationMap.end())
         return CodeLocationLabel();
 
     size_t osrExitIndex = findResult->value;
-    RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_descriptor.mightArriveAtOSRExitFromCallOperation());
+    RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].willArriveAtOSRExitFromCallOperation());
     OSRExitCompilationInfo& info = m_state.finalizer->osrExit[osrExitIndex];
-    RELEASE_ASSERT(info.m_callOperationExceptionOSRExitEntrance.isSet());
-    return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_callOperationExceptionOSRExitEntrance);
+    RELEASE_ASSERT(info.m_thunkLabel.isSet());
+    return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_thunkLabel);
 #endif // FTL_USES_B3
 }
 
@@ -82,28 +89,19 @@
 #endif // FTL_USES_B3
 }
 
-OSRExit* ExceptionHandlerManager::getByIdOSRExit(uint32_t stackmapRecordIndex)
+OSRExit* ExceptionHandlerManager::callOperationOSRExit(uint32_t stackmapRecordIndex)
 {
-    auto findResult = m_map.find(stackmapRecordIndex);
-    if (findResult == m_map.end())
+    auto findResult = m_callOperationMap.find(stackmapRecordIndex);
+    if (findResult == m_callOperationMap.end())
         return nullptr;
     size_t osrExitIndex = findResult->value;
     OSRExit* exit = &m_state.jitCode->osrExit[osrExitIndex];
-    RELEASE_ASSERT(exit->m_descriptor.m_exceptionType == ExceptionType::GetById);
+    // 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());
     return exit; 
 }
 
-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; 
-}
-
 OSRExit* ExceptionHandlerManager::getCallOSRExitCommon(uint32_t stackmapRecordIndex)
 {
     auto findResult = m_map.find(stackmapRecordIndex);

Modified: trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.h (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.h	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.h	2015-12-01 00:55:32 UTC (rev 192845)
@@ -54,14 +54,14 @@
     ExceptionHandlerManager(State& state);
 
     void addNewExit(uint32_t stackmapRecordIndex, size_t osrExitIndex);
+    void addNewCallOperationExit(uint32_t stackmapRecordIndex, size_t osrExitIndex);
 
     // These functions only make sense to be called after we've generated the OSR
     // exit thunks and allocated the OSR exit thunks' link buffer.
     CodeLocationLabel callOperationExceptionTarget(uint32_t stackmapRecordIndex);
     CodeLocationLabel lazySlowPathExceptionTarget(uint32_t stackmapRecordIndex);
 
-    OSRExit* getByIdOSRExit(uint32_t stackmapRecordIndex);
-    OSRExit* subOSRExit(uint32_t stackmapRecordIndex);
+    OSRExit* callOperationOSRExit(uint32_t stackmapRecordIndex);
     OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSCall&);
     OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSTailCall&);
     OSRExit* getCallOSRExit(uint32_t stackmapRecordIndex, const JSCallVarargs&);
@@ -78,6 +78,7 @@
     State& m_state;
     typedef HashMap<uint32_t, size_t, WTF::IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> RecordIndexToOSRExitIndexMap;
     RecordIndexToOSRExitIndexMap m_map;
+    RecordIndexToOSRExitIndexMap m_callOperationMap;
 };
 
 } } // namespace JSC::FTL

Modified: trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp	2015-12-01 00:55:32 UTC (rev 192845)
@@ -53,27 +53,18 @@
     
     info.m_thunkLabel = label();
 
-    Jump jumpToPushIndexFromGenericUnwind;
-    if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind()) {
+    ASSERT(!(exit.willArriveAtOSRExitFromGenericUnwind() && exit.willArriveAtOSRExitFromCallOperation()));
+    if (exit.willArriveAtOSRExitFromGenericUnwind()) {
         restoreCalleeSavesFromVMCalleeSavesBuffer();
         loadPtr(vm()->addressOfCallFrameForCatch(), framePointerRegister);
         addPtr(TrustedImm32(- static_cast<int64_t>(m_state.jitCode->stackmaps.stackSizeForLocals())), 
             framePointerRegister, stackPointerRegister);
 
-        if (exit.m_descriptor.needsRegisterRecoveryOnGenericUnwindOSRExitPath())
+        if (exit.needsRegisterRecoveryOnGenericUnwindOSRExitPath())
             exit.recoverRegistersFromSpillSlot(*this, osrExitFromGenericUnwindStackSpillSlot);
-
-        jumpToPushIndexFromGenericUnwind = jump();
-    }
-
-    if (exit.m_descriptor.mightArriveAtOSRExitFromCallOperation()) {
-        info.m_callOperationExceptionOSRExitEntrance = label();
+    } else if (exit.willArriveAtOSRExitFromCallOperation())
         exit.recoverRegistersFromSpillSlot(*this, osrExitFromGenericUnwindStackSpillSlot);
-    }
     
-    if (exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind())
-        jumpToPushIndexFromGenericUnwind.link(this);
-
     pushToSaveImmediateWithoutTouchingRegisters(TrustedImm32(index));
     info.m_thunkJump = patchableJump();
     

Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp	2015-12-01 00:55:32 UTC (rev 192845)
@@ -56,62 +56,6 @@
 {
 }
 
-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;
-}
-
 bool OSRExitDescriptor::isExceptionHandler() const
 {
     return m_exceptionType != ExceptionType::None;
@@ -131,6 +75,7 @@
     : OSRExitBase(descriptor.m_kind, descriptor.m_codeOrigin, descriptor.m_codeOriginForExitProfile)
     , m_descriptor(descriptor)
     , m_stackmapRecordIndex(stackmapRecordIndex)
+    , m_exceptionType(descriptor.m_exceptionType)
 {
     m_isExceptionHandler = descriptor.isExceptionHandler();
 }
@@ -186,7 +131,7 @@
 
 void OSRExit::spillRegistersToSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
 {
-    RELEASE_ASSERT(m_descriptor.mightArriveAtOSRExitFromGenericUnwind() || m_descriptor.mightArriveAtOSRExitFromCallOperation());
+    RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
     unsigned count = 0;
     for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
         if (registersToPreserveForCallThatMightThrow.get(reg)) {
@@ -204,7 +149,7 @@
 
 void OSRExit::recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
 {
-    RELEASE_ASSERT(m_descriptor.mightArriveAtOSRExitFromGenericUnwind() || m_descriptor.mightArriveAtOSRExitFromCallOperation());
+    RELEASE_ASSERT(willArriveAtOSRExitFromGenericUnwind() || willArriveAtOSRExitFromCallOperation());
     unsigned count = 0;
     for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
         if (registersToPreserveForCallThatMightThrow.get(reg)) {
@@ -220,6 +165,64 @@
     }
 }
 
+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;
+}
+
 } } // namespace JSC::FTL
 
 #endif // ENABLE(FTL_JIT)

Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.h (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.h	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.h	2015-12-01 00:55:32 UTC (rev 192845)
@@ -136,14 +136,16 @@
 //   intrinsics (or meta-data, or something) to inform the backend that it's safe to
 //   make the predicate passed to 'exitIf()' more truthy.
 
-enum class ExceptionType {
+enum class ExceptionType : uint8_t {
     None,
     CCallException,
     JSCall,
     GetById,
+    GetByIdCallOperation,
     PutById,
+    PutByIdCallOperation,
     LazySlowPath,
-    SubGenerator
+    SubGenerator,
 };
 
 struct OSRExitDescriptor {
@@ -152,10 +154,6 @@
         CodeOrigin, CodeOrigin originForProfile,
         unsigned numberOfArguments, unsigned numberOfLocals);
 
-    bool willArriveAtExitFromIndirectExceptionCheck() const;
-    bool mightArriveAtOSRExitFromGenericUnwind() const;
-    bool mightArriveAtOSRExitFromCallOperation() const;
-    bool needsRegisterRecoveryOnGenericUnwindOSRExitPath() const;
     bool isExceptionHandler() const;
 
     ExitKind m_kind;
@@ -191,6 +189,7 @@
     unsigned m_patchableCodeOffset;
     // Offset within Stackmap::records
     uint32_t m_stackmapRecordIndex;
+    ExceptionType m_exceptionType;
 
     RegisterSet registersToPreserveForCallThatMightThrow;
 
@@ -203,6 +202,11 @@
     void gatherRegistersToSpillForCallIfException(StackMaps&, StackMaps::Record&);
     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;
 };
 
 } } // namespace JSC::FTL

Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h	2015-12-01 00:55:32 UTC (rev 192845)
@@ -39,7 +39,6 @@
     }
     
     MacroAssembler::Label m_thunkLabel;
-    MacroAssembler::Label m_callOperationExceptionOSRExitEntrance;
     MacroAssembler::PatchableJump m_thunkJump;
     CodeLocationLabel m_thunkAddress;
 };

Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp (192844 => 192845)


--- trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp	2015-12-01 00:33:47 UTC (rev 192844)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp	2015-12-01 00:55:32 UTC (rev 192845)
@@ -547,7 +547,7 @@
         dataLog("    Exit stackmap ID: ", exit.m_descriptor.m_stackmapID, "\n");
         dataLog("    Current call site index: ", exec->callSiteIndex().bits(), "\n");
         dataLog("    Exit is exception handler: ", exit.m_isExceptionHandler,
-            " might arrive at exit from genericUnwind(): ", exit.m_descriptor.mightArriveAtOSRExitFromGenericUnwind(), 
+            " will arrive at exit from genericUnwind(): ", exit.willArriveAtOSRExitFromGenericUnwind(), 
             " will arrive at exit from lazy slow path: ", exit.m_descriptor.m_exceptionType == ExceptionType::LazySlowPath, "\n");
         dataLog("    Exit values: ", exit.m_descriptor.m_values, "\n");
         if (!exit.m_descriptor.m_materializations.isEmpty()) {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to