Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (155316 => 155317)
--- trunk/Source/_javascript_Core/ChangeLog 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-09-09 00:11:57 UTC (rev 155317)
@@ -1,5 +1,37 @@
2013-09-08 Mark Hahnenberg <[email protected]>
+ Calculating the size of the Heap should not require walking over it
+ https://bugs.webkit.org/show_bug.cgi?id=120910
+
+ Reviewed by Geoffrey Garen.
+
+ Currently Heap::size() is O(sizeof(Heap)). This is too expensive to
+ call during a collection. We should keep a count of visited and copied
+ bytes as each collection progresses so as to avoid re-walking the Heap
+ at the end of collection.
+
+ * heap/GCThreadSharedData.cpp:
+ (JSC::GCThreadSharedData::childBytesVisited):
+ (JSC::GCThreadSharedData::childBytesCopied):
+ * heap/GCThreadSharedData.h:
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ (JSC::Heap::markRoots):
+ (JSC::Heap::sizeAfterCollect):
+ (JSC::Heap::collect):
+ * heap/Heap.h:
+ * heap/SlotVisitor.cpp:
+ (JSC::SlotVisitor::SlotVisitor):
+ (JSC::SlotVisitor::reset):
+ * heap/SlotVisitor.h:
+ (JSC::SlotVisitor::bytesVisited):
+ (JSC::SlotVisitor::bytesCopied):
+ * heap/SlotVisitorInlines.h:
+ (JSC::SlotVisitor::internalAppend):
+ (JSC::SlotVisitor::copyLater):
+
+2013-09-08 Mark Hahnenberg <[email protected]>
+
Clearing MarkedBlock::m_newlyAllocated should be separate from MarkedBlock::clearMarks
https://bugs.webkit.org/show_bug.cgi?id=121007
Modified: trunk/Source/_javascript_Core/heap/GCThreadSharedData.cpp (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/GCThreadSharedData.cpp 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/GCThreadSharedData.cpp 2013-09-09 00:11:57 UTC (rev 155317)
@@ -50,6 +50,22 @@
result += m_gcThreads[i]->slotVisitor()->visitCount();
return result;
}
+
+size_t GCThreadSharedData::childBytesVisited()
+{
+ size_t result = 0;
+ for (unsigned i = 0; i < m_gcThreads.size(); ++i)
+ result += m_gcThreads[i]->slotVisitor()->bytesVisited();
+ return result;
+}
+
+size_t GCThreadSharedData::childBytesCopied()
+{
+ size_t result = 0;
+ for (unsigned i = 0; i < m_gcThreads.size(); ++i)
+ result += m_gcThreads[i]->slotVisitor()->bytesCopied();
+ return result;
+}
#endif
GCThreadSharedData::GCThreadSharedData(VM* vm)
Modified: trunk/Source/_javascript_Core/heap/GCThreadSharedData.h (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/GCThreadSharedData.h 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/GCThreadSharedData.h 2013-09-09 00:11:57 UTC (rev 155317)
@@ -65,6 +65,8 @@
#if ENABLE(PARALLEL_GC)
void resetChildren();
size_t childVisitCount();
+ size_t childBytesVisited();
+ size_t childBytesCopied();
size_t childDupStrings();
#endif
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2013-09-09 00:11:57 UTC (rev 155317)
@@ -251,6 +251,8 @@
, m_bytesAllocatedLimit(m_minBytesPerCycle)
, m_bytesAllocated(0)
, m_bytesAbandoned(0)
+ , m_totalBytesVisited(0)
+ , m_totalBytesCopied(0)
, m_operationInProgress(NoOperation)
, m_blockAllocator()
, m_objectSpace(this)
@@ -591,6 +593,13 @@
MARK_LOG_MESSAGE2("\nNumber of live Objects after full GC %lu, took %.6f secs\n", visitCount, WTF::monotonicallyIncreasingTime() - gcStartTime);
#endif
+ m_totalBytesVisited = visitor.bytesVisited();
+ m_totalBytesCopied = visitor.bytesCopied();
+#if ENABLE(PARALLEL_GC)
+ m_totalBytesVisited += m_sharedData.childBytesVisited();
+ m_totalBytesCopied += m_sharedData.childBytesCopied();
+#endif
+
visitor.reset();
#if ENABLE(PARALLEL_GC)
m_sharedData.resetChildren();
@@ -634,6 +643,16 @@
return m_objectSpace.capacity() + m_storageSpace.capacity() + extraSize();
}
+size_t Heap::sizeAfterCollect()
+{
+ // The result here may not agree with the normal Heap::size().
+ // This is due to the fact that we only count live copied bytes
+ // rather than all used (including dead) copied bytes, thus it's
+ // always the case that m_totalBytesCopied <= m_storageSpace.size().
+ ASSERT(m_totalBytesCopied <= m_storageSpace.size());
+ return m_totalBytesVisited + m_totalBytesCopied + extraSize();
+}
+
size_t Heap::protectedGlobalObjectCount()
{
return forEachProtectedCell<CountIfGlobalObject>();
@@ -798,7 +817,7 @@
m_objectSpace.resetAllocators();
}
- size_t currentHeapSize = size();
+ size_t currentHeapSize = sizeAfterCollect();
if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
HeapStatistics::exitWithFailure();
Modified: trunk/Source/_javascript_Core/heap/Heap.h (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/Heap.h 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2013-09-09 00:11:57 UTC (rev 155317)
@@ -232,6 +232,8 @@
void zombifyDeadObjects();
void markDeadObjects();
+ size_t sizeAfterCollect();
+
JSStack& stack();
BlockAllocator& blockAllocator();
@@ -247,6 +249,9 @@
size_t m_bytesAllocatedLimit;
size_t m_bytesAllocated;
size_t m_bytesAbandoned;
+
+ size_t m_totalBytesVisited;
+ size_t m_totalBytesCopied;
OperationInProgress m_operationInProgress;
BlockAllocator m_blockAllocator;
Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.cpp (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/SlotVisitor.cpp 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.cpp 2013-09-09 00:11:57 UTC (rev 155317)
@@ -18,6 +18,8 @@
SlotVisitor::SlotVisitor(GCThreadSharedData& shared)
: m_stack(shared.m_vm->heap.blockAllocator())
+ , m_bytesVisited(0)
+ , m_bytesCopied(0)
, m_visitCount(0)
, m_isInParallelMode(false)
, m_shared(shared)
@@ -46,6 +48,8 @@
void SlotVisitor::reset()
{
+ m_bytesVisited = 0;
+ m_bytesCopied = 0;
m_visitCount = 0;
ASSERT(m_stack.isEmpty());
#if ENABLE(PARALLEL_GC)
Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.h (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/SlotVisitor.h 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.h 2013-09-09 00:11:57 UTC (rev 155317)
@@ -72,6 +72,8 @@
void setup();
void reset();
+ size_t bytesVisited() const { return m_bytesVisited; }
+ size_t bytesCopied() const { return m_bytesCopied; }
size_t visitCount() const { return m_visitCount; }
void donate();
@@ -123,6 +125,8 @@
MarkStackArray m_stack;
HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
+ size_t m_bytesVisited;
+ size_t m_bytesCopied;
size_t m_visitCount;
bool m_isInParallelMode;
Modified: trunk/Source/_javascript_Core/heap/SlotVisitorInlines.h (155316 => 155317)
--- trunk/Source/_javascript_Core/heap/SlotVisitorInlines.h 2013-09-08 23:36:40 UTC (rev 155316)
+++ trunk/Source/_javascript_Core/heap/SlotVisitorInlines.h 2013-09-09 00:11:57 UTC (rev 155317)
@@ -100,6 +100,7 @@
if (Heap::testAndSetMarked(cell) || !cell->structure())
return;
+ m_bytesVisited += MarkedBlock::blockFor(cell)->cellSize();
m_visitCount++;
MARK_LOG_CHILD(*this, cell);
@@ -211,6 +212,8 @@
inline void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes)
{
ASSERT(bytes);
+ m_bytesCopied += bytes;
+
CopiedBlock* block = CopiedSpace::blockFor(ptr);
if (block->isOversize()) {
m_shared.m_copiedSpace->pin(block);