diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 4a6a551ba45..66e7ade7ac8 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -185,7 +185,7 @@ interface nsIFinishReportingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(a1292276-726b-4ef5-a017-5a455d6664dd)] +[scriptable, builtinclass, uuid(2596fa26-495a-4827-a5f5-e34e7f4dd7b5)] interface nsIMemoryReporterManager : nsISupports { /* @@ -300,6 +300,10 @@ interface nsIMemoryReporterManager : nsISupports * * |pageFaultsHard| (UNITS_COUNT_CUMULATIVE) The number of hard (a.k.a. * major) page faults that have occurred since the process started. + * + * |largestContiguousVMBlock| (UNITS_BYTES) The size of the largest + * contiguous block of virtual memory. Only available on Windows; on all + * other platforms, reading this value returns 0. */ readonly attribute int64_t explicit; readonly attribute int64_t vsize; @@ -325,6 +329,8 @@ interface nsIMemoryReporterManager : nsISupports readonly attribute int64_t pageFaultsHard; + readonly attribute int64_t largestContiguousVMBlock; + /* * This attribute indicates if moz_malloc_usable_size() works. */ diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 90435ce77e4..dfa41367055 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -337,6 +337,7 @@ static nsresult GetResident(int64_t* aN) #include #include +#include #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1 static nsresult GetVsize(int64_t* aN) @@ -370,6 +371,34 @@ static nsresult GetResidentFast(int64_t* aN) return GetResident(aN); } +#define HAVE_LARGEST_CONTIGUOUS_BLOCK_REPORTERS 1 +static nsresult LargestContiguousVMBlock(int64_t* aN) +{ + SIZE_T biggestRegion = 0; + MEMORY_BASIC_INFORMATION vmemInfo = {0}; + for (size_t currentAddress = 0; ; ) { + if (!VirtualQuery((LPCVOID)currentAddress, &vmemInfo, sizeof(vmemInfo))) { + // Something went wrong, just return whatever we've got already. + break; + } + + if (vmemInfo.State == MEM_FREE) { + biggestRegion = std::max(biggestRegion, vmemInfo.RegionSize); + } + + SIZE_T lastAddress = currentAddress; + currentAddress += vmemInfo.RegionSize; + + // If we overflow, we've examined all of the address space. + if (currentAddress < lastAddress) { + break; + } + } + + *aN = biggestRegion; + return NS_OK; +} + #define HAVE_PRIVATE_REPORTER class PrivateReporter MOZ_FINAL : public MemoryUniReporter { @@ -1382,6 +1411,17 @@ nsMemoryReporterManager::GetPageFaultsHard(int64_t* aAmount) #endif } +NS_IMETHODIMP +nsMemoryReporterManager::GetLargestContiguousVMBlock(int64_t* aAmount) +{ +#ifdef HAVE_LARGEST_CONTIGUOUS_BLOCK_REPORTERS + return LargestContiguousVMBlock(aAmount); +#else + *aAmount = 0; + return NS_ERROR_NOT_AVAILABLE; +#endif +} + NS_IMETHODIMP nsMemoryReporterManager::GetHasMozMallocUsableSize(bool* aHas) {