| Index: Source/platform/heap/Heap.cpp
|
| diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp
|
| index 444119d1e00566567f89f972ad6ec3cc353a4456..0cfac56103240cf7f07d53f597ba8e2e5db6a007 100644
|
| --- a/Source/platform/heap/Heap.cpp
|
| +++ b/Source/platform/heap/Heap.cpp
|
| @@ -151,11 +151,27 @@ public:
|
| if (LIKELY(gcType != ThreadState::ThreadTerminationGC && ThreadState::stopThreads()))
|
| m_parkedAllThreads = true;
|
|
|
| + switch (gcType) {
|
| + case ThreadState::GCWithSweep:
|
| + case ThreadState::GCWithoutSweep:
|
| + m_visitor = adoptPtr(new MarkingVisitor<Visitor::GlobalMarking>());
|
| + break;
|
| + case ThreadState::TakeSnapshot:
|
| + m_visitor = adoptPtr(new MarkingVisitor<Visitor::SnapshotMarking>());
|
| + break;
|
| + case ThreadState::ThreadTerminationGC:
|
| + m_visitor = adoptPtr(new MarkingVisitor<Visitor::ThreadLocalMarking>());
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + }
|
| +
|
| if (m_state->isMainThread())
|
| TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState);
|
| }
|
|
|
| - bool allThreadsParked() { return m_parkedAllThreads; }
|
| + bool allThreadsParked() const { return m_parkedAllThreads; }
|
| + Visitor* visitor() const { return m_visitor.get(); }
|
|
|
| ~GCScope()
|
| {
|
| @@ -174,6 +190,7 @@ private:
|
| GCForbiddenScope m_gcForbiddenScope;
|
| SafePointScope m_safePointScope;
|
| ThreadState::GCType m_gcType;
|
| + OwnPtr<Visitor> m_visitor;
|
| bool m_parkedAllThreads; // False if we fail to park all threads
|
| };
|
|
|
| @@ -326,6 +343,28 @@ void BaseHeap::makeConsistentForGC()
|
| ASSERT(!m_firstUnsweptPage);
|
| }
|
|
|
| +void BaseHeap::makeConsistentForMutator()
|
| +{
|
| + clearFreeLists();
|
| + ASSERT(isConsistentForGC());
|
| + ASSERT(!m_firstPage);
|
| +
|
| + // Drop marks from marked objects and rebuild free lists in preparation for
|
| + // resuming the executions of mutators.
|
| + BasePage* previousPage = nullptr;
|
| + for (BasePage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) {
|
| + page->makeConsistentForMutator();
|
| + page->markAsSwept();
|
| + }
|
| + if (previousPage) {
|
| + ASSERT(m_firstUnsweptPage);
|
| + previousPage->m_next = m_firstPage;
|
| + m_firstPage = m_firstUnsweptPage;
|
| + m_firstUnsweptPage = nullptr;
|
| + }
|
| + ASSERT(!m_firstUnsweptPage);
|
| +}
|
| +
|
| size_t BaseHeap::objectPayloadSizeForTesting()
|
| {
|
| ASSERT(isConsistentForGC());
|
| @@ -347,7 +386,7 @@ void BaseHeap::prepareHeapForTermination()
|
|
|
| void BaseHeap::prepareForSweep()
|
| {
|
| - ASSERT(!threadState()->isInGC());
|
| + ASSERT(threadState()->isInGC());
|
| ASSERT(!m_firstUnsweptPage);
|
|
|
| // Move all pages to a list of unswept pages.
|
| @@ -1223,6 +1262,37 @@ void NormalPage::makeConsistentForGC()
|
| Heap::increaseMarkedObjectSize(markedObjectSize);
|
| }
|
|
|
| +void NormalPage::makeConsistentForMutator()
|
| +{
|
| + size_t markedObjectSize = 0;
|
| + Address startOfGap = payload();
|
| + for (Address headerAddress = payload(); headerAddress < payloadEnd();) {
|
| + HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress);
|
| + ASSERT(header->size() < blinkPagePayloadSize());
|
| + // Check if a free list entry first since we cannot call
|
| + // isMarked on a free list entry.
|
| + if (header->isFree()) {
|
| + headerAddress += header->size();
|
| + continue;
|
| + }
|
| + header->checkHeader();
|
| +
|
| + if (startOfGap != headerAddress)
|
| + heapForNormalPage()->addToFreeList(startOfGap, headerAddress - startOfGap);
|
| + if (header->isMarked()) {
|
| + header->unmark();
|
| + markedObjectSize += header->size();
|
| + }
|
| + headerAddress += header->size();
|
| + startOfGap = headerAddress;
|
| + }
|
| + if (startOfGap != payloadEnd())
|
| + heapForNormalPage()->addToFreeList(startOfGap, payloadEnd() - startOfGap);
|
| +
|
| + if (markedObjectSize)
|
| + Heap::increaseMarkedObjectSize(markedObjectSize);
|
| +}
|
| +
|
| #if defined(ADDRESS_SANITIZER)
|
| void NormalPage::poisonObjects(ObjectsToPoison objectsToPoison, Poisoning poisoning)
|
| {
|
| @@ -1515,6 +1585,15 @@ void LargeObjectPage::makeConsistentForGC()
|
| }
|
| }
|
|
|
| +void LargeObjectPage::makeConsistentForMutator()
|
| +{
|
| + HeapObjectHeader* header = heapObjectHeader();
|
| + if (header->isMarked()) {
|
| + header->unmark();
|
| + Heap::increaseMarkedObjectSize(size());
|
| + }
|
| +}
|
| +
|
| #if defined(ADDRESS_SANITIZER)
|
| void LargeObjectPage::poisonObjects(ObjectsToPoison objectsToPoison, Poisoning poisoning)
|
| {
|
| @@ -1940,7 +2019,6 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
|
| // the GC.
|
| if (!gcScope.allThreadsParked())
|
| return;
|
| - MarkingVisitor<Visitor::GlobalMarking> visitor;
|
|
|
| if (state->isMainThread())
|
| ScriptForbiddenScope::enter();
|
| @@ -1953,7 +2031,7 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
|
| TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC");
|
| double timeStamp = WTF::currentTimeMS();
|
| #if ENABLE(GC_PROFILING)
|
| - visitor.objectGraph().clear();
|
| + gcScope.visitor()->objectGraph().clear();
|
| #endif
|
|
|
| // Disallow allocation during garbage collection (but not during the
|
| @@ -1968,24 +2046,24 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
|
| Heap::resetHeapCounters();
|
|
|
| // 1. Trace persistent roots.
|
| - ThreadState::visitPersistentRoots(&visitor);
|
| + ThreadState::visitPersistentRoots(gcScope.visitor());
|
|
|
| // 2. Trace objects reachable from the persistent roots including
|
| // ephemerons.
|
| - processMarkingStack(&visitor);
|
| + processMarkingStack(gcScope.visitor());
|
|
|
| // 3. Trace objects reachable from the stack. We do this independent of the
|
| // given stackState since other threads might have a different stack state.
|
| - ThreadState::visitStackRoots(&visitor);
|
| + ThreadState::visitStackRoots(gcScope.visitor());
|
|
|
| // 4. Trace objects reachable from the stack "roots" including ephemerons.
|
| // Only do the processing if we found a pointer to an object on one of the
|
| // thread stacks.
|
| if (lastGCWasConservative())
|
| - processMarkingStack(&visitor);
|
| + processMarkingStack(gcScope.visitor());
|
|
|
| - postMarkingProcessing(&visitor);
|
| - globalWeakProcessing(&visitor);
|
| + postMarkingProcessing(gcScope.visitor());
|
| + globalWeakProcessing(gcScope.visitor());
|
|
|
| // Now we can delete all orphaned pages because there are no dangling
|
| // pointers to the orphaned pages. (If we have such dangling pointers,
|
| @@ -1995,7 +2073,7 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
|
| postGC(gcType);
|
|
|
| #if ENABLE(GC_PROFILING)
|
| - visitor.reportStats();
|
| + gcScope.visitor()->reportStats();
|
| #endif
|
|
|
| double markingTimeInMilliseconds = WTF::currentTimeMS() - timeStamp;
|
| @@ -2021,7 +2099,6 @@ void Heap::collectGarbageForTerminatingThread(ThreadState* state)
|
| // ThreadTerminationGC.
|
| GCScope gcScope(state, ThreadState::NoHeapPointersOnStack, ThreadState::ThreadTerminationGC);
|
|
|
| - MarkingVisitor<Visitor::ThreadLocalMarking> visitor;
|
| ThreadState::NoAllocationScope noAllocationScope(state);
|
|
|
| state->preGC();
|
| @@ -2037,14 +2114,14 @@ void Heap::collectGarbageForTerminatingThread(ThreadState* state)
|
| // global GC finds a "pointer" on the stack or due to a programming
|
| // error where an object has a dangling cross-thread pointer to an
|
| // object on this heap.
|
| - state->visitPersistents(&visitor);
|
| + state->visitPersistents(gcScope.visitor());
|
|
|
| // 2. Trace objects reachable from the thread's persistent roots
|
| // including ephemerons.
|
| - processMarkingStack(&visitor);
|
| + processMarkingStack(gcScope.visitor());
|
|
|
| - postMarkingProcessing(&visitor);
|
| - globalWeakProcessing(&visitor);
|
| + postMarkingProcessing(gcScope.visitor());
|
| + globalWeakProcessing(gcScope.visitor());
|
|
|
| state->postGC(ThreadState::GCWithSweep);
|
| }
|
|
|