Title: [293714] trunk
Revision
293714
Author
[email protected]
Date
2022-05-02 22:07:01 -0700 (Mon, 02 May 2022)

Log Message

[JSC] Introduce unlinked version of invalidation
https://bugs.webkit.org/show_bug.cgi?id=239887

Reviewed by Saam Barati.

This patch makes invalidation mechanism unlinked for unlinked DFG.

1. We always use CheckTraps instead of InvalidationPoint with VMTraps so that we do not need
to repatch existing code.
2. We introduce load-and-branch based InvalidationPoint for unlinked DFG so that we do not need
to repatch it to jump to OSR exit when watchpoint fires. We store this condition in DFG::JITData
so that code can quickly access to that.
3. We make isStillValid conditions in DFG::CommonData always true for unlinked DFG code. Instead,
we check isJettisoned() condition of CodeBlock since it will become eventually per CodeBlock
information (while this CodeBlock gets invalidated, unlinked DFG code itself can be used for
the other CodeBlock).

After this change, now, jumpReplacements for unlinked DFG becomes empty. We no longer repatch these invalidation points.

* Source/_javascript_Core/bytecode/CodeBlock.cpp:
(JSC::CodeBlock::jettison):
(JSC::CodeBlock::hasInstalledVMTrapsBreakpoints const):
(JSC::CodeBlock::canInstallVMTrapBreakpoints const):
(JSC::CodeBlock::installVMTrapBreakpoints):
(JSC::CodeBlock::hasInstalledVMTrapBreakpoints const): Deleted.
* Source/_javascript_Core/bytecode/CodeBlock.h:
* Source/_javascript_Core/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* Source/_javascript_Core/dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::invalidate):
(JSC::DFG::CommonData::~CommonData):
(JSC::DFG::CommonData::installVMTrapBreakpoints):
(JSC::DFG::CommonData::isVMTrapBreakpoint):
* Source/_javascript_Core/dfg/DFGCommonData.h:
(JSC::DFG::CommonData::CommonData):
(JSC::DFG::CommonData::hasInstalledVMTrapsBreakpoints const):
(JSC::DFG::CommonData::isStillValid const):
* Source/_javascript_Core/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/_javascript_Core/dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::JITCode):
* Source/_javascript_Core/dfg/DFGJITCode.h:
* Source/_javascript_Core/dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* Source/_javascript_Core/dfg/DFGOSREntry.cpp:
(JSC::DFG::prepareOSREntry):
(JSC::DFG::prepareCatchOSREntry):
* Source/_javascript_Core/dfg/DFGPlan.cpp:
(JSC::DFG::Plan::finalize):
* Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileInvalidationPoint):
(JSC::DFG::SpeculativeJIT::compileCheckTraps):
(JSC::DFG::SpeculativeJIT::emitInvalidationPoint): Deleted.
* Source/_javascript_Core/dfg/DFGSpeculativeJIT.h:
* Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/_javascript_Core/ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::JITCode):
* Source/_javascript_Core/ftl/FTLJITCode.h:
(JSC::FTL::JITCode::isUnlinked const):
* Source/_javascript_Core/ftl/FTLOSREntry.cpp:
(JSC::FTL::prepareOSREntry):
* Source/_javascript_Core/jit/JITCode.cpp:
(JSC::JITCode::isUnlinked const):
* Source/_javascript_Core/jit/JITCode.h:
* Source/_javascript_Core/runtime/VMTraps.cpp:
(JSC::VMTraps::tryInstallTrapBreakpoints):
(JSC::VMTraps::handleTraps):

Canonical link: https://commits.webkit.org/250203@main

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (293713 => 293714)


--- trunk/JSTests/ChangeLog	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/JSTests/ChangeLog	2022-05-03 05:07:01 UTC (rev 293714)
@@ -1,3 +1,13 @@
+2022-04-29  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Introduce unlinked version of invalidation
+        https://bugs.webkit.org/show_bug.cgi?id=239887
+
+        Reviewed by Saam Barati.
+
+        * stress/polling-based-trap-on-unlinked-dfg.js: Added.
+        (test):
+
 2022-05-01  Yusuke Suzuki  <[email protected]>
 
         [JSC] Add ISO8601 based Temporal.PlainDate getters

Added: trunk/JSTests/stress/polling-based-trap-on-unlinked-dfg.js (0 => 293714)


--- trunk/JSTests/stress/polling-based-trap-on-unlinked-dfg.js	                        (rev 0)
+++ trunk/JSTests/stress/polling-based-trap-on-unlinked-dfg.js	2022-05-03 05:07:01 UTC (rev 293714)
@@ -0,0 +1,10 @@
+//@ runDefault("--forceUnlinkedDFG=1", "--watchdog=1000", "--watchdog-exception-ok", "--useFTLJIT=0")
+
+function test(value)
+{
+    return value * value;
+}
+noInline(test);
+
+for (var i = 0;; ++i)
+    test(i);

Modified: trunk/Source/_javascript_Core/ChangeLog (293713 => 293714)


--- trunk/Source/_javascript_Core/ChangeLog	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-05-03 05:07:01 UTC (rev 293714)
@@ -1,3 +1,79 @@
+2022-04-29  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Introduce unlinked version of invalidation
+        https://bugs.webkit.org/show_bug.cgi?id=239887
+
+        Reviewed by Saam Barati.
+
+        This patch makes invalidation mechanism unlinked for unlinked DFG.
+
+        1. We always use CheckTraps instead of InvalidationPoint with VMTraps so that we do not need
+           to repatch existing code.
+        2. We introduce load-and-branch based InvalidationPoint for unlinked DFG so that we do not need
+           to repatch it to jump to OSR exit when watchpoint fires. We store this condition in DFG::JITData
+           so that code can quickly access to that.
+        3. We make isStillValid conditions in DFG::CommonData always true for unlinked DFG code. Instead,
+           we check isJettisoned() condition of CodeBlock since it will become eventually per CodeBlock
+           information (while this CodeBlock gets invalidated, unlinked DFG code itself can be used for
+           the other CodeBlock).
+
+        After this change, now, jumpReplacements for unlinked DFG becomes empty. We no longer repatch these invalidation points.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::jettison):
+        (JSC::CodeBlock::hasInstalledVMTrapsBreakpoints const):
+        (JSC::CodeBlock::canInstallVMTrapBreakpoints const):
+        (JSC::CodeBlock::installVMTrapBreakpoints):
+        (JSC::CodeBlock::hasInstalledVMTrapBreakpoints const): Deleted.
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::isJettisoned const):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCommonData.cpp:
+        (JSC::DFG::CommonData::invalidateLinkedCode):
+        (JSC::DFG::CommonData::~CommonData):
+        (JSC::DFG::CommonData::installVMTrapBreakpoints):
+        (JSC::DFG::CommonData::invalidate): Deleted.
+        (JSC::DFG::CommonData::isVMTrapBreakpoint): Deleted.
+        * dfg/DFGCommonData.h:
+        (JSC::DFG::CommonData::CommonData):
+        (JSC::DFG::CommonData::hasInstalledVMTrapsBreakpoints const):
+        (JSC::DFG::CommonData::isUnlinked const):
+        (JSC::DFG::CommonData::isStillValid const):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGJITCode.cpp:
+        (JSC::DFG::JITCode::JITCode):
+        * dfg/DFGJITCode.h:
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGOSREntry.cpp:
+        (JSC::DFG::prepareOSREntry):
+        (JSC::DFG::prepareCatchOSREntry):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::finalize):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileInvalidationPoint):
+        (JSC::DFG::SpeculativeJIT::compileCheckTraps):
+        (JSC::DFG::SpeculativeJIT::emitInvalidationPoint): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLJITCode.cpp:
+        (JSC::FTL::JITCode::JITCode):
+        * ftl/FTLJITCode.h:
+        (JSC::FTL::JITCode::isUnlinked const):
+        * ftl/FTLOSREntry.cpp:
+        (JSC::FTL::prepareOSREntry):
+        * jit/JITCode.cpp:
+        (JSC::JITCode::isUnlinked const):
+        * jit/JITCode.h:
+        * runtime/VMTraps.cpp:
+        (JSC::VMTraps::tryInstallTrapBreakpoints):
+        (JSC::VMTraps::handleTraps):
+
 2022-05-02  Yusuke Suzuki  <[email protected]>
 
         [JSC] Introduce shifting Structure encoding

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -2250,11 +2250,21 @@
             compilation->setJettisonReason(reason, detail);
         
         // This accomplishes (1), and does its own book-keeping about whether it has already happened.
-        if (!jitCode()->dfgCommon()->invalidate()) {
-            // We've already been invalidated.
-            RELEASE_ASSERT(this != replacement() || (vm.heap.currentThreadIsDoingGCWork() && !vm.heap.isMarked(ownerExecutable())));
-            return;
+        if (auto* jitData = dfgJITData()) {
+            if (jitData->isInvalidated()) {
+                // We've already been invalidated.
+                RELEASE_ASSERT(this != replacement() || (vm.heap.currentThreadIsDoingGCWork() && !vm.heap.isMarked(ownerExecutable())));
+                return;
+            }
+            jitData->invalidate();
         }
+        if (!jitCode()->isUnlinked()) {
+            if (!jitCode()->dfgCommon()->invalidateLinkedCode()) {
+                // We've already been invalidated.
+                RELEASE_ASSERT(this != replacement() || (vm.heap.currentThreadIsDoingGCWork() && !vm.heap.isMarked(ownerExecutable())));
+                return;
+            }
+        }
     }
     
     if (DFG::shouldDumpDisassembly())
@@ -3479,13 +3489,13 @@
     m_unlinkedCode->llintExecuteCounter().setNewThreshold(0, this);
 }
 
-bool CodeBlock::hasInstalledVMTrapBreakpoints() const
+bool CodeBlock::hasInstalledVMTrapsBreakpoints() const
 {
 #if ENABLE(SIGNAL_BASED_VM_TRAPS)
     // This function may be called from a signal handler. We need to be
     // careful to not call anything that is not signal handler safe, e.g.
     // we should not perturb the refCount of m_jitCode.
-    if (!JITCode::isOptimizingJIT(jitType()))
+    if (!canInstallVMTrapBreakpoints())
         return false;
     return m_jitCode->dfgCommon()->hasInstalledVMTrapsBreakpoints();
 #else
@@ -3493,7 +3503,7 @@
 #endif
 }
 
-bool CodeBlock::installVMTrapBreakpoints()
+bool CodeBlock::canInstallVMTrapBreakpoints() const
 {
 #if ENABLE(SIGNAL_BASED_VM_TRAPS)
     // This function may be called from a signal handler. We need to be
@@ -3501,6 +3511,22 @@
     // we should not perturb the refCount of m_jitCode.
     if (!JITCode::isOptimizingJIT(jitType()))
         return false;
+    if (m_jitCode->isUnlinked())
+        return false;
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool CodeBlock::installVMTrapBreakpoints()
+{
+#if ENABLE(SIGNAL_BASED_VM_TRAPS)
+    // This function may be called from a signal handler. We need to be
+    // careful to not call anything that is not signal handler safe, e.g.
+    // we should not perturb the refCount of m_jitCode.
+    if (!canInstallVMTrapBreakpoints())
+        return false;
     auto& commonData = *m_jitCode->dfgCommon();
     commonData.installVMTrapBreakpoints(this);
     return true;

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (293713 => 293714)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -227,7 +227,8 @@
 
     JSParserScriptMode scriptMode() const { return m_unlinkedCode->scriptMode(); }
 
-    bool hasInstalledVMTrapBreakpoints() const;
+    bool hasInstalledVMTrapsBreakpoints() const;
+    bool canInstallVMTrapBreakpoints() const;
     bool installVMTrapBreakpoints();
 
     ALWAYS_INLINE bool isTemporaryRegister(VirtualRegister reg)
@@ -739,6 +740,8 @@
         m_numBreakpoints -= numBreakpoints;
     }
 
+    bool isJettisoned() const { return m_isJettisoned; }
+
     enum SteppingMode {
         SteppingModeDisabled,
         SteppingModeEnabled

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -8124,7 +8124,7 @@
         }
         
         case op_check_traps: {
-            addToGraph(Options::usePollingTraps() ? CheckTraps : InvalidationPoint);
+            addToGraph((Options::usePollingTraps() || m_graph.m_plan.isUnlinked()) ? CheckTraps : InvalidationPoint);
             NEXT_OPCODE(op_check_traps);
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -55,28 +55,36 @@
     return pcCodeBlockMap;
 }
 
-bool CommonData::invalidate()
+bool CommonData::invalidateLinkedCode()
 {
-    if (!isStillValid)
+    if (m_isUnlinked) {
+        ASSERT(m_jumpReplacements.isEmpty());
+        return true;
+    }
+
+    if (!m_isStillValid)
         return false;
 
-    if (UNLIKELY(hasVMTrapsBreakpointsInstalled)) {
+    if (UNLIKELY(m_hasVMTrapsBreakpointsInstalled)) {
         Locker locker { pcCodeBlockMapLock };
         auto& map = pcCodeBlockMap();
         for (auto& jumpReplacement : m_jumpReplacements)
             map.remove(jumpReplacement.dataLocation());
-        hasVMTrapsBreakpointsInstalled = false;
+        m_hasVMTrapsBreakpointsInstalled = false;
     }
 
     for (unsigned i = m_jumpReplacements.size(); i--;)
         m_jumpReplacements[i].fire();
-    isStillValid = false;
+
+    m_isStillValid = false;
     return true;
 }
 
 CommonData::~CommonData()
 {
-    if (UNLIKELY(hasVMTrapsBreakpointsInstalled)) {
+    if (m_isUnlinked)
+        return;
+    if (UNLIKELY(m_hasVMTrapsBreakpointsInstalled)) {
         Locker locker { pcCodeBlockMapLock };
         auto& map = pcCodeBlockMap();
         for (auto& jumpReplacement : m_jumpReplacements)
@@ -86,10 +94,11 @@
 
 void CommonData::installVMTrapBreakpoints(CodeBlock* owner)
 {
+    ASSERT(!m_isUnlinked);
     Locker locker { pcCodeBlockMapLock };
-    if (!isStillValid || hasVMTrapsBreakpointsInstalled)
+    if (!m_isStillValid || m_hasVMTrapsBreakpointsInstalled)
         return;
-    hasVMTrapsBreakpointsInstalled = true;
+    m_hasVMTrapsBreakpointsInstalled = true;
 
     auto& map = pcCodeBlockMap();
 #if !defined(NDEBUG)
@@ -120,17 +129,6 @@
     return result->value;
 }
 
-bool CommonData::isVMTrapBreakpoint(void* address)
-{
-    if (!isStillValid)
-        return false;
-    for (unsigned i = m_jumpReplacements.size(); i--;) {
-        if (address == m_jumpReplacements[i].dataLocation())
-            return true;
-    }
-    return false;
-}
-
 void CommonData::validateReferences(const TrackedReferences& trackedReferences)
 {
     if (InlineCallFrameSet* set = inlineCallFrames.get()) {

Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.h (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -79,18 +79,21 @@
 class CommonData : public MathICHolder {
     WTF_MAKE_NONCOPYABLE(CommonData);
 public:
-    CommonData()
+    CommonData(bool isUnlinked)
         : codeOrigins(CodeOriginPool::create())
+        , m_isUnlinked(isUnlinked)
     { }
     ~CommonData();
     
     void shrinkToFit();
     
-    bool invalidate(); // Returns true if we did invalidate, or false if the code block was already invalidated.
-    bool hasInstalledVMTrapsBreakpoints() const { return isStillValid && hasVMTrapsBreakpointsInstalled; }
+    bool invalidateLinkedCode(); // Returns true if we did invalidate, or false if the code block was already invalidated.
+    bool hasInstalledVMTrapsBreakpoints() const { return m_isStillValid && m_hasVMTrapsBreakpointsInstalled; }
     void installVMTrapBreakpoints(CodeBlock* owner);
-    bool isVMTrapBreakpoint(void* address);
 
+    bool isUnlinked() const { return m_isUnlinked; }
+    bool isStillValid() const { return m_isStillValid; }
+
     CatchEntrypointData* catchOSREntryDataForBytecodeIndex(BytecodeIndex bytecodeIndex)
     {
         return tryBinarySearch<CatchEntrypointData, BytecodeIndex>(
@@ -136,8 +139,6 @@
     
     ScratchBuffer* catchOSREntryBuffer;
     RefPtr<Profiler::Compilation> compilation;
-    bool isStillValid { true };
-    bool hasVMTrapsBreakpointsInstalled { false };
     
 #if USE(JSVALUE32_64)
     Bag<double> doubleConstants;
@@ -145,6 +146,11 @@
     
     unsigned frameRegisterCount { std::numeric_limits<unsigned>::max() };
     unsigned requiredRegisterCountForExit { std::numeric_limits<unsigned>::max() };
+
+private:
+    bool m_isUnlinked { false };
+    bool m_isStillValid { true };
+    bool m_hasVMTrapsBreakpointsInstalled { false };
 };
 
 CodeBlock* codeBlockForVMTrapPC(void* pc);

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -453,7 +453,7 @@
 
     case CheckTraps:
         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=194323
-        ASSERT(Options::usePollingTraps());
+        ASSERT(Options::usePollingTraps() || graph.m_plan.isUnlinked());
         return true;
 
     case CompareEq:

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -37,7 +37,7 @@
 
 JITCode::JITCode(bool isUnlinked)
     : DirectJITCode(JITType::DFGJIT)
-    , isUnlinked(isUnlinked)
+    , common(isUnlinked)
 {
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCode.h (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGJITCode.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCode.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -57,6 +57,7 @@
     using ExitVector = FixedVector<MacroAssemblerCodeRef<OSRExitPtrTag>>;
 
     static ptrdiff_t offsetOfExits() { return OBJECT_OFFSETOF(JITData, m_exits); }
+    static ptrdiff_t offsetOfIsInvalidated() { return OBJECT_OFFSETOF(JITData, m_isInvalidated); }
 
     static std::unique_ptr<JITData> create(unsigned poolSize, ExitVector&& exits)
     {
@@ -69,6 +70,13 @@
     }
     const MacroAssemblerCodeRef<OSRExitPtrTag>& exitCode(unsigned exitIndex) const { return m_exits[exitIndex]; }
 
+    bool isInvalidated() const { return !!m_isInvalidated; }
+
+    void invalidate()
+    {
+        m_isInvalidated = 1;
+    }
+
 private:
     explicit JITData(unsigned size, ExitVector&& exits)
         : Base(size)
@@ -77,6 +85,7 @@
     }
 
     ExitVector m_exits;
+    uint8_t m_isInvalidated { 0 };
 };
 
 class JITCode final : public DirectJITCode {
@@ -86,6 +95,7 @@
     
     CommonData* dfgCommon() final;
     JITCode* dfg() final;
+    bool isUnlinked() const { return common.isUnlinked(); }
     
     OSREntryData* osrEntryDataForBytecodeIndex(BytecodeIndex bytecodeIndex)
     {
@@ -180,7 +190,6 @@
     unsigned osrEntryRetry { 0 };
     bool abandonOSREntry { false };
 #endif // ENABLE(FTL_JIT)
-    bool isUnlinked { false };
 };
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -291,25 +291,32 @@
     if (!m_exceptionChecksWithCallFrameRollback.empty())
         linkBuffer.link(m_exceptionChecksWithCallFrameRollback, CodeLocationLabel(vm().getCTIStub(handleExceptionWithCallFrameRollbackGenerator).retaggedCode<NoPtrTag>()));
 
-    Vector<JumpReplacement> jumpReplacements;
-    MacroAssemblerCodeRef<JITThunkPtrTag> osrExitThunk = vm().getCTIStub(osrExitGenerationThunkGenerator);
-    auto target = CodeLocationLabel<JITThunkPtrTag>(osrExitThunk.code());
-    for (unsigned i = 0; i < m_osrExit.size(); ++i) {
-        OSRExitCompilationInfo& info = m_exitCompilationInfo[i];
-
-        if (!m_graph.m_plan.isUnlinked()) {
+    if (!m_graph.m_plan.isUnlinked()) {
+        MacroAssemblerCodeRef<JITThunkPtrTag> osrExitThunk = vm().getCTIStub(osrExitGenerationThunkGenerator);
+        auto target = CodeLocationLabel<JITThunkPtrTag>(osrExitThunk.code());
+        Vector<JumpReplacement> jumpReplacements;
+        for (unsigned i = 0; i < m_osrExit.size(); ++i) {
+            OSRExitCompilationInfo& info = m_exitCompilationInfo[i];
             linkBuffer.link(info.m_patchableJump.m_jump, target);
             OSRExit& exit = m_osrExit[i];
             exit.m_patchableJumpLocation = linkBuffer.locationOf<JSInternalPtrTag>(info.m_patchableJump);
+            if (info.m_replacementSource.isSet()) {
+                jumpReplacements.append(JumpReplacement(
+                    linkBuffer.locationOf<JSInternalPtrTag>(info.m_replacementSource),
+                    linkBuffer.locationOf<OSRExitPtrTag>(info.m_replacementDestination)));
+            }
         }
+        m_jitCode->common.m_jumpReplacements = WTFMove(jumpReplacements);
+    }
 
-        if (info.m_replacementSource.isSet()) {
-            jumpReplacements.append(JumpReplacement(
-                linkBuffer.locationOf<JSInternalPtrTag>(info.m_replacementSource),
-                linkBuffer.locationOf<OSRExitPtrTag>(info.m_replacementDestination)));
-        }
+#if ASSERT_ENABLED
+    for (auto& info : m_exitCompilationInfo) {
+        if (info.m_replacementSource.isSet())
+            ASSERT(!m_graph.m_plan.isUnlinked());
     }
-    m_jitCode->common.m_jumpReplacements = WTFMove(jumpReplacements);
+    if (m_graph.m_plan.isUnlinked())
+        ASSERT(m_jitCode->common.m_jumpReplacements.isEmpty());
+#endif
     
     if (UNLIKELY(m_graph.compilation())) {
         ASSERT(m_exitSiteLabels.size() == m_osrExit.size());

Modified: trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -97,7 +97,8 @@
     ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
     ASSERT(codeBlock->alternative());
     ASSERT(codeBlock->alternative()->jitType() == JITType::BaselineJIT);
-    ASSERT(codeBlock->jitCode()->dfgCommon()->isStillValid);
+    ASSERT(codeBlock->jitCode()->dfgCommon()->isStillValid());
+    ASSERT(!codeBlock->isJettisoned());
 
     if (!Options::useOSREntryToDFG())
         return nullptr;
@@ -346,7 +347,8 @@
 MacroAssemblerCodePtr<ExceptionHandlerPtrTag> prepareCatchOSREntry(VM& vm, CallFrame* callFrame, CodeBlock* baselineCodeBlock, CodeBlock* optimizedCodeBlock, BytecodeIndex bytecodeIndex)
 {
     ASSERT(optimizedCodeBlock->jitType() == JITType::DFGJIT || optimizedCodeBlock->jitType() == JITType::FTLJIT);
-    ASSERT(optimizedCodeBlock->jitCode()->dfgCommon()->isStillValid);
+    ASSERT(optimizedCodeBlock->jitCode()->dfgCommon()->isStillValid());
+    ASSERT(!optimizedCodeBlock->isJettisoned());
 
     if (!Options::useOSREntryToDFG() && optimizedCodeBlock->jitCode()->jitType() == JITType::DFGJIT)
         return nullptr;

Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGPlan.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -554,8 +554,9 @@
             m_codeBlock->shrinkToFit(locker, CodeBlock::ShrinkMode::LateShrink);
         }
 
-        // Since Plan::reallyAdd could fire watchpoints (see ArrayBufferViewWatchpointAdaptor::add), it is possible that the current CodeBlock is now invalidated.
-        if (!m_codeBlock->jitCode()->dfgCommon()->isStillValid) {
+        // Since Plan::reallyAdd could fire watchpoints (see ArrayBufferViewWatchpointAdaptor::add),
+        // it is possible that the current CodeBlock is now invalidated & jettisoned.
+        if (m_codeBlock->isJettisoned()) {
             CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("invalidated"));
             return CompilationInvalidated;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -324,10 +324,20 @@
     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
 }
 
-void SpeculativeJIT::emitInvalidationPoint(Node* node)
+void SpeculativeJIT::compileInvalidationPoint(Node* node)
 {
     if (!m_compileOkay)
         return;
+
+#if USE(JSVALUE64)
+    if (m_graph.m_plan.isUnlinked()) {
+        auto exitJump = m_jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::Address(GPRInfo::constantsRegister, JITData::offsetOfIsInvalidated()));
+        speculationCheck(UncountableInvalidation, JSValueRegs(), nullptr, exitJump);
+        noResult(node);
+        return;
+    }
+#endif
+
     OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
     m_jit.appendOSRExit(OSRExit(
         UncountableInvalidation, JSValueSource(), MethodOfGettingAValueProfile(),
@@ -2497,7 +2507,7 @@
     
 void SpeculativeJIT::compileCheckTraps(Node* node)
 {
-    ASSERT(Options::usePollingTraps());
+    ASSERT(Options::usePollingTraps() || m_graph.m_plan.isUnlinked());
     GPRTemporary unused(this);
     GPRReg unusedGPR = unused.gpr();
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -1674,7 +1674,7 @@
     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
     void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
     
-    void emitInvalidationPoint(Node*);
+    void compileInvalidationPoint(Node*);
     
     void unreachable(Node*);
     

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -4024,7 +4024,7 @@
     }
 
     case InvalidationPoint:
-        emitInvalidationPoint(node);
+        compileInvalidationPoint(node);
         break;
 
     case CheckTraps:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -5434,7 +5434,7 @@
     }
         
     case InvalidationPoint:
-        emitInvalidationPoint(node);
+        compileInvalidationPoint(node);
         break;
 
     case CheckTraps:

Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -37,6 +37,7 @@
 
 JITCode::JITCode()
     : JSC::JITCode(JITType::FTLJIT)
+    , common(/* isUnlinked */ false)
 {
 }
 

Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.h (293713 => 293714)


--- trunk/Source/_javascript_Core/ftl/FTLJITCode.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -69,6 +69,8 @@
     static ptrdiff_t commonDataOffset() { return OBJECT_OFFSETOF(JITCode, common); }
     void shrinkToFit(const ConcurrentJSLocker&) override;
 
+    bool isUnlinked() const { return common.isUnlinked(); }
+
     PCToCodeOriginMap* pcToCodeOriginMap() override { return common.m_pcToCodeOriginMap.get(); }
 
     const RegisterAtOffsetList* calleeSaveRegisters() const { return &m_calleeSaveRegisters; }

Modified: trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -48,7 +48,7 @@
     DFG::JITCode* dfgCode = dfgCodeBlock->jitCode()->dfg();
     ForOSREntryJITCode* entryCode = entryCodeBlock->jitCode()->ftlForOSREntry();
 
-    if (!entryCode->dfgCommon()->isStillValid) {
+    if (!entryCode->dfgCommon()->isStillValid()) {
         dfgCode->clearOSREntryBlockAndResetThresholds(dfgCodeBlock);
         return nullptr;
     }

Modified: trunk/Source/_javascript_Core/jit/JITCode.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/jit/JITCode.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/jit/JITCode.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JITCode.h"
 
+#include "DFGJITCode.h"
 #include "FTLJITCode.h"
 
 #include <wtf/PrintStream.h>
@@ -65,6 +66,30 @@
     }
 }
 
+bool JITCode::isUnlinked() const
+{
+    switch (m_jitType) {
+    case JITType::None:
+    case JITType::HostCallThunk:
+    case JITType::InterpreterThunk:
+    case JITType::BaselineJIT:
+        return true;
+    case JITType::DFGJIT:
+#if ENABLE(DFG_JIT)
+        return static_cast<const DFG::JITCode*>(this)->isUnlinked();
+#else
+        return false;
+#endif
+    case JITType::FTLJIT:
+#if ENABLE(FTL_JIT)
+        return static_cast<const FTL::JITCode*>(this)->isUnlinked();
+#else
+        return false;
+#endif
+    }
+    return true;
+}
+
 void JITCode::validateReferences(const TrackedReferences&)
 {
 }

Modified: trunk/Source/_javascript_Core/jit/JITCode.h (293713 => 293714)


--- trunk/Source/_javascript_Core/jit/JITCode.h	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/jit/JITCode.h	2022-05-03 05:07:01 UTC (rev 293714)
@@ -189,6 +189,8 @@
     {
         return m_jitType;
     }
+
+    bool isUnlinked() const;
     
     template<typename PointerType>
     static JITType jitTypeFor(PointerType jitCode)

Modified: trunk/Source/_javascript_Core/runtime/VMTraps.cpp (293713 => 293714)


--- trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2022-05-03 04:38:50 UTC (rev 293713)
+++ trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2022-05-03 05:07:01 UTC (rev 293714)
@@ -145,7 +145,7 @@
         return;
     }
 
-    if (JITCode::isOptimizingJIT(foundCodeBlock->jitType())) {
+    if (foundCodeBlock->canInstallVMTrapBreakpoints()) {
         if (!m_lock->tryLock())
             return; // Let the SignalSender try again later.
 
@@ -155,7 +155,7 @@
             return;
         }
 
-        if (!foundCodeBlock->hasInstalledVMTrapBreakpoints())
+        if (!foundCodeBlock->hasInstalledVMTrapsBreakpoints())
             foundCodeBlock->installVMTrapBreakpoints();
         return;
     }
@@ -222,7 +222,7 @@
                     // Either we trapped for some other reason, e.g. Wasm OOB, or we didn't properly monitor the PC. Regardless, we can't do much now...
                     return SignalAction::NotHandled;
                 }
-                ASSERT(currentCodeBlock->hasInstalledVMTrapBreakpoints());
+                ASSERT(currentCodeBlock->hasInstalledVMTrapsBreakpoints());
                 VM& vm = currentCodeBlock->vm();
 
                 // This signal handler is triggered by the mutator thread due to the installed halt instructions
@@ -242,7 +242,7 @@
                 bool sawCurrentCodeBlock = false;
                 vm.heap.forEachCodeBlockIgnoringJITPlans(codeBlockSetLocker, [&] (CodeBlock* codeBlock) {
                     // We want to jettison all code blocks that have vm traps breakpoints, otherwise we could hit them later.
-                    if (codeBlock->hasInstalledVMTrapBreakpoints()) {
+                    if (codeBlock->hasInstalledVMTrapsBreakpoints()) {
                         if (currentCodeBlock == codeBlock)
                             sawCurrentCodeBlock = true;
 
@@ -379,7 +379,7 @@
         Locker codeBlockSetLocker { vm.heap.codeBlockSet().getLock() };
         vm.heap.forEachCodeBlockIgnoringJITPlans(codeBlockSetLocker, [&] (CodeBlock* codeBlock) {
             // We want to jettison all code blocks that have vm traps breakpoints, otherwise we could hit them later.
-            if (codeBlock->hasInstalledVMTrapBreakpoints())
+            if (codeBlock->hasInstalledVMTrapsBreakpoints())
                 codeBlock->jettison(Profiler::JettisonDueToVMTraps);
         });
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to