summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/heap')
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp11
-rw-r--r--Source/JavaScriptCore/heap/Heap.h8
-rw-r--r--Source/JavaScriptCore/heap/IncrementalSweeper.cpp107
-rw-r--r--Source/JavaScriptCore/heap/IncrementalSweeper.h51
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.h7
5 files changed, 181 insertions, 3 deletions
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index 9b68fb10a..90c4bb72c 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -27,6 +27,7 @@
#include "ConservativeRoots.h"
#include "GCActivityCallback.h"
#include "HeapRootVisitor.h"
+#include "IncrementalSweeper.h"
#include "Interpreter.h"
#include "JSGlobalData.h"
#include "JSGlobalObject.h"
@@ -245,6 +246,7 @@ Heap::Heap(JSGlobalData* globalData, HeapType heapType)
, m_objectSpace(this)
, m_storageSpace(this)
, m_activityCallback(DefaultGCActivityCallback::create(this))
+ , m_sweeper(IncrementalSweeper::create(this))
, m_machineThreads(this)
, m_sharedData(globalData)
, m_slotVisitor(m_sharedData)
@@ -703,9 +705,11 @@ void Heap::collect(SweepToggle sweepToggle)
GCPHASE(Sweeping);
m_objectSpace.sweep();
m_objectSpace.shrink();
- m_bytesAbandoned = 0;
}
+ m_sweeper->startSweeping(m_objectSpace.blocks().set());
+ m_bytesAbandoned = 0;
+
{
GCPHASE(ResetAllocators);
m_objectSpace.resetAllocators();
@@ -737,6 +741,11 @@ GCActivityCallback* Heap::activityCallback()
return m_activityCallback.get();
}
+IncrementalSweeper* Heap::sweeper()
+{
+ return m_sweeper.get();
+}
+
void Heap::setGarbageCollectionTimerEnabled(bool enable)
{
activityCallback()->setEnabled(enable);
diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h
index edfd91483..296447d7b 100644
--- a/Source/JavaScriptCore/heap/Heap.h
+++ b/Source/JavaScriptCore/heap/Heap.h
@@ -47,6 +47,7 @@ namespace JSC {
class GlobalCodeBlock;
class Heap;
class HeapRootVisitor;
+ class IncrementalSweeper;
class JSCell;
class JSGlobalData;
class JSValue;
@@ -100,6 +101,8 @@ namespace JSC {
JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>);
JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
+ IncrementalSweeper* sweeper();
+
// true if an allocation or collection is in progress
inline bool isBusy();
@@ -217,6 +220,7 @@ namespace JSC {
OwnPtr<HashSet<MarkedArgumentBuffer*> > m_markListSet;
OwnPtr<GCActivityCallback> m_activityCallback;
+ OwnPtr<IncrementalSweeper> m_sweeper;
MachineThreads m_machineThreads;
@@ -240,9 +244,9 @@ namespace JSC {
inline bool Heap::shouldCollect()
{
#if ENABLE(GGC)
- return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect;
+ return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect && m_operationInProgress == NoOperation;
#else
- return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect;
+ return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect && m_operationInProgress == NoOperation;
#endif
}
diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
new file mode 100644
index 000000000..08a9f6c73
--- /dev/null
+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
@@ -0,0 +1,107 @@
+#include "config.h"
+#include "IncrementalSweeper.h"
+
+#include "APIShims.h"
+#include "Heap.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "MarkedBlock.h"
+#include "ScopeChain.h"
+#include <wtf/HashSet.h>
+#include <wtf/WTFThreadData.h>
+
+namespace JSC {
+
+#if USE(CF)
+
+static const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
+static const CFTimeInterval sweepTimeSlicePerBlock = 0.01;
+static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeSlicePerBlock;
+
+void IncrementalSweeper::timerDidFire(CFRunLoopTimerRef, void* info)
+{
+ Heap* heap = static_cast<Heap*>(info);
+ APIEntryShim shim(heap->globalData());
+ heap->sweeper()->doSweep(WTF::monotonicallyIncreasingTime());
+}
+
+IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
+ : m_heap(heap)
+ , m_currentBlockToSweepIndex(0)
+ , m_lengthOfLastSweepIncrement(0.0)
+{
+ memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
+ m_context.info = m_heap;
+ m_runLoop = runLoop;
+ m_timer.adoptCF(CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent(), decade, 0, 0, &timerDidFire, &m_context));
+ CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+}
+
+IncrementalSweeper::~IncrementalSweeper()
+{
+ CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+ CFRunLoopTimerInvalidate(m_timer.get());
+}
+
+PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
+{
+ return adoptPtr(new IncrementalSweeper(heap, CFRunLoopGetCurrent()));
+}
+
+void IncrementalSweeper::scheduleTimer()
+{
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + (m_lengthOfLastSweepIncrement * sweepTimeMultiplier));
+}
+
+void IncrementalSweeper::cancelTimer()
+{
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + decade);
+}
+
+void IncrementalSweeper::doSweep(double sweepBeginTime)
+{
+ for (; m_currentBlockToSweepIndex < m_blocksToSweep.size(); m_currentBlockToSweepIndex++) {
+ MarkedBlock* nextBlock = m_blocksToSweep[m_currentBlockToSweepIndex];
+ if (!nextBlock->needsSweeping())
+ continue;
+
+ nextBlock->sweep();
+ m_blocksToSweep[m_currentBlockToSweepIndex++] = 0;
+ m_lengthOfLastSweepIncrement = WTF::monotonicallyIncreasingTime() - sweepBeginTime;
+ scheduleTimer();
+ return;
+ }
+
+ m_blocksToSweep.clear();
+ cancelTimer();
+}
+
+void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot)
+{
+ WTF::copyToVector(blockSnapshot, m_blocksToSweep);
+ m_currentBlockToSweepIndex = 0;
+ scheduleTimer();
+}
+
+#else
+
+IncrementalSweeper::IncrementalSweeper()
+{
+}
+
+IncrementalSweeper::~IncrementalSweeper()
+{
+}
+
+PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap*)
+{
+ return adoptPtr(new IncrementalSweeper());
+}
+
+void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
+{
+}
+
+#endif
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.h b/Source/JavaScriptCore/heap/IncrementalSweeper.h
new file mode 100644
index 000000000..48f040409
--- /dev/null
+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.h
@@ -0,0 +1,51 @@
+#ifndef IncrementalSweeper_h
+#define IncrementalSweeper_h
+
+#include "MarkedBlock.h"
+#include <wtf/HashSet.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+#if USE(CF)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace JSC {
+
+class Heap;
+
+class IncrementalSweeper {
+public:
+ ~IncrementalSweeper();
+
+ static PassOwnPtr<IncrementalSweeper> create(Heap*);
+ void startSweeping(const HashSet<MarkedBlock*>& blockSnapshot);
+
+private:
+#if USE(CF)
+ IncrementalSweeper(Heap*, CFRunLoopRef);
+
+ static void timerDidFire(CFRunLoopTimerRef, void*);
+ void doSweep(double startTime);
+ void scheduleTimer();
+ void cancelTimer();
+
+ Heap* m_heap;
+ unsigned m_currentBlockToSweepIndex;
+ RetainPtr<CFRunLoopTimerRef> m_timer;
+ RetainPtr<CFRunLoopRef> m_runLoop;
+ CFRunLoopTimerContext m_context;
+
+ double m_lengthOfLastSweepIncrement;
+ Vector<MarkedBlock*> m_blocksToSweep;
+#else
+
+ IncrementalSweeper();
+
+#endif
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h
index c21e20b19..b94c1e2b0 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.h
+++ b/Source/JavaScriptCore/heap/MarkedBlock.h
@@ -157,6 +157,8 @@ namespace JSC {
bool isLiveCell(const void*);
void setMarked(const void*);
+ bool needsSweeping();
+
#if ENABLE(GGC)
void setDirtyObject(const void* atom)
{
@@ -416,6 +418,11 @@ namespace JSC {
}
}
+ inline bool MarkedBlock::needsSweeping()
+ {
+ return m_state == Marked;
+ }
+
#if ENABLE(GGC)
template <int _cellSize> void MarkedBlock::gatherDirtyCellsWithSize(DirtyCellVector& dirtyCells)
{