bool RecyclerPageAllocator::ResetWriteWatch() { if (allocFlags != MEM_WRITE_WATCH) { return false; } GCETW(GC_RESETWRITEWATCH_START, (this)); SuspendIdleDecommit(); bool success = true; // Only reset write watch on allocated pages if (!ResetWriteWatch(&segments) || !ResetWriteWatch(&decommitSegments) || !ResetAllWriteWatch(&fullSegments) || !ResetAllWriteWatch(&largeSegments)) { allocFlags = 0; success = false; } ResumeIdleDecommit(); GCETW(GC_RESETWRITEWATCH_STOP, (this)); return success; }
void RecyclerSweep::FinishSweep() { #if ENABLE_PARTIAL_GC #if ENABLE_ALLOCATIONS_DURING_CONCURRENT_SWEEP if (recycler->collectionState == CollectionStateConcurrentSweepPass2) { GCETW_INTERNAL(GC_START, (recycler, ETWEvent_ConcurrentSweep_Pass2)); } #endif Assert(this->partial == recycler->inPartialCollectMode); // Adjust heuristics if (recycler->inPartialCollectMode) { if (this->AdjustPartialHeuristics()) { GCETW(GC_SWEEP_PARTIAL_REUSE_PAGE_START, (recycler)); // If we are doing a full concurrent GC, all allocated bytes are consider "collected". // We only start accumulating uncollected allocate bytes during partial GC. // FinishPartialCollect will reset it to 0 if we are not doing a partial GC recycler->partialUncollectedAllocBytes = this->InPartialCollect()? this->nextPartialUncollectedAllocBytes : 0; #ifdef RECYCLER_TRACE if (recycler->GetRecyclerFlagsTable().Trace.IsEnabled(Js::PartialCollectPhase)) { Output::Print(_u("AdjustPartialHeuristics returned true\n")); Output::Print(_u(" partialUncollectedAllocBytes = %d\n"), recycler->partialUncollectedAllocBytes); Output::Print(_u(" nextPartialUncollectedAllocBytes = %d\n"), this->nextPartialUncollectedAllocBytes); } #endif recycler->autoHeap.SweepPartialReusePages(*this); GCETW(GC_SWEEP_PARTIAL_REUSE_PAGE_STOP, (recycler)); #ifdef RECYCLER_WRITE_WATCH if (!CONFIG_FLAG(ForceSoftwareWriteBarrier)) { if (!this->IsBackground()) { RECYCLER_PROFILE_EXEC_BEGIN(recycler, Js::ResetWriteWatchPhase); if (!recycler->recyclerPageAllocator.ResetWriteWatch() || !recycler->recyclerLargeBlockPageAllocator.ResetWriteWatch()) { // Shouldn't happen Assert(false); recycler->enablePartialCollect = false; recycler->FinishPartialCollect(this); } RECYCLER_PROFILE_EXEC_END(recycler, Js::ResetWriteWatchPhase); } } #endif } else { #ifdef RECYCLER_TRACE if (recycler->GetRecyclerFlagsTable().Trace.IsEnabled(Js::PartialCollectPhase)) { Output::Print(_u("AdjustPartialHeuristics returned false\n")); } #endif #if ENABLE_CONCURRENT_GC if (this->IsBackground()) { recycler->BackgroundFinishPartialCollect(this); } else #endif { recycler->FinishPartialCollect(this); } } } else { Assert(!this->adjustPartialHeuristics); // Initial value or Sweep should have called FinishPartialCollect to these if we are not doing partial Assert(recycler->partialUncollectedAllocBytes == 0); } #if ENABLE_CONCURRENT_GC recycler->SweepPendingObjects(*this); #endif #if ENABLE_ALLOCATIONS_DURING_CONCURRENT_SWEEP if (recycler->collectionState == CollectionStateConcurrentSweepPass2) { GCETW_INTERNAL(GC_STOP, (recycler, ETWEvent_ConcurrentSweep_Pass2)); } #endif #endif }