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);
});
}