summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
commit43a42f108af6bcbd91f2672731c3047c26213af1 (patch)
tree7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/heap
parentd9cf437c840c6eb7417bdd97e6c40979255d3158 (diff)
downloadqtwebkit-43a42f108af6bcbd91f2672731c3047c26213af1.tar.gz
Imported WebKit commit 302e7806bff028bd1167a1ec7c86a1ee00ecfb49 (http://svn.webkit.org/repository/webkit/trunk@132067)
New snapshot that fixes build without QtWidgets
Diffstat (limited to 'Source/JavaScriptCore/heap')
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpace.cpp49
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h1
-rw-r--r--Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h4
-rw-r--r--Source/JavaScriptCore/heap/GCThread.cpp10
-rw-r--r--Source/JavaScriptCore/heap/GCThreadSharedData.cpp57
-rw-r--r--Source/JavaScriptCore/heap/GCThreadSharedData.h5
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp7
-rw-r--r--Source/JavaScriptCore/heap/SlotVisitor.cpp10
8 files changed, 93 insertions, 50 deletions
diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp
index cedafee3a..c228f9460 100644
--- a/Source/JavaScriptCore/heap/CopiedSpace.cpp
+++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp
@@ -173,6 +173,7 @@ void CopiedSpace::doneFillingBlock(CopiedBlock* block, CopiedBlock** exchange)
{
MutexLocker locker(m_loanedBlocksLock);
ASSERT(m_numberOfLoanedBlocks > 0);
+ ASSERT(m_inCopyingPhase);
m_numberOfLoanedBlocks--;
if (!m_numberOfLoanedBlocks)
m_loanedBlocksCondition.signal();
@@ -199,6 +200,22 @@ void CopiedSpace::startedCopying()
totalUsableBytes += block->payloadCapacity();
}
+ CopiedBlock* block = m_oversizeBlocks.head();
+ while (block) {
+ CopiedBlock* next = block->next();
+ if (block->isPinned()) {
+ m_blockFilter.add(reinterpret_cast<Bits>(block));
+ totalLiveBytes += block->payloadCapacity();
+ totalUsableBytes += block->payloadCapacity();
+ block->didSurviveGC();
+ } else {
+ m_oversizeBlocks.remove(block);
+ m_blockSet.remove(block);
+ m_heap->blockAllocator().deallocateCustomSize(CopiedBlock::destroy(block));
+ }
+ block = next;
+ }
+
double markedSpaceBytes = m_heap->objectSpace().capacity();
double totalFragmentation = ((double)totalLiveBytes + markedSpaceBytes) / ((double)totalUsableBytes + markedSpaceBytes);
m_shouldDoCopyPhase = totalFragmentation <= Options::minHeapUtilization();
@@ -224,31 +241,13 @@ void CopiedSpace::doneCopying()
while (!m_fromSpace->isEmpty()) {
CopiedBlock* block = m_fromSpace->removeHead();
- if (block->isPinned() || !m_shouldDoCopyPhase) {
- block->didSurviveGC();
- // We don't add the block to the blockSet because it was never removed.
- ASSERT(m_blockSet.contains(block));
- m_blockFilter.add(reinterpret_cast<Bits>(block));
- m_toSpace->push(block);
- continue;
- }
-
- m_blockSet.remove(block);
- m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block));
- }
-
- CopiedBlock* curr = m_oversizeBlocks.head();
- while (curr) {
- CopiedBlock* next = curr->next();
- if (!curr->isPinned()) {
- m_oversizeBlocks.remove(curr);
- m_blockSet.remove(curr);
- m_heap->blockAllocator().deallocateCustomSize(CopiedBlock::destroy(curr));
- } else {
- m_blockFilter.add(reinterpret_cast<Bits>(curr));
- curr->didSurviveGC();
- }
- curr = next;
+ // All non-pinned blocks in from-space should have been reclaimed as they were evacuated.
+ ASSERT(block->isPinned() || !m_shouldDoCopyPhase);
+ block->didSurviveGC();
+ // We don't add the block to the blockSet because it was never removed.
+ ASSERT(m_blockSet.contains(block));
+ m_blockFilter.add(reinterpret_cast<Bits>(block));
+ m_toSpace->push(block);
}
if (!m_toSpace->head())
diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
index 01e816793..c244015e7 100644
--- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
+++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
@@ -113,6 +113,7 @@ inline void CopiedSpace::recycleBorrowedBlock(CopiedBlock* block)
{
MutexLocker locker(m_loanedBlocksLock);
ASSERT(m_numberOfLoanedBlocks > 0);
+ ASSERT(m_inCopyingPhase);
m_numberOfLoanedBlocks--;
if (!m_numberOfLoanedBlocks)
m_loanedBlocksCondition.signal();
diff --git a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h b/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h
index 73400750f..eb7bd2e82 100644
--- a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h
+++ b/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h
@@ -56,10 +56,8 @@ private:
inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr, size_t bytes)
{
- if (CopiedSpace::isOversize(bytes)) {
- ASSERT(CopiedSpace::oversizeBlockFor(oldPtr)->isPinned());
+ if (CopiedSpace::isOversize(bytes))
return false;
- }
if (CopiedSpace::blockFor(oldPtr)->isPinned())
return false;
diff --git a/Source/JavaScriptCore/heap/GCThread.cpp b/Source/JavaScriptCore/heap/GCThread.cpp
index ea43456bd..ce3bbedc9 100644
--- a/Source/JavaScriptCore/heap/GCThread.cpp
+++ b/Source/JavaScriptCore/heap/GCThread.cpp
@@ -70,8 +70,16 @@ CopyVisitor* GCThread::copyVisitor()
GCPhase GCThread::waitForNextPhase()
{
MutexLocker locker(m_shared.m_phaseLock);
+ while (m_shared.m_gcThreadsShouldWait)
+ m_shared.m_phaseCondition.wait(m_shared.m_phaseLock);
+
+ m_shared.m_numberOfActiveGCThreads--;
+ if (!m_shared.m_numberOfActiveGCThreads)
+ m_shared.m_activityCondition.signal();
+
while (m_shared.m_currentPhase == NoPhase)
m_shared.m_phaseCondition.wait(m_shared.m_phaseLock);
+ m_shared.m_numberOfActiveGCThreads++;
return m_shared.m_currentPhase;
}
@@ -84,7 +92,7 @@ void GCThread::gcThreadMain()
// Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
// creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
{
- MutexLocker locker(m_shared.m_markingLock);
+ MutexLocker locker(m_shared.m_phaseLock);
}
{
ParallelModeEnabler enabler(*m_slotVisitor);
diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp
index d9946d589..446b41c2f 100644
--- a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp
+++ b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp
@@ -61,13 +61,16 @@ GCThreadSharedData::GCThreadSharedData(JSGlobalData* globalData)
, m_parallelMarkersShouldExit(false)
, m_blocksToCopy(globalData->heap.m_blockSnapshot)
, m_copyIndex(0)
+ , m_numberOfActiveGCThreads(0)
+ , m_gcThreadsShouldWait(false)
, m_currentPhase(NoPhase)
{
m_copyLock.Init();
#if ENABLE(PARALLEL_GC)
// Grab the lock so the new GC threads can be properly initialized before they start running.
- MutexLocker locker(m_markingLock);
+ MutexLocker locker(m_phaseLock);
for (unsigned i = 1; i < Options::numberOfGCMarkers(); ++i) {
+ m_numberOfActiveGCThreads++;
SlotVisitor* slotVisitor = new SlotVisitor(*this);
CopyVisitor* copyVisitor = new CopyVisitor(*this);
GCThread* newThread = new GCThread(*this, slotVisitor, copyVisitor);
@@ -75,6 +78,10 @@ GCThreadSharedData::GCThreadSharedData(JSGlobalData* globalData)
newThread->initializeThreadID(threadID);
m_gcThreads.append(newThread);
}
+
+ // Wait for all the GCThreads to get to the right place.
+ while (m_numberOfActiveGCThreads)
+ m_activityCondition.wait(m_phaseLock);
#endif
}
@@ -87,6 +94,7 @@ GCThreadSharedData::~GCThreadSharedData()
MutexLocker phaseLocker(m_phaseLock);
ASSERT(m_currentPhase == NoPhase);
m_parallelMarkersShouldExit = true;
+ m_gcThreadsShouldWait = false;
m_currentPhase = Exit;
m_phaseCondition.broadcast();
}
@@ -115,24 +123,44 @@ void GCThreadSharedData::reset()
}
}
-void GCThreadSharedData::didStartMarking()
+void GCThreadSharedData::startNextPhase(GCPhase phase)
{
- MutexLocker markingLocker(m_markingLock);
MutexLocker phaseLocker(m_phaseLock);
+ ASSERT(!m_gcThreadsShouldWait);
ASSERT(m_currentPhase == NoPhase);
- m_currentPhase = Mark;
- m_parallelMarkersShouldExit = false;
+ m_gcThreadsShouldWait = true;
+ m_currentPhase = phase;
m_phaseCondition.broadcast();
}
-void GCThreadSharedData::didFinishMarking()
+void GCThreadSharedData::endCurrentPhase()
+{
+ ASSERT(m_gcThreadsShouldWait);
+ MutexLocker locker(m_phaseLock);
+ m_currentPhase = NoPhase;
+ m_gcThreadsShouldWait = false;
+ m_phaseCondition.broadcast();
+ while (m_numberOfActiveGCThreads)
+ m_activityCondition.wait(m_phaseLock);
+}
+
+void GCThreadSharedData::didStartMarking()
{
MutexLocker markingLocker(m_markingLock);
- MutexLocker phaseLocker(m_phaseLock);
+ m_parallelMarkersShouldExit = false;
+ startNextPhase(Mark);
+}
+
+void GCThreadSharedData::didFinishMarking()
+{
+ {
+ MutexLocker markingLocker(m_markingLock);
+ m_parallelMarkersShouldExit = true;
+ m_markingCondition.broadcast();
+ }
+
ASSERT(m_currentPhase == Mark);
- m_currentPhase = NoPhase;
- m_parallelMarkersShouldExit = true;
- m_markingCondition.broadcast();
+ endCurrentPhase();
}
void GCThreadSharedData::didStartCopying()
@@ -150,18 +178,13 @@ void GCThreadSharedData::didStartCopying()
for (size_t i = 0; i < m_gcThreads.size(); i++)
m_gcThreads[i]->copyVisitor()->startCopying();
- MutexLocker locker(m_phaseLock);
- ASSERT(m_currentPhase == NoPhase);
- m_currentPhase = Copy;
- m_phaseCondition.broadcast();
+ startNextPhase(Copy);
}
void GCThreadSharedData::didFinishCopying()
{
- MutexLocker locker(m_phaseLock);
ASSERT(m_currentPhase == Copy);
- m_currentPhase = NoPhase;
- m_phaseCondition.broadcast();
+ endCurrentPhase();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.h b/Source/JavaScriptCore/heap/GCThreadSharedData.h
index bd48d9263..f341afc04 100644
--- a/Source/JavaScriptCore/heap/GCThreadSharedData.h
+++ b/Source/JavaScriptCore/heap/GCThreadSharedData.h
@@ -74,6 +74,8 @@ private:
friend class CopyVisitor;
void getNextBlocksToCopy(size_t&, size_t&);
+ void startNextPhase(GCPhase);
+ void endCurrentPhase();
JSGlobalData* m_globalData;
CopiedSpace* m_copiedSpace;
@@ -100,6 +102,9 @@ private:
Mutex m_phaseLock;
ThreadCondition m_phaseCondition;
+ ThreadCondition m_activityCondition;
+ unsigned m_numberOfActiveGCThreads;
+ bool m_gcThreadsShouldWait;
GCPhase m_currentPhase;
ListableHandler<WeakReferenceHarvester>::List m_weakReferenceHarvesters;
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index 772d85144..cd3393aa2 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -612,10 +612,9 @@ void Heap::copyBackingStores()
m_storageSpace.startedCopying();
if (m_storageSpace.shouldDoCopyPhase()) {
m_sharedData.didStartCopying();
- CopyVisitor& visitor = m_copyVisitor;
- visitor.startCopying();
- visitor.copyFromShared();
- visitor.doneCopying();
+ m_copyVisitor.startCopying();
+ m_copyVisitor.copyFromShared();
+ m_copyVisitor.doneCopying();
// We need to wait for everybody to finish and return their CopiedBlocks
// before signaling that the phase is complete.
m_storageSpace.doneCopying();
diff --git a/Source/JavaScriptCore/heap/SlotVisitor.cpp b/Source/JavaScriptCore/heap/SlotVisitor.cpp
index 26d056feb..7a30debda 100644
--- a/Source/JavaScriptCore/heap/SlotVisitor.cpp
+++ b/Source/JavaScriptCore/heap/SlotVisitor.cpp
@@ -10,6 +10,7 @@
#include "JSGlobalData.h"
#include "JSObject.h"
#include "JSString.h"
+#include <wtf/StackStats.h>
namespace JSC {
@@ -58,6 +59,7 @@ void SlotVisitor::reset()
void SlotVisitor::append(ConservativeRoots& conservativeRoots)
{
+ StackStats::probe();
JSCell** roots = conservativeRoots.roots();
size_t size = conservativeRoots.size();
for (size_t i = 0; i < size; ++i)
@@ -66,6 +68,7 @@ void SlotVisitor::append(ConservativeRoots& conservativeRoots)
ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
{
+ StackStats::probe();
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_visitedTypeCounts.count(cell);
#endif
@@ -92,6 +95,7 @@ ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell
void SlotVisitor::donateKnownParallel()
{
+ StackStats::probe();
// NOTE: Because we re-try often, we can afford to be conservative, and
// assume that donating is not profitable.
@@ -119,6 +123,7 @@ void SlotVisitor::donateKnownParallel()
void SlotVisitor::drain()
{
+ StackStats::probe();
ASSERT(m_isInParallelMode);
#if ENABLE(PARALLEL_GC)
@@ -144,6 +149,7 @@ void SlotVisitor::drain()
void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
{
+ StackStats::probe();
ASSERT(m_isInParallelMode);
ASSERT(Options::numberOfGCMarkers());
@@ -221,6 +227,7 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
void SlotVisitor::mergeOpaqueRoots()
{
+ StackStats::probe();
ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
{
MutexLocker locker(m_shared.m_opaqueRootsLock);
@@ -276,6 +283,7 @@ ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
// as it can change the JSValue pointed to be the argument when the original JSValue
// is a string that contains the same contents as another string.
+ StackStats::probe();
ASSERT(slot);
JSValue value = *slot;
ASSERT(value);
@@ -309,12 +317,14 @@ ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
void SlotVisitor::harvestWeakReferences()
{
+ StackStats::probe();
for (WeakReferenceHarvester* current = m_shared.m_weakReferenceHarvesters.head(); current; current = current->next())
current->visitWeakReferences(*this);
}
void SlotVisitor::finalizeUnconditionalFinalizers()
{
+ StackStats::probe();
while (m_shared.m_unconditionalFinalizers.hasNext())
m_shared.m_unconditionalFinalizers.removeNext()->finalizeUnconditionally();
}