Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (119027 => 119028)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2012-05-31 03:04:00 UTC (rev 119028)
@@ -97,6 +97,7 @@
heap/HandleSet.cpp
heap/HandleStack.cpp
heap/Heap.cpp
+ heap/IncrementalSweeper.cpp
heap/MachineStackMarker.cpp
heap/MarkedAllocator.cpp
heap/MarkedBlock.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (119027 => 119028)
--- trunk/Source/_javascript_Core/ChangeLog 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-05-31 03:04:00 UTC (rev 119028)
@@ -1,3 +1,56 @@
+2012-05-30 Mark Hahnenberg <[email protected]>
+
+ Heap should sweep incrementally
+ https://bugs.webkit.org/show_bug.cgi?id=85429
+
+ We shouldn't have to wait for the opportunistic GC timer to fire in order
+ to call object destructors. Instead, we should incrementally sweep some
+ subset of the blocks requiring sweeping periodically. We tie this sweeping
+ to a timer rather than to collections because we want to reclaim this memory
+ even if we stop allocating. This way, our memory usage scales smoothly with
+ actual use, regardless of whether we've recently done an opportunistic GC or not.
+
+ Reviewed by Geoffrey Garen.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * _javascript_Core.gypi:
+ * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ (JSC::Heap::collect): We no longer sweep during a full sweep. We only shrink now,
+ which we will switch over to being done during incremental sweeping too as soon as
+ all finalizers can be run lazily (and, by extension, incrementally).
+ (JSC::Heap::sweeper):
+ (JSC):
+ * heap/Heap.h:
+ (JSC):
+ (Heap):
+ * heap/IncrementalSweeper.cpp: Added.
+ (JSC):
+ (JSC::IncrementalSweeper::timerDidFire): The IncrementalSweeper works very similarly to
+ GCActivityCallback. It is tied to a run-loop based timer that fires periodically based
+ on how long the previous sweep increment took to run. The IncrementalSweeper doesn't do
+ anything if the platform doesn't support CoreFoundation.
+ (JSC::IncrementalSweeper::IncrementalSweeper):
+ (JSC::IncrementalSweeper::~IncrementalSweeper):
+ (JSC::IncrementalSweeper::create):
+ (JSC::IncrementalSweeper::scheduleTimer):
+ (JSC::IncrementalSweeper::cancelTimer):
+ (JSC::IncrementalSweeper::doSweep): Iterates over the snapshot of the MarkedSpace taken
+ during the last collection, checking to see which blocks need sweeping. If it successfully
+ gets to the end of the blocks that need sweeping then it cancels the timer.
+ (JSC::IncrementalSweeper::startSweeping): We take a snapshot of the Heap and store it in
+ a Vector that the incremental sweep will iterate over. We also reset our index into this Vector.
+ * heap/IncrementalSweeper.h: Added.
+ (JSC):
+ (IncrementalSweeper):
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::needsSweeping): If a block is in the Marked state it needs sweeping
+ to be usable and to run any destructors that need to be run.
+
2012-05-30 Patrick Gansterer <[email protected]>
[WINCE] Fix JSString after r115516.
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (119027 => 119028)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-05-31 03:04:00 UTC (rev 119028)
@@ -232,6 +232,8 @@
Source/_javascript_Core/heap/HandleSet.cpp \
Source/_javascript_Core/heap/HandleSet.h \
Source/_javascript_Core/heap/HeapBlock.h \
+ Source/_javascript_Core/heap/IncrementalSweeper.h \
+ Source/_javascript_Core/heap/IncrementalSweeper.cpp \
Source/_javascript_Core/heap/SlotVisitor.h \
Source/_javascript_Core/heap/HandleStack.cpp \
Source/_javascript_Core/heap/HandleStack.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.gypi (119027 => 119028)
--- trunk/Source/_javascript_Core/_javascript_Core.gypi 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/_javascript_Core.gypi 2012-05-31 03:04:00 UTC (rev 119028)
@@ -134,6 +134,7 @@
'heap/Heap.h',
'heap/HeapBlock.h',
'heap/HeapRootVisitor.h',
+ 'heap/IncrementalSweeper.h',
'heap/ListableHandler.h',
'heap/Local.h',
'heap/LocalScope.h',
@@ -406,6 +407,7 @@
'heap/HandleStack.cpp',
'heap/BlockAllocator.cpp',
'heap/Heap.cpp',
+ 'heap/IncrementalSweeper.cpp',
'heap/MachineStackMarker.cpp',
'heap/MarkedAllocator.cpp',
'heap/MarkedBlock.cpp',
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj (119027 => 119028)
--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj 2012-05-31 03:04:00 UTC (rev 119028)
@@ -2158,6 +2158,14 @@
>
</File>
<File
+ RelativePath="..\..\heap\IncrementalSweeper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\IncrementalSweeper.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\heap\WeakBlock.cpp"
>
</File>
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (119027 => 119028)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-05-31 03:04:00 UTC (rev 119028)
@@ -637,6 +637,8 @@
BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; };
C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* CopiedSpace.cpp */; };
+ C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */; };
+ C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F8BCC157544A900245B71 /* IncrementalSweeper.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */; };
C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1331,6 +1333,8 @@
BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; };
BCFD8C910EEB2EE700283848 /* JumpTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpTable.h; sourceTree = "<group>"; };
C240305314B404C90079EB64 /* CopiedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopiedSpace.cpp; sourceTree = "<group>"; };
+ C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncrementalSweeper.cpp; sourceTree = "<group>"; };
+ C25F8BCC157544A900245B71 /* IncrementalSweeper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncrementalSweeper.h; sourceTree = "<group>"; };
C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedAllocator.h; sourceTree = "<group>"; };
C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkedAllocator.cpp; sourceTree = "<group>"; };
C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpaceInlineMethods.h; sourceTree = "<group>"; };
@@ -1609,6 +1613,8 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
+ C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */,
+ C25F8BCC157544A900245B71 /* IncrementalSweeper.h */,
14816E19154CC56C00B8054C /* BlockAllocator.cpp */,
14816E1A154CC56C00B8054C /* BlockAllocator.h */,
A7521E121429169A003C8D0C /* CardSet.h */,
@@ -2310,6 +2316,7 @@
86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */,
C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */,
+ C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */,
BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */,
@@ -3221,6 +3228,7 @@
0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */,
0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */,
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
+ C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: trunk/Source/_javascript_Core/Target.pri (119027 => 119028)
--- trunk/Source/_javascript_Core/Target.pri 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/Target.pri 2012-05-31 03:04:00 UTC (rev 119028)
@@ -78,6 +78,7 @@
heap/HandleStack.cpp \
heap/BlockAllocator.cpp \
heap/Heap.cpp \
+ heap/IncrementalSweeper.cpp \
heap/MachineStackMarker.cpp \
heap/MarkStack.cpp \
heap/MarkedAllocator.cpp \
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (119027 => 119028)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2012-05-31 03:04:00 UTC (rev 119028)
@@ -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 @@
, 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 @@
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 @@
return m_activityCallback.get();
}
+IncrementalSweeper* Heap::sweeper()
+{
+ return m_sweeper.get();
+}
+
void Heap::setGarbageCollectionTimerEnabled(bool enable)
{
activityCallback()->setEnabled(enable);
Modified: trunk/Source/_javascript_Core/heap/Heap.h (119027 => 119028)
--- trunk/Source/_javascript_Core/heap/Heap.h 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2012-05-31 03:04:00 UTC (rev 119028)
@@ -47,6 +47,7 @@
class GlobalCodeBlock;
class Heap;
class HeapRootVisitor;
+ class IncrementalSweeper;
class JSCell;
class JSGlobalData;
class JSValue;
@@ -100,6 +101,8 @@
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 @@
OwnPtr<HashSet<MarkedArgumentBuffer*> > m_markListSet;
OwnPtr<GCActivityCallback> m_activityCallback;
+ OwnPtr<IncrementalSweeper> m_sweeper;
MachineThreads m_machineThreads;
Added: trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp (0 => 119028)
--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp (rev 0)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp 2012-05-31 03:04:00 UTC (rev 119028)
@@ -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
Added: trunk/Source/_javascript_Core/heap/IncrementalSweeper.h (0 => 119028)
--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.h (rev 0)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.h 2012-05-31 03:04:00 UTC (rev 119028)
@@ -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
Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.h (119027 => 119028)
--- trunk/Source/_javascript_Core/heap/MarkedBlock.h 2012-05-31 02:58:48 UTC (rev 119027)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.h 2012-05-31 03:04:00 UTC (rev 119028)
@@ -157,6 +157,8 @@
bool isLiveCell(const void*);
void setMarked(const void*);
+ bool needsSweeping();
+
#if ENABLE(GGC)
void setDirtyObject(const void* atom)
{
@@ -416,6 +418,11 @@
}
}
+ inline bool MarkedBlock::needsSweeping()
+ {
+ return m_state == Marked;
+ }
+
#if ENABLE(GGC)
template <int _cellSize> void MarkedBlock::gatherDirtyCellsWithSize(DirtyCellVector& dirtyCells)
{