- Revision
- 277027
- Author
- [email protected]
- Date
- 2021-05-05 10:28:13 -0700 (Wed, 05 May 2021)
Log Message
Enable incremental sweeping of GCAwareJITStubRoutines.
https://bugs.webkit.org/show_bug.cgi?id=225376
Reviewed by Filip Pizlo.
This patch makes the following changes:
1. Enhance JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() to be able to
run in an incremental time slice.
2. Added JITStubRoutineSet::notifyHaveRoutinesToDelete() so that
GCAwareJITStubRoutine::observeZeroRefCount() can flag that the GC may have
some dead GCAwareJITStubRoutines to delete.
3. Added JITStubRoutineSet::mayHaveRoutinesToDelete() so that clients can do
a cheap check ahead of time to determine if there's work to do, and avoid
calling JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() altogether
if not needed.
4. Added Heap::mayHaveJITStubRoutinesToDelete() and Heap::deleteDeadJITStubRoutines()
as wrappers around JITStubRoutineSet::mayHaveRoutinesToDelete() and
JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() because the use of
the JITStubRoutineSet is a heap internal implementation detail.
5. Enhanced the IncrementalSweeper to also call Heap::deleteDeadJITStubRoutines()
if needed.
6. Enhanced Heap::sweepSynchronously() to also call Heap::deleteDeadJITStubRoutines()
if needed.
7. Time slices for Heap::deleteDeadJITStubRoutines() is currently set at the
current values:
a. max of 1 ms (1/10 of the IncreamentalSweeper's time slice) when invoked from
the IncreamentalSweeper.
b. max of 5 ms when invoked from Heap::deleteUnmarkedCompiledCode().
c. unlimited time (with a sanity check) when called from Heap::sweepSynchronously().
The choices of 1ms and 5ms were picked to not be too long, but would still delete
the bulk of the dead GCAwareJITStubRoutines quickly enough based on data from my
instrumented runs the CLI version of JetStream2.
I think these hardcoded values will do for now. If need be, we can try something
more sophisticated later.
* CMakeLists.txt:
* heap/Heap.cpp:
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::sweepSynchronously):
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::mayHaveJITStubRoutinesToDelete):
(JSC::Heap::deleteDeadJITStubRoutines):
* heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::doSweep):
* heap/JITStubRoutineSet.cpp:
(JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
* heap/JITStubRoutineSet.h:
(JSC::JITStubRoutineSet::mayHaveRoutinesToDelete):
(JSC::JITStubRoutineSet::notifyHaveRoutinesToDelete):
(JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
* jit/GCAwareJITStubRoutine.cpp:
(JSC::GCAwareJITStubRoutine::observeZeroRefCount):
* jit/JITStubRoutine.h:
(JSC::JITStubRoutine::createSelfManagedRoutine): Deleted.
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (277026 => 277027)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2021-05-05 17:28:13 UTC (rev 277027)
@@ -672,6 +672,7 @@
heap/IsoSubspace.h
heap/IsoSubspaceInlines.h
heap/IsoSubspacePerVM.h
+ heap/JITStubRoutineSet.h
heap/LocalAllocator.h
heap/LocalAllocatorInlines.h
heap/LockDuringMarking.h
Modified: trunk/Source/_javascript_Core/ChangeLog (277026 => 277027)
--- trunk/Source/_javascript_Core/ChangeLog 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-05-05 17:28:13 UTC (rev 277027)
@@ -1,3 +1,70 @@
+2021-05-05 Mark Lam <[email protected]>
+
+ Enable incremental sweeping of GCAwareJITStubRoutines.
+ https://bugs.webkit.org/show_bug.cgi?id=225376
+
+ Reviewed by Filip Pizlo.
+
+ This patch makes the following changes:
+
+ 1. Enhance JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() to be able to
+ run in an incremental time slice.
+
+ 2. Added JITStubRoutineSet::notifyHaveRoutinesToDelete() so that
+ GCAwareJITStubRoutine::observeZeroRefCount() can flag that the GC may have
+ some dead GCAwareJITStubRoutines to delete.
+
+ 3. Added JITStubRoutineSet::mayHaveRoutinesToDelete() so that clients can do
+ a cheap check ahead of time to determine if there's work to do, and avoid
+ calling JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() altogether
+ if not needed.
+
+ 4. Added Heap::mayHaveJITStubRoutinesToDelete() and Heap::deleteDeadJITStubRoutines()
+ as wrappers around JITStubRoutineSet::mayHaveRoutinesToDelete() and
+ JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() because the use of
+ the JITStubRoutineSet is a heap internal implementation detail.
+
+ 5. Enhanced the IncrementalSweeper to also call Heap::deleteDeadJITStubRoutines()
+ if needed.
+
+ 6. Enhanced Heap::sweepSynchronously() to also call Heap::deleteDeadJITStubRoutines()
+ if needed.
+
+ 7. Time slices for Heap::deleteDeadJITStubRoutines() is currently set at the
+ current values:
+ a. max of 1 ms (1/10 of the IncreamentalSweeper's time slice) when invoked from
+ the IncreamentalSweeper.
+ b. max of 5 ms when invoked from Heap::deleteUnmarkedCompiledCode().
+ c. unlimited time (with a sanity check) when called from Heap::sweepSynchronously().
+
+ The choices of 1ms and 5ms were picked to not be too long, but would still delete
+ the bulk of the dead GCAwareJITStubRoutines quickly enough based on data from my
+ instrumented runs the CLI version of JetStream2.
+
+ I think these hardcoded values will do for now. If need be, we can try something
+ more sophisticated later.
+
+ * CMakeLists.txt:
+ * heap/Heap.cpp:
+ (JSC::Heap::deleteUnmarkedCompiledCode):
+ (JSC::Heap::sweepSynchronously):
+ * heap/Heap.h:
+ * heap/HeapInlines.h:
+ (JSC::Heap::mayHaveJITStubRoutinesToDelete):
+ (JSC::Heap::deleteDeadJITStubRoutines):
+ * heap/IncrementalSweeper.cpp:
+ (JSC::IncrementalSweeper::doSweep):
+ * heap/JITStubRoutineSet.cpp:
+ (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
+ * heap/JITStubRoutineSet.h:
+ (JSC::JITStubRoutineSet::mayHaveRoutinesToDelete):
+ (JSC::JITStubRoutineSet::notifyHaveRoutinesToDelete):
+ (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
+ * jit/GCAwareJITStubRoutine.cpp:
+ (JSC::GCAwareJITStubRoutine::observeZeroRefCount):
+ * jit/JITStubRoutine.h:
+ (JSC::JITStubRoutine::createSelfManagedRoutine): Deleted.
+
2021-05-03 Mark Lam <[email protected]>
Fix syntax error message for AUTOPLUSPLUS token.
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2021-05-05 17:28:13 UTC (rev 277027)
@@ -973,7 +973,8 @@
// Sweeping must occur before deleting stubs, otherwise the stubs might still think they're alive as they get deleted.
// And CodeBlock destructor is assuming that CodeBlock gets destroyed before UnlinkedCodeBlock gets destroyed.
vm().forEachCodeBlockSpace([] (auto& space) { space.space.sweep(); });
- m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines();
+ if (mayHaveJITStubRoutinesToDelete())
+ deleteDeadJITStubRoutines(5_ms);
}
void Heap::addToRememberedSet(const JSCell* constCell)
@@ -1040,6 +1041,14 @@
}
m_objectSpace.sweepBlocks();
m_objectSpace.shrink();
+
+ unsigned passes = 0;
+ while (mayHaveJITStubRoutinesToDelete()) {
+ constexpr Seconds unlimitedTime = 600_s;
+ deleteDeadJITStubRoutines(unlimitedTime);
+ RELEASE_ASSERT(passes++ < 100);
+ }
+
if (UNLIKELY(Options::logGC())) {
MonotonicTime after = MonotonicTime::now();
dataLog("=> ", capacity() / 1024, "kb, ", (after - before).milliseconds(), "ms");
Modified: trunk/Source/_javascript_Core/heap/Heap.h (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/Heap.h 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2021-05-05 17:28:13 UTC (rev 277027)
@@ -406,6 +406,9 @@
bool isMarkingForGCVerifier() const { return m_isMarkingForGCVerifier; }
+ static bool mayHaveJITStubRoutinesToDelete();
+ void deleteDeadJITStubRoutines(Seconds timeSlice);
+
private:
friend class AllocatingScope;
friend class CodeBlock;
Modified: trunk/Source/_javascript_Core/heap/HeapInlines.h (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/HeapInlines.h 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/HeapInlines.h 2021-05-05 17:28:13 UTC (rev 277027)
@@ -29,6 +29,7 @@
#include "Heap.h"
#include "HeapCellInlines.h"
#include "IndexingHeader.h"
+#include "JITStubRoutineSet.h"
#include "JSCast.h"
#include "Structure.h"
#include <type_traits>
@@ -279,4 +280,14 @@
func(*visitor);
}
+inline bool Heap::mayHaveJITStubRoutinesToDelete()
+{
+ return JITStubRoutineSet::mayHaveRoutinesToDelete();
+}
+
+inline void Heap::deleteDeadJITStubRoutines(Seconds timeSlice)
+{
+ m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines(timeSlice);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp 2021-05-05 17:28:13 UTC (rev 277027)
@@ -36,6 +36,7 @@
static constexpr Seconds sweepTimeSlice = 10_ms;
static constexpr double sweepTimeTotal = .10;
static constexpr double sweepTimeMultiplier = 1.0 / sweepTimeTotal;
+static constexpr Seconds deleteJITStubRoutinesTimeSlice = std::min(sweepTimeSlice / 10, 1_ms);
void IncrementalSweeper::scheduleTimer()
{
@@ -55,7 +56,17 @@
void IncrementalSweeper::doSweep(VM& vm, MonotonicTime sweepBeginTime)
{
- while (sweepNextBlock(vm)) {
+ bool hasMoreBlocksToSweep = true;
+ bool hasMoreWork = true;
+ while (hasMoreWork) {
+ if (hasMoreBlocksToSweep)
+ hasMoreBlocksToSweep = sweepNextBlock(vm);
+
+ if (Heap::mayHaveJITStubRoutinesToDelete())
+ vm.heap.deleteDeadJITStubRoutines(deleteJITStubRoutinesTimeSlice);
+
+ hasMoreWork = hasMoreBlocksToSweep || Heap::mayHaveJITStubRoutinesToDelete();
+
Seconds elapsedTime = MonotonicTime::now() - sweepBeginTime;
if (elapsedTime < sweepTimeSlice)
continue;
Modified: trunk/Source/_javascript_Core/heap/JITStubRoutineSet.cpp (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/JITStubRoutineSet.cpp 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/JITStubRoutineSet.cpp 2021-05-05 17:28:13 UTC (rev 277027)
@@ -29,9 +29,14 @@
#if ENABLE(JIT)
#include "GCAwareJITStubRoutine.h"
+#include <algorithm>
namespace JSC {
+using WTF::Range;
+
+bool JITStubRoutineSet::s_mayHaveRoutinesToDelete = false;
+
JITStubRoutineSet::JITStubRoutineSet() { }
JITStubRoutineSet::~JITStubRoutineSet()
{
@@ -113,19 +118,46 @@
}
}
-void JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines()
+void JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines(Seconds timeSlice)
{
+ ASSERT(s_mayHaveRoutinesToDelete);
+
+ MonotonicTime startTime = MonotonicTime::now();
+ Seconds elapsedTime;
+ constexpr unsigned maxBatchSize = 100;
+
+ unsigned endIndex = m_routines.size();
+
+ // Clear the s_mayHaveRoutinesToDelete flag before we start.
+ // Destruction of a MarkingGCAwareJITStubRoutine can trigger more routines
+ // to be deleted, and some of those may be the ones we have already iterated
+ // pass.
+ s_mayHaveRoutinesToDelete = false;
+
unsigned srcIndex = 0;
- unsigned dstIndex = srcIndex;
- while (srcIndex < m_routines.size()) {
- Routine routine = m_routines[srcIndex++];
- if (!routine.routine->m_isJettisoned || routine.routine->m_mayBeExecuting) {
- m_routines[dstIndex++] = routine;
- continue;
+ while (srcIndex < endIndex) {
+ unsigned batchSize = std::min<unsigned>(maxBatchSize, endIndex - srcIndex);
+ while (batchSize--) {
+ Routine routine = m_routines[srcIndex];
+ if (!routine.routine->m_isJettisoned || routine.routine->m_mayBeExecuting) {
+ srcIndex++;
+ continue;
+ }
+ m_routines[srcIndex] = m_routines[--endIndex];
+
+ routine.routine->deleteFromGC();
}
- routine.routine->deleteFromGC();
+
+ elapsedTime = MonotonicTime::now() - startTime;
+ if (elapsedTime > timeSlice) {
+ // We timed out. Assume there's more to do, and that we should check
+ // again next time slice.
+ s_mayHaveRoutinesToDelete = true;
+ break;
+ }
}
- m_routines.shrinkCapacity(dstIndex);
+
+ m_routines.shrinkCapacity(endIndex);
}
template<typename Visitor>
Modified: trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h (277026 => 277027)
--- trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h 2021-05-05 17:28:13 UTC (rev 277027)
@@ -31,8 +31,6 @@
#include <wtf/Range.h>
#include <wtf/Vector.h>
-using WTF::Range;
-
namespace JSC {
class GCAwareJITStubRoutine;
@@ -61,10 +59,13 @@
void prepareForConservativeScan();
- void deleteUnmarkedJettisonedStubRoutines();
+ void deleteUnmarkedJettisonedStubRoutines(Seconds timeSlice);
template<typename Visitor> void traceMarkedStubRoutines(Visitor&);
-
+
+ static bool mayHaveRoutinesToDelete() { return s_mayHaveRoutinesToDelete; }
+ static void notifyHaveRoutinesToDelete() { s_mayHaveRoutinesToDelete = true; }
+
private:
void markSlow(uintptr_t address);
@@ -73,7 +74,9 @@
GCAwareJITStubRoutine* routine;
};
Vector<Routine> m_routines;
- Range<uintptr_t> m_range { 0, 0 };
+ WTF::Range<uintptr_t> m_range { 0, 0 };
+
+ static bool s_mayHaveRoutinesToDelete;
};
#else // !ENABLE(JIT)
@@ -90,8 +93,11 @@
void clearMarks() { }
void mark(void*) { }
void prepareForConservativeScan() { }
- void deleteUnmarkedJettisonedStubRoutines() { }
+ void deleteUnmarkedJettisonedStubRoutines(Seconds) { }
template<typename Visitor> void traceMarkedStubRoutines(Visitor&) { }
+
+ static bool mayHaveRoutinesToDelete() { return false; }
+ static void notifyHaveRoutinesToDelete() { }
};
#endif // !ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp (277026 => 277027)
--- trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp 2021-05-05 17:28:13 UTC (rev 277027)
@@ -62,6 +62,7 @@
RELEASE_ASSERT(!m_refCount);
m_isJettisoned = true;
+ JITStubRoutineSet::notifyHaveRoutinesToDelete();
}
void GCAwareJITStubRoutine::deleteFromGC()
Modified: trunk/Source/_javascript_Core/jit/JITStubRoutine.h (277026 => 277027)
--- trunk/Source/_javascript_Core/jit/JITStubRoutine.h 2021-05-05 17:00:50 UTC (rev 277026)
+++ trunk/Source/_javascript_Core/jit/JITStubRoutine.h 2021-05-05 17:28:13 UTC (rev 277027)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,14 +55,6 @@
{
}
- // Use this if you want to pass a CodePtr to someone who insists on taking
- // a RefPtr<JITStubRoutine>.
- static Ref<JITStubRoutine> createSelfManagedRoutine(
- MacroAssemblerCodePtr<JITStubRoutinePtrTag> rawCodePointer)
- {
- return adoptRef(*new JITStubRoutine(MacroAssemblerCodeRef<JITStubRoutinePtrTag>::createSelfManagedCodeRef(rawCodePointer)));
- }
-
virtual ~JITStubRoutine();
virtual void aboutToDie() { }