| Index: third_party/WebKit/Source/platform/heap/ThreadState.cpp
|
| diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
|
| index f5b8a6545385aa544b24d3ad064841ae8215952e..9d4756afcd7872b7c32fd9090c8a7de75c8bb326 100644
|
| --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
|
| +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
|
| @@ -38,6 +38,7 @@
|
| #include "platform/heap/CallbackStack.h"
|
| #include "platform/heap/Handle.h"
|
| #include "platform/heap/Heap.h"
|
| +#include "platform/heap/HeapCompact.h"
|
| #include "platform/heap/PagePool.h"
|
| #include "platform/heap/SafePoint.h"
|
| #include "platform/heap/Visitor.h"
|
| @@ -79,7 +80,7 @@ uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
|
|
|
| const size_t defaultAllocatedObjectSizeThreshold = 100 * 1024;
|
|
|
| -const char* gcReasonString(BlinkGC::GCReason reason) {
|
| +const char* ThreadState::gcReasonString(BlinkGC::GCReason reason) {
|
| switch (reason) {
|
| case BlinkGC::IdleGC:
|
| return "IdleGC";
|
| @@ -504,6 +505,7 @@ void ThreadState::threadLocalWeakProcessing() {
|
| // Due to the complexity, we just forbid allocations.
|
| NoAllocationScope noAllocationScope(this);
|
|
|
| + GCForbiddenScope gcForbiddenScope(this);
|
| std::unique_ptr<Visitor> visitor =
|
| Visitor::create(this, BlinkGC::ThreadLocalWeakProcessing);
|
|
|
| @@ -999,7 +1001,7 @@ void ThreadState::runScheduledGC(BlinkGC::StackState stackState) {
|
| return;
|
|
|
| // If a safe point is entered while initiating a GC, we clearly do
|
| - // not want to do another as part that -- the safe point is only
|
| + // not want to do another as part of that -- the safe point is only
|
| // entered after checking if a scheduled GC ought to run first.
|
| // Prevent that from happening by marking GCs as forbidden while
|
| // one is initiated and later running.
|
| @@ -1040,6 +1042,34 @@ void ThreadState::makeConsistentForGC() {
|
| m_arenas[i]->makeConsistentForGC();
|
| }
|
|
|
| +void ThreadState::compact() {
|
| + if (!heap().compaction()->isCompacting())
|
| + return;
|
| +
|
| + SweepForbiddenScope scope(this);
|
| + ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
|
| + NoAllocationScope noAllocationScope(this);
|
| +
|
| + // Compaction is done eagerly and before the mutator threads get
|
| + // to run again. Doing it lazily is problematic, as the mutator's
|
| + // references to live objects could suddenly be invalidated by
|
| + // compaction of a page/heap. We do know all the references to
|
| + // the relocating objects just after marking, but won't later.
|
| + // (e.g., stack references could have been created, new objects
|
| + // created which refer to old collection objects, and so on.)
|
| +
|
| + // Compact the hash table backing store arena first, it usually has
|
| + // higher fragmentation and is larger.
|
| + //
|
| + // TODO: implement bail out wrt any overall deadline, not compacting
|
| + // the remaining arenas if the time budget has been exceeded.
|
| + heap().compaction()->startThreadCompaction();
|
| + for (int i = BlinkGC::HashTableArenaIndex; i >= BlinkGC::Vector1ArenaIndex;
|
| + --i)
|
| + static_cast<NormalPageArena*>(m_arenas[i])->sweepAndCompact();
|
| + heap().compaction()->finishThreadCompaction();
|
| +}
|
| +
|
| void ThreadState::makeConsistentForMutator() {
|
| ASSERT(isInGC());
|
| for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
|
| @@ -1123,9 +1153,19 @@ void ThreadState::preSweep() {
|
|
|
| eagerSweep();
|
|
|
| + // Any sweep compaction must happen after pre-finalizers and eager
|
| + // sweeping, as it will finalize dead objects in compactable arenas
|
| + // (e.g., backing stores for container objects.)
|
| + //
|
| + // As per-contract for prefinalizers, those finalizable objects must
|
| + // still be accessible when the prefinalizer runs, hence we cannot
|
| + // schedule compaction until those have run. Similarly for eager sweeping.
|
| + compact();
|
| +
|
| #if defined(ADDRESS_SANITIZER)
|
| poisonAllHeaps();
|
| #endif
|
| +
|
| if (previousGCState == EagerSweepScheduled) {
|
| // Eager sweeping should happen only in testing.
|
| completeSweep();
|
| @@ -1674,7 +1714,7 @@ void ThreadState::collectGarbage(BlinkGC::StackState stackState,
|
| RELEASE_ASSERT(!isGCForbidden());
|
| completeSweep();
|
|
|
| - std::unique_ptr<Visitor> visitor = Visitor::create(this, gcType);
|
| + GCForbiddenScope gcForbiddenScope(this);
|
|
|
| SafePointScope safePointScope(stackState, this);
|
|
|
| @@ -1685,6 +1725,12 @@ void ThreadState::collectGarbage(BlinkGC::StackState stackState,
|
| if (!parkThreadsScope.parkThreads())
|
| return;
|
|
|
| + BlinkGC::GCType visitorType = gcType;
|
| + if (heap().compaction()->shouldCompact(this, gcType, reason))
|
| + visitorType = heap().compaction()->initialize(this);
|
| +
|
| + std::unique_ptr<Visitor> visitor = Visitor::create(this, visitorType);
|
| +
|
| ScriptForbiddenIfMainThreadScope scriptForbidden;
|
|
|
| TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping",
|
| @@ -1697,7 +1743,7 @@ void ThreadState::collectGarbage(BlinkGC::StackState stackState,
|
|
|
| // Disallow allocation during garbage collection (but not during the
|
| // finalization that happens when the visitorScope is torn down).
|
| - ThreadState::NoAllocationScope noAllocationScope(this);
|
| + NoAllocationScope noAllocationScope(this);
|
|
|
| heap().commitCallbackStacks();
|
| heap().preGC();
|
| @@ -1785,10 +1831,11 @@ void ThreadState::collectGarbageForTerminatingThread() {
|
| // ahead while it is running, hence the termination GC does not enter a
|
| // safepoint. VisitorScope will not enter also a safepoint scope for
|
| // ThreadTerminationGC.
|
| + GCForbiddenScope gcForbiddenScope(this);
|
| std::unique_ptr<Visitor> visitor =
|
| Visitor::create(this, BlinkGC::ThreadTerminationGC);
|
|
|
| - ThreadState::NoAllocationScope noAllocationScope(this);
|
| + NoAllocationScope noAllocationScope(this);
|
|
|
| heap().commitCallbackStacks();
|
| preGC();
|
|
|