| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- //-------------------------------------------------------------------------------------------------------
- // 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"
- RecyclerPageAllocator::RecyclerPageAllocator(HeapInfo * heapInfo, AllocationPolicyManager * policyManager,
- Js::ConfigFlagsTable& flagTable, uint maxFreePageCount, uint maxAllocPageCount, bool enableWriteBarrier)
- : IdleDecommitPageAllocator(policyManager,
- PageAllocatorType_Recycler,
- flagTable,
- 0, maxFreePageCount,
- true,
- #if ENABLE_BACKGROUND_PAGE_ZEROING
- &zeroPageQueue,
- #endif
- maxAllocPageCount,
- enableWriteBarrier
- )
- {
- this->heapInfo = heapInfo;
- }
- bool RecyclerPageAllocator::IsMemProtectMode()
- {
- return heapInfo->GetRecycler()->IsMemProtectMode();
- }
- #if ENABLE_CONCURRENT_GC
- #ifdef RECYCLER_WRITE_WATCH
- void
- RecyclerPageAllocator::EnableWriteWatch()
- {
- Assert(segments.Empty());
- Assert(fullSegments.Empty());
- Assert(emptySegments.Empty());
- Assert(decommitSegments.Empty());
- Assert(largeSegments.Empty());
- allocFlags = MEM_WRITE_WATCH;
- }
- bool
- RecyclerPageAllocator::ResetWriteWatch()
- {
- if (!IsWriteWatchEnabled())
- {
- 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;
- }
- bool
- RecyclerPageAllocator::ResetWriteWatch(DListBase<PageSegment> * segmentList)
- {
- DListBase<PageSegment>::Iterator i(segmentList);
- while (i.Next())
- {
- PageSegment& segment = i.Data();
- size_t pageCount = segment.GetAvailablePageCount();
- Assert(pageCount <= MAXUINT32);
- PageSegment::PageBitVector unallocPages = segment.GetUnAllocatedPages();
- for (uint index = 0u; index < pageCount; index++)
- {
- if (unallocPages.Test(index))
- {
- continue;
- }
- char * address = segment.GetAddress() + index * AutoSystemInfo::PageSize;
- if (::ResetWriteWatch(address, AutoSystemInfo::PageSize) != 0)
- {
- #if DBG_DUMP
- Output::Print(_u("ResetWriteWatch failed for %p\n"), address);
- Output::Flush();
- #endif
- // shouldn't happen
- Assert(false);
- return false;
- }
- }
- }
- return true;
- }
- template <typename T>
- bool
- RecyclerPageAllocator::ResetAllWriteWatch(DListBase<T> * segmentList)
- {
- typename DListBase<T>::Iterator i(segmentList);
- while (i.Next())
- {
- T& segment = i.Data();
- if (::ResetWriteWatch(segment.GetAddress(), segment.GetPageCount() * AutoSystemInfo::PageSize ) != 0)
- {
- #if DBG_DUMP
- Output::Print(_u("ResetWriteWatch failed for %p\n"), segment.GetAddress());
- Output::Flush();
- #endif
- // shouldn't happen
- Assert(false);
- return false;
- }
- }
- return true;
- }
- #endif
- #ifdef RECYCLER_WRITE_WATCH
- #if DBG
- size_t
- RecyclerPageAllocator::GetWriteWatchPageCount()
- {
- if (allocFlags != MEM_WRITE_WATCH)
- {
- return 0;
- }
- SuspendIdleDecommit();
- // Only reset write watch on allocated pages
- size_t count = GetWriteWatchPageCount(&segments)
- + GetWriteWatchPageCount(&decommitSegments)
- + GetAllWriteWatchPageCount(&fullSegments)
- + GetAllWriteWatchPageCount(&largeSegments);
- ResumeIdleDecommit();
- return count;
- }
- size_t
- RecyclerPageAllocator::GetWriteWatchPageCount(DListBase<PageSegment> * segmentList)
- {
- size_t totalCount = 0;
- DListBase<PageSegment>::Iterator i(segmentList);
- while (i.Next())
- {
- PageSegment& segment = i.Data();
- size_t pageCount = segment.GetAvailablePageCount();
- Assert(pageCount <= MAXUINT32);
- PageSegment::PageBitVector unallocPages = segment.GetUnAllocatedPages();
- for (uint index = 0u; index < pageCount; index++)
- {
- if (unallocPages.Test(index))
- {
- continue;
- }
- char * address = segment.GetAddress() + index * AutoSystemInfo::PageSize;
- void * written;
- ULONG_PTR count = 0;
- DWORD pageSize = AutoSystemInfo::PageSize;
- if (::GetWriteWatch(0, address, AutoSystemInfo::PageSize, &written, &count, &pageSize) == 0)
- {
- #if DBG_DUMP
- Output::Print(_u("GetWriteWatch failed for %p\n"), segment.GetAddress());
- Output::Flush();
- #endif
- // shouldn't happen
- Assert(false);
- }
- else
- {
- Assert(count <= 1);
- Assert(pageSize == AutoSystemInfo::PageSize);
- Assert(count == 0 || written == address);
- totalCount += count;
- }
- }
- }
- return totalCount;
- }
- template <typename T>
- size_t
- RecyclerPageAllocator::GetAllWriteWatchPageCount(DListBase<T> * segmentList)
- {
- size_t totalCount = 0;
- _TYPENAME DListBase<T>::Iterator it(segmentList);
- while (it.Next())
- {
- T& segment = it.Data();
- for (uint i = 0; i < segment.GetPageCount(); i++)
- {
- void * address = segment.GetAddress() + i * AutoSystemInfo::PageSize;
- void * written;
- ULONG_PTR count = 0;
- DWORD pageSize = AutoSystemInfo::PageSize;
- if (::GetWriteWatch(0, address, AutoSystemInfo::PageSize, &written, &count, &pageSize) == 0)
- {
- #if DBG_DUMP
- Output::Print(_u("GetWriteWatch failed for %p\n"), segment.GetAddress());
- Output::Flush();
- #endif
- // shouldn't happen
- Assert(false);
- }
- else
- {
- Assert(count <= 1);
- Assert(pageSize == AutoSystemInfo::PageSize);
- Assert(count == 0 || written == address);
- totalCount += count;
- }
- }
- }
- return totalCount;
- }
- #endif
- #endif
- #endif
|