|
|
@@ -2,6 +2,7 @@
|
|
|
// Copyright (C) Microsoft. All rights reserved.
|
|
|
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
|
|
//-------------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
#include "CommonMemoryPch.h"
|
|
|
|
|
|
#ifdef _M_AMD64
|
|
|
@@ -19,6 +20,7 @@
|
|
|
#include "Core/BinaryFeatureControl.h"
|
|
|
#include "Common/ThreadService.h"
|
|
|
#include "Memory/AutoAllocatorObjectPtr.h"
|
|
|
+#include "Common/Tick.h"
|
|
|
|
|
|
DEFINE_RECYCLER_TRACKER_PERF_COUNTER(RecyclerWeakReferenceBase);
|
|
|
|
|
|
@@ -104,8 +106,9 @@ template _ALWAYSINLINE char * Recycler::AllocWithAttributesInlined<NoBit, false>
|
|
|
template _ALWAYSINLINE char* Recycler::RealAlloc<NoBit, false>(HeapInfo* heap, size_t size);
|
|
|
template _ALWAYSINLINE _Ret_notnull_ void * __cdecl operator new<Recycler>(size_t byteSize, Recycler * alloc, char * (Recycler::*AllocFunc)(size_t));
|
|
|
|
|
|
-Recycler::Recycler(AllocationPolicyManager * policyManager, IdleDecommitPageAllocator * pageAllocator, void (*outOfMemoryFunc)(), Js::ConfigFlagsTable& configFlagsTable) :
|
|
|
- collectionState(CollectionStateNotCollecting),
|
|
|
+Recycler::Recycler(AllocationPolicyManager * policyManager, IdleDecommitPageAllocator * pageAllocator, void (*outOfMemoryFunc)(), Js::ConfigFlagsTable& configFlagsTable, RecyclerTelemetryHostInterface* hostInterface) :
|
|
|
+ collectionStateChangedObserver(this),
|
|
|
+ collectionState(CollectionStateNotCollecting, &collectionStateChangedObserver),
|
|
|
recyclerFlagsTable(configFlagsTable),
|
|
|
autoHeap(policyManager, configFlagsTable, pageAllocator),
|
|
|
#ifdef ENABLE_JS_ETW
|
|
|
@@ -232,6 +235,9 @@ Recycler::Recycler(AllocationPolicyManager * policyManager, IdleDecommitPageAllo
|
|
|
#ifdef NTBUILD
|
|
|
, telemetryBlock(&localTelemetryBlock)
|
|
|
#endif
|
|
|
+#ifdef ENABLE_BASIC_TELEMETRY
|
|
|
+ , telemetryStats(this, hostInterface)
|
|
|
+#endif
|
|
|
#ifdef ENABLE_JS_ETW
|
|
|
,bulkFreeMemoryWrittenCount(0)
|
|
|
#endif
|
|
|
@@ -249,6 +255,23 @@ Recycler::Recycler(AllocationPolicyManager * policyManager, IdleDecommitPageAllo
|
|
|
, trackerCriticalSection(nullptr)
|
|
|
#endif
|
|
|
{
|
|
|
+
|
|
|
+#ifdef ENABLE_BASIC_TELEMETRY
|
|
|
+
|
|
|
+ if (CoCreateGuid(&recyclerID) != S_OK)
|
|
|
+ {
|
|
|
+ // CoCreateGuid failed
|
|
|
+ recyclerID = { 0 };
|
|
|
+ }
|
|
|
+
|
|
|
+ this->GetHeapInfo()->GetRecyclerPageAllocator()->SetDecommitStats(this->GetRecyclerTelemetryInfo().GetThreadPageAllocator_decommitStats());
|
|
|
+ this->GetHeapInfo()->GetRecyclerLeafPageAllocator()->SetDecommitStats(this->GetRecyclerTelemetryInfo().GetRecyclerLeafPageAllocator_decommitStats());
|
|
|
+ this->GetHeapInfo()->GetRecyclerLargeBlockPageAllocator()->SetDecommitStats(this->GetRecyclerTelemetryInfo().GetRecyclerLargeBlockPageAllocator_decommitStats());
|
|
|
+#ifdef RECYCLER_WRITE_BARRIER_ALLOC_SEPARATE_PAGE
|
|
|
+ this->GetHeapInfo()->GetRecyclerWithBarrierPageAllocator()->SetDecommitStats(this->GetRecyclerTelemetryInfo().GetRecyclerWithBarrierPageAllocator_decommitStats());
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef RECYCLER_MARK_TRACK
|
|
|
this->markMap = NoCheckHeapNew(MarkMap, &NoCheckHeapAllocator::Instance, 163, &markMapCriticalSection);
|
|
|
markContext.SetMarkMap(markMap);
|
|
|
@@ -2024,7 +2047,7 @@ void
|
|
|
Recycler::ResetMarks(ResetMarkFlags flags)
|
|
|
{
|
|
|
Assert(!this->CollectionInProgress());
|
|
|
- collectionState = CollectionStateResetMarks;
|
|
|
+ this->SetCollectionState(CollectionStateResetMarks);
|
|
|
|
|
|
RecyclerVerboseTrace(GetRecyclerFlagsTable(), _u("Reset marks\n"));
|
|
|
GCETW(GC_RESETMARKS_START, (this));
|
|
|
@@ -2236,7 +2259,7 @@ Recycler::Mark()
|
|
|
{
|
|
|
// Marking in thread, we can just pre-mark them
|
|
|
ResetMarks(this->enableScanImplicitRoots ? ResetMarkFlags_InThreadImplicitRoots : ResetMarkFlags_InThread);
|
|
|
- collectionState = CollectionStateFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateFindRoots);
|
|
|
RootMark(CollectionStateMark);
|
|
|
}
|
|
|
|
|
|
@@ -2275,7 +2298,7 @@ Recycler::ResetCollectionState()
|
|
|
{
|
|
|
Assert(IsMarkStackEmpty());
|
|
|
|
|
|
- this->collectionState = CollectionStateNotCollecting;
|
|
|
+ this->SetCollectionState(CollectionStateNotCollecting);
|
|
|
#if ENABLE_CONCURRENT_GC
|
|
|
this->backgroundFinishMarkCount = 0;
|
|
|
#endif
|
|
|
@@ -2399,7 +2422,7 @@ Recycler::RescanMark(DWORD waitTime)
|
|
|
this->backgroundFinishMarkCount++;
|
|
|
this->PrepareSweep();
|
|
|
GCETW(GC_RESCANMARKWAIT_START, (this, waitTime));
|
|
|
- const BOOL waited = WaitForConcurrentThread(waitTime);
|
|
|
+ const BOOL waited = WaitForConcurrentThread(waitTime, RecyclerWaitReason::RescanMark);
|
|
|
GCETW(GC_RESCANMARKWAIT_STOP, (this, !waited));
|
|
|
if (!waited)
|
|
|
{
|
|
|
@@ -2414,7 +2437,7 @@ Recycler::RescanMark(DWORD waitTime)
|
|
|
return Recycler::InvalidScanRootBytes;
|
|
|
}
|
|
|
Assert(collectionState == CollectionStateRescanWait);
|
|
|
- collectionState = CollectionStateRescanFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateRescanFindRoots);
|
|
|
#ifdef RECYCLER_WRITE_WATCH
|
|
|
if (!CONFIG_FLAG(ForceSoftwareWriteBarrier))
|
|
|
{
|
|
|
@@ -2525,7 +2548,7 @@ Recycler::DoParallelMark()
|
|
|
// If we failed, then process the work in-thread now.
|
|
|
if (concurrentSuccess)
|
|
|
{
|
|
|
- WaitForConcurrentThread(INFINITE);
|
|
|
+ WaitForConcurrentThread(INFINITE, RecyclerWaitReason::DoParallelMark);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -2556,7 +2579,7 @@ Recycler::DoParallelMark()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- this->collectionState = CollectionStateMark;
|
|
|
+ this->SetCollectionState(CollectionStateMark);
|
|
|
|
|
|
// Process tracked objects, if any, then do one final mark phase in case they marked any new objects.
|
|
|
// (Unless it's a partial collect, in which case we don't process tracked objects at all)
|
|
|
@@ -2609,7 +2632,7 @@ Recycler::DoBackgroundParallelMark()
|
|
|
Assert(this->DoQueueTrackedObject());
|
|
|
#endif
|
|
|
|
|
|
- this->collectionState = CollectionStateBackgroundParallelMark;
|
|
|
+ this->SetCollectionState(CollectionStateBackgroundParallelMark);
|
|
|
|
|
|
// Kick off marking on parallel threads too, if there is work for them
|
|
|
// If the threads haven't been created yet, this will create them (or fail).
|
|
|
@@ -2647,7 +2670,7 @@ Recycler::DoBackgroundParallelMark()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- this->collectionState = CollectionStateConcurrentMark;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentMark);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
@@ -2680,7 +2703,7 @@ Recycler::RootMark(CollectionState markState)
|
|
|
scannedRootBytes += ScanStack();
|
|
|
}
|
|
|
|
|
|
- this->collectionState = markState;
|
|
|
+ this->SetCollectionState(markState);
|
|
|
|
|
|
#if ENABLE_CONCURRENT_GC
|
|
|
if (this->enableParallelMark)
|
|
|
@@ -2815,7 +2838,7 @@ Recycler::EndMarkOnLowMemory()
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- this->collectionState = CollectionStateRescanFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateRescanFindRoots);
|
|
|
|
|
|
this->ClearNeedOOMRescan();
|
|
|
|
|
|
@@ -3035,7 +3058,7 @@ Recycler::Sweep(bool concurrent)
|
|
|
|
|
|
RECYCLER_PROFILE_EXEC_END(this, concurrent? Js::ConcurrentSweepPhase : Js::SweepPhase);
|
|
|
|
|
|
- this->collectionState = CollectionStatePostSweepRedeferralCallback;
|
|
|
+ this->SetCollectionState(CollectionStatePostSweepRedeferralCallback);
|
|
|
// Note that PostSweepRedeferralCallback can't have exception escape.
|
|
|
collectionWrapper->PostSweepRedeferralCallBack();
|
|
|
|
|
|
@@ -3054,7 +3077,7 @@ Recycler::Sweep(bool concurrent)
|
|
|
this->allowAllocationsDuringConcurrentSweepForCollection = false;
|
|
|
}
|
|
|
#endif
|
|
|
- this->collectionState = CollectionStateConcurrentSweep;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweep);
|
|
|
|
|
|
DoBackgroundWork(true);
|
|
|
// Continue as if the concurrent sweep were executing
|
|
|
@@ -3218,7 +3241,7 @@ Recycler::SweepHeap(bool concurrent, RecyclerSweepManager& recyclerSweepManager)
|
|
|
Assert(!this->DoQueueTrackedObject());
|
|
|
if (concurrent)
|
|
|
{
|
|
|
- collectionState = CollectionStateSetupConcurrentSweep;
|
|
|
+ SetCollectionState(CollectionStateSetupConcurrentSweep);
|
|
|
|
|
|
#if ENABLE_BACKGROUND_PAGE_ZEROING
|
|
|
if (CONFIG_FLAG(EnableBGFreeZero))
|
|
|
@@ -3231,7 +3254,7 @@ Recycler::SweepHeap(bool concurrent, RecyclerSweepManager& recyclerSweepManager)
|
|
|
#endif
|
|
|
{
|
|
|
Assert(!concurrent);
|
|
|
- collectionState = CollectionStateSweep;
|
|
|
+ SetCollectionState(CollectionStateSweep);
|
|
|
}
|
|
|
|
|
|
this->SweepWeakReference();
|
|
|
@@ -3397,7 +3420,7 @@ Recycler::FinishDisposeObjects()
|
|
|
if (!this->inDispose && this->hasDisposableObject
|
|
|
&& GetRecyclerFlagsTable().Trace.IsEnabled(Js::RecyclerPhase))
|
|
|
{
|
|
|
- Output::Print(_u("%04X> RC(%p): %s %d\n"), this->mainThreadId, this, _u("Dispose object delayed"), this->collectionState);
|
|
|
+ Output::Print(_u("%04X> RC(%p): %s %d\n"), this->mainThreadId, this, _u("Dispose object delayed"), static_cast<CollectionState>(this->collectionState));
|
|
|
}
|
|
|
#endif
|
|
|
return false;
|
|
|
@@ -3932,9 +3955,9 @@ Recycler::DoCollect(CollectionFlags flags)
|
|
|
#if DBG || defined RECYCLER_TRACE
|
|
|
collectionCount++;
|
|
|
#endif
|
|
|
- collectionState = Collection_PreCollection;
|
|
|
+ this->SetCollectionState(Collection_PreCollection);
|
|
|
collectionWrapper->PreCollectionCallBack(flags);
|
|
|
- collectionState = CollectionStateNotCollecting;
|
|
|
+ this->SetCollectionState(CollectionStateNotCollecting);
|
|
|
|
|
|
hasExhaustiveCandidate = false; // reset the candidate detection
|
|
|
|
|
|
@@ -4116,7 +4139,7 @@ Recycler::PartialCollect(bool concurrent)
|
|
|
Assert(this->inPartialCollectMode);
|
|
|
Assert(collectionState == CollectionStateNotCollecting);
|
|
|
// Rescan again
|
|
|
- collectionState = CollectionStateRescanFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateRescanFindRoots);
|
|
|
#if ENABLE_CONCURRENT_GC
|
|
|
if (concurrent && enableConcurrentMark && this->partialConcurrentNextCollection)
|
|
|
{
|
|
|
@@ -4446,11 +4469,11 @@ Recycler::RequestConcurrentWrapperCallback()
|
|
|
if (StartConcurrent(CollectionStateConcurrentWrapperCallback))
|
|
|
{
|
|
|
// Wait for the callback to complete
|
|
|
- WaitForConcurrentThread(INFINITE);
|
|
|
+ WaitForConcurrentThread(INFINITE, RecyclerWaitReason::RequestConcurrentCallbackWrapper);
|
|
|
|
|
|
// The state must not change back until we restore the original state
|
|
|
Assert(collectionState == CollectionStateConcurrentWrapperCallback);
|
|
|
- this->collectionState = oldState;
|
|
|
+ this->SetCollectionState(oldState);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
@@ -4481,7 +4504,7 @@ Recycler::CollectOnConcurrentThread()
|
|
|
|
|
|
const DWORD waitTime = RecyclerHeuristic::FinishConcurrentCollectWaitTime(this->GetRecyclerFlagsTable());
|
|
|
GCETW(GC_SYNCHRONOUSMARKWAIT_START, (this, waitTime));
|
|
|
- const BOOL waited = WaitForConcurrentThread(waitTime);
|
|
|
+ const BOOL waited = WaitForConcurrentThread(waitTime, RecyclerWaitReason::CollectOnConcurrentThread);
|
|
|
GCETW(GC_SYNCHRONOUSMARKWAIT_STOP, (this, !waited));
|
|
|
if (!waited)
|
|
|
{
|
|
|
@@ -4509,7 +4532,7 @@ Recycler::CollectOnConcurrentThread()
|
|
|
// Assert(markContext.Empty());
|
|
|
DebugOnly(this->isProcessingRescan = false);
|
|
|
|
|
|
- this->collectionState = CollectionStateMark;
|
|
|
+ this->SetCollectionState(CollectionStateMark);
|
|
|
this->ProcessTrackedObjects();
|
|
|
this->ProcessMark(false);
|
|
|
this->EndMark();
|
|
|
@@ -4832,8 +4855,9 @@ bool Recycler::AbortConcurrent(bool restoreState)
|
|
|
|
|
|
this->FinishSweepPrep();
|
|
|
this->FinishConcurrentSweepPass1();
|
|
|
- this->collectionState = CollectionStateConcurrentSweepPass2;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweepPass2);
|
|
|
this->recyclerSweepManager->FinishSweep();
|
|
|
+
|
|
|
this->FinishConcurrentSweep();
|
|
|
this->recyclerSweepManager->EndBackground();
|
|
|
|
|
|
@@ -4844,7 +4868,7 @@ bool Recycler::AbortConcurrent(bool restoreState)
|
|
|
|
|
|
GCETW(GC_BACKGROUNDSWEEP_STOP, (this, sweptBytes));
|
|
|
|
|
|
- this->collectionState = CollectionStateTransferSweptWait;
|
|
|
+ this->SetCollectionState(CollectionStateTransferSweptWait);
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, Js::ConcurrentSweepPhase);
|
|
|
|
|
|
// AbortConcurrent already consumed the event from the concurrent thread, just signal it so
|
|
|
@@ -4952,7 +4976,7 @@ Recycler::FinalizeConcurrent(bool restoreState)
|
|
|
#endif
|
|
|
|
|
|
bool aborted = AbortConcurrent(needCleanExitState);
|
|
|
- collectionState = CollectionStateExit;
|
|
|
+ SetCollectionState(CollectionStateExit);
|
|
|
if (aborted && this->concurrentThread != NULL)
|
|
|
{
|
|
|
// In case the thread already died, wait for that too
|
|
|
@@ -5151,7 +5175,7 @@ Recycler::DisableConcurrent()
|
|
|
Assert(concurrentThread != NULL || threadService->HasCallback());
|
|
|
|
|
|
FinalizeConcurrent(true);
|
|
|
- this->collectionState = CollectionStateNotCollecting;
|
|
|
+ this->SetCollectionState(CollectionStateNotCollecting);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -5162,7 +5186,7 @@ Recycler::StartConcurrent(CollectionState const state)
|
|
|
tickCountStartConcurrent = GetTickCount();
|
|
|
|
|
|
CollectionState oldState = this->collectionState;
|
|
|
- this->collectionState = state;
|
|
|
+ this->SetCollectionState(state);
|
|
|
|
|
|
if (threadService->HasCallback())
|
|
|
{
|
|
|
@@ -5171,7 +5195,7 @@ Recycler::StartConcurrent(CollectionState const state)
|
|
|
|
|
|
if (!threadService->Invoke(Recycler::StaticBackgroundWorkCallback, this))
|
|
|
{
|
|
|
- this->collectionState = oldState;
|
|
|
+ this->SetCollectionState(oldState);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -5237,7 +5261,7 @@ Recycler::StartBackgroundMark(bool foregroundResetMark, bool foregroundFindRoots
|
|
|
|
|
|
if (foregroundFindRoots)
|
|
|
{
|
|
|
- this->collectionState = CollectionStateFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateFindRoots);
|
|
|
FindRoots();
|
|
|
ScanStack();
|
|
|
Assert(collectionState == CollectionStateFindRoots);
|
|
|
@@ -5263,7 +5287,6 @@ Recycler::StartBackgroundMark(bool foregroundResetMark, bool foregroundFindRoots
|
|
|
this->RevertPrepareBackgroundFindRoots();
|
|
|
}
|
|
|
this->collectionState = CollectionStateNotCollecting;
|
|
|
-
|
|
|
#ifdef ENABLE_JS_ETW
|
|
|
collectionFinishReason = ETWEventGCActivationTrigger::ETWEvent_GC_Trigger_Status_Failed;
|
|
|
#endif
|
|
|
@@ -5593,7 +5616,7 @@ Recycler::BackgroundFindRoots()
|
|
|
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, Js::BackgroundFindRootsPhase);
|
|
|
this->hasPendingConcurrentFindRoot = false;
|
|
|
- this->collectionState = CollectionStateConcurrentMark;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentMark);
|
|
|
|
|
|
GCETW(GC_BACKGROUNDSCANROOTS_STOP, (this));
|
|
|
RECYCLER_STATS_ADD(this, rootCount, this->collectionStats.markData.markCount - lastMarkCount);
|
|
|
@@ -5611,9 +5634,9 @@ Recycler::BackgroundFinishMark()
|
|
|
#endif
|
|
|
Assert(collectionState == CollectionStateConcurrentFinishMark);
|
|
|
size_t rescannedRootBytes = FinishMarkRescan(true) * AutoSystemInfo::PageSize;
|
|
|
- this->collectionState = CollectionStateConcurrentFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentFindRoots);
|
|
|
rescannedRootBytes += this->BackgroundFindRoots();
|
|
|
- this->collectionState = CollectionStateConcurrentFinishMark;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentFinishMark);
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_BEGIN(this, Js::MarkPhase);
|
|
|
ProcessMark(true);
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, Js::MarkPhase);
|
|
|
@@ -5664,7 +5687,7 @@ Recycler::FinishConcurrentCollectWrapped(CollectionFlags flags)
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
|
-Recycler::WaitForConcurrentThread(DWORD waitTime)
|
|
|
+Recycler::WaitForConcurrentThread(DWORD waitTime, RecyclerWaitReason caller)
|
|
|
{
|
|
|
Assert(this->IsConcurrentState() || this->collectionState == CollectionStateParallelMark);
|
|
|
|
|
|
@@ -5676,8 +5699,22 @@ Recycler::WaitForConcurrentThread(DWORD waitTime)
|
|
|
SetThreadPriority(this->concurrentThread, THREAD_PRIORITY_NORMAL);
|
|
|
}
|
|
|
|
|
|
+#ifdef ENABLE_BASIC_TELEMETRY
|
|
|
+ bool isBlockingMainThread = this->telemetryStats.IsOnScriptThread();
|
|
|
+ Js::Tick start = Js::Tick::Now();
|
|
|
+#endif
|
|
|
+
|
|
|
DWORD ret = WaitForSingleObject(concurrentWorkDoneEvent, waitTime);
|
|
|
|
|
|
+#ifdef ENABLE_BASIC_TELEMETRY
|
|
|
+ if (isBlockingMainThread)
|
|
|
+ {
|
|
|
+ Js::Tick end = Js::Tick::Now();
|
|
|
+ Js::TickDelta elapsed = end - start;
|
|
|
+ this->telemetryStats.IncrementUserThreadBlockedCount(elapsed.ToMicroseconds(), caller);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
if (concurrentThread != NULL)
|
|
|
{
|
|
|
if (ret == WAIT_TIMEOUT)
|
|
|
@@ -5781,7 +5818,7 @@ Recycler::FinishConcurrentCollect(CollectionFlags flags)
|
|
|
PrintCollectTrace(Js::ConcurrentMarkPhase, true);
|
|
|
#endif
|
|
|
#endif
|
|
|
- collectionState = CollectionStateRescanFindRoots;
|
|
|
+ SetCollectionState(CollectionStateRescanFindRoots);
|
|
|
|
|
|
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
|
|
|
// TODO: Change this behavior
|
|
|
@@ -5840,7 +5877,7 @@ Recycler::FinishConcurrentCollect(CollectionFlags flags)
|
|
|
if (forceInThread)
|
|
|
{
|
|
|
this->FinishConcurrentSweepPass1();
|
|
|
- this->collectionState = CollectionStateConcurrentSweepPass2;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweepPass2);
|
|
|
#ifdef RECYCLER_TRACE
|
|
|
if (this->GetRecyclerFlagsTable().Trace.IsEnabled(Js::ConcurrentSweepPhase) && CONFIG_FLAG_RELEASE(Verbose))
|
|
|
{
|
|
|
@@ -5858,7 +5895,7 @@ Recycler::FinishConcurrentCollect(CollectionFlags flags)
|
|
|
|
|
|
GCETW(GC_BACKGROUNDSWEEP_STOP, (this, sweptBytes));
|
|
|
|
|
|
- this->collectionState = CollectionStateTransferSweptWait;
|
|
|
+ this->SetCollectionState(CollectionStateTransferSweptWait);
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, Js::ConcurrentSweepPhase);
|
|
|
|
|
|
FinishTransferSwept(flags);
|
|
|
@@ -5907,7 +5944,7 @@ Recycler::FinishTransferSwept(CollectionFlags flags)
|
|
|
#ifdef RECYCLER_TRACE
|
|
|
PrintCollectTrace(Js::ConcurrentSweepPhase, true);
|
|
|
#endif
|
|
|
- collectionState = CollectionStateTransferSwept;
|
|
|
+ SetCollectionState(CollectionStateTransferSwept);
|
|
|
|
|
|
#if ENABLE_BACKGROUND_PAGE_FREEING
|
|
|
if (CONFIG_FLAG(EnableBGFreeZero))
|
|
|
@@ -6043,12 +6080,12 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
case CollectionStateConcurrentResetMarks:
|
|
|
this->BackgroundResetMarks();
|
|
|
this->BackgroundResetWriteWatchAll();
|
|
|
- this->collectionState = CollectionStateConcurrentFindRoots;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentFindRoots);
|
|
|
// fall-through
|
|
|
case CollectionStateConcurrentFindRoots:
|
|
|
this->BackgroundFindRoots();
|
|
|
this->BackgroundScanStack();
|
|
|
- this->collectionState = CollectionStateConcurrentMark;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentMark);
|
|
|
// fall-through
|
|
|
case CollectionStateConcurrentMark:
|
|
|
this->BackgroundMark();
|
|
|
@@ -6072,7 +6109,7 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, this->collectionState == CollectionStateConcurrentFinishMark ?
|
|
|
Js::BackgroundFinishMarkPhase : Js::ConcurrentMarkPhase);
|
|
|
|
|
|
- this->collectionState = CollectionStateRescanWait;
|
|
|
+ this->SetCollectionState(CollectionStateRescanWait);
|
|
|
DebugOnly(this->markContext.GetPageAllocator()->ClearConcurrentThreadId());
|
|
|
}
|
|
|
else
|
|
|
@@ -6088,7 +6125,7 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
|
|
|
if (this->AllowAllocationsDuringConcurrentSweep())
|
|
|
{
|
|
|
- this->collectionState = CollectionStateConcurrentSweepPass1;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweepPass1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -6149,7 +6186,7 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
#if ENABLE_ALLOCATIONS_DURING_CONCURRENT_SWEEP
|
|
|
if (CONFIG_FLAG_RELEASE(EnableConcurrentSweepAlloc) && this->AllowAllocationsDuringConcurrentSweep())
|
|
|
{
|
|
|
- this->collectionState = CollectionStateConcurrentSweepPass1Wait;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweepPass1Wait);
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
|
@@ -6179,7 +6216,7 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
this->FinishConcurrentSweep();
|
|
|
this->recyclerSweepManager->EndBackground();
|
|
|
|
|
|
- this->collectionState = CollectionStateConcurrentSweepPass2Wait;
|
|
|
+ this->SetCollectionState(CollectionStateConcurrentSweepPass2Wait);
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
@@ -6218,7 +6255,7 @@ Recycler::DoBackgroundWork(bool forceForeground)
|
|
|
GCETW_INTERNAL(GC_STOP, (this, ETWEvent_ConcurrentSweep));
|
|
|
GCETW_INTERNAL(GC_STOP2, (this, ETWEvent_ConcurrentSweep, this->collectionStartReason, this->collectionStartFlags));
|
|
|
}
|
|
|
- this->collectionState = CollectionStateTransferSweptWait;
|
|
|
+ this->SetCollectionState(CollectionStateTransferSweptWait);
|
|
|
}
|
|
|
|
|
|
RECYCLER_PROFILE_EXEC_BACKGROUND_END(this, Js::ConcurrentSweepPhase);
|
|
|
@@ -6498,6 +6535,7 @@ Recycler::FinishCollection()
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+
|
|
|
#ifdef RECYCLER_STATS
|
|
|
if (CUSTOM_PHASE_STATS1(this->GetRecyclerFlagsTable(), Js::RecyclerPhase))
|
|
|
{
|
|
|
@@ -7123,7 +7161,7 @@ Recycler::PrintBlockStatus(HeapBucket * heapBucket, HeapBlock * heapBlock, char1
|
|
|
{
|
|
|
if (this->GetRecyclerFlagsTable().Trace.IsEnabled(Js::ConcurrentSweepPhase) && CONFIG_FLAG_RELEASE(Verbose))
|
|
|
{
|
|
|
- Output::Print(_u("[GC #%d] [HeapBucket 0x%p] HeapBlock 0x%p %s [CollectionState: %d] \n"), this->collectionCount, heapBucket, heapBlock, statusMessage, this->collectionState);
|
|
|
+ Output::Print(_u("[GC #%d] [HeapBucket 0x%p] HeapBlock 0x%p %s [CollectionState: %d] \n"), this->collectionCount, heapBucket, heapBlock, statusMessage, static_cast<CollectionState>(this->collectionState));
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
@@ -7830,7 +7868,7 @@ void Recycler::AutoSetupRecyclerForNonCollectingMark::SetupForHeapEnumeration()
|
|
|
m_recycler.EnsureNotCollecting();
|
|
|
DoCommonSetup();
|
|
|
m_recycler.ResetMarks(ResetMarkFlags_HeapEnumeration);
|
|
|
- m_recycler.collectionState = CollectionStateNotCollecting;
|
|
|
+ m_recycler.SetCollectionState(CollectionStateNotCollecting);
|
|
|
m_recycler.isHeapEnumInProgress = true;
|
|
|
m_recycler.isCollectionDisabled = true;
|
|
|
}
|
|
|
@@ -7842,7 +7880,7 @@ Recycler::AutoSetupRecyclerForNonCollectingMark::~AutoSetupRecyclerForNonCollect
|
|
|
#ifdef RECYCLER_STATS
|
|
|
m_recycler.collectionStats = m_previousCollectionStats;
|
|
|
#endif
|
|
|
- m_recycler.collectionState = m_previousCollectionState;
|
|
|
+ m_recycler.SetCollectionState(m_previousCollectionState);
|
|
|
m_recycler.isHeapEnumInProgress = false;
|
|
|
m_recycler.isCollectionDisabled = false;
|
|
|
}
|
|
|
@@ -7854,7 +7892,7 @@ bool Recycler::DumpObjectGraph(RecyclerObjectGraphDumper::Param * param)
|
|
|
bool isExited = (this->collectionState == CollectionStateExit);
|
|
|
if (isExited)
|
|
|
{
|
|
|
- this->collectionState = CollectionStateNotCollecting;
|
|
|
+ this->SetCollectionState(CollectionStateNotCollecting);
|
|
|
}
|
|
|
if (this->collectionState != CollectionStateNotCollecting)
|
|
|
{
|
|
|
@@ -7884,7 +7922,7 @@ bool Recycler::DumpObjectGraph(RecyclerObjectGraphDumper::Param * param)
|
|
|
|
|
|
if (isExited)
|
|
|
{
|
|
|
- this->collectionState = CollectionStateExit;
|
|
|
+ this->SetCollectionState(CollectionStateExit);
|
|
|
}
|
|
|
|
|
|
if (!succeeded)
|