diff options
Diffstat (limited to 'Source/JavaScriptCore/heap')
-rw-r--r-- | Source/JavaScriptCore/heap/Heap.cpp | 11 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/Heap.h | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/IncrementalSweeper.cpp | 107 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/IncrementalSweeper.h | 51 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/MarkedBlock.h | 7 |
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) { |