Index: Source/wtf/PartitionAlloc.cpp |
diff --git a/Source/wtf/PartitionAlloc.cpp b/Source/wtf/PartitionAlloc.cpp |
index a63a684c51980189aed9ab281b326c9f54d06ac4..15c8286edef49b243c0d9d5658b9c32767d577ba 100644 |
--- a/Source/wtf/PartitionAlloc.cpp |
+++ b/Source/wtf/PartitionAlloc.cpp |
@@ -112,6 +112,7 @@ static void parititonAllocBaseInit(PartitionRootBase* root) |
spinLockUnlock(&PartitionRootBase::gInitializedLock); |
root->initialized = true; |
+ root->totalSizeOfCommittedPages = 0; |
root->totalSizeOfSuperPages = 0; |
root->nextSuperPage = 0; |
root->nextPartitionPage = 0; |
@@ -308,12 +309,26 @@ static NEVER_INLINE void partitionFull() |
IMMEDIATE_CRASH(); |
} |
+static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) |
+{ |
+ decommitSystemPages(addr, len); |
+ ASSERT(root->totalSizeOfCommittedPages > len); |
+ root->totalSizeOfCommittedPages -= len; |
+} |
+ |
+static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) |
+{ |
+ recommitSystemPages(addr, len); |
+ root->totalSizeOfCommittedPages += len; |
+} |
+ |
static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, size_t numPartitionPages) |
{ |
ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPage) % kPartitionPageSize)); |
ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPageEnd) % kPartitionPageSize)); |
RELEASE_ASSERT(numPartitionPages <= kNumPartitionPagesPerSuperPage); |
size_t totalSize = kPartitionPageSize * numPartitionPages; |
+ root->totalSizeOfCommittedPages += totalSize; |
size_t numPartitionPagesLeft = (root->nextPartitionPageEnd - root->nextPartitionPage) >> kPartitionPageShift; |
if (LIKELY(numPartitionPagesLeft >= numPartitionPages)) { |
// In this case, we can still hand out pages from the current super page |
@@ -382,11 +397,11 @@ static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, |
return ret; |
} |
-static ALWAYS_INLINE void partitionUnusePage(PartitionPage* page) |
+static ALWAYS_INLINE void partitionUnusePage(PartitionRootBase* root, PartitionPage* page) |
{ |
ASSERT(page->bucket->numSystemPagesPerSlotSpan); |
void* addr = partitionPageToPointer(page); |
- decommitSystemPages(addr, page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize); |
+ partitionDecommitSystemPages(root, addr, page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize); |
} |
static ALWAYS_INLINE size_t partitionBucketSlots(const PartitionBucket* bucket) |
@@ -675,7 +690,7 @@ void* partitionAllocSlowPath(PartitionRootBase* root, int flags, size_t size, Pa |
ASSERT(newPage->freeCacheIndex == -1); |
bucket->freePagesHead = newPage->nextPage; |
void* addr = partitionPageToPointer(newPage); |
- recommitSystemPages(addr, newPage->bucket->numSystemPagesPerSlotSpan * kSystemPageSize); |
+ partitionRecommitSystemPages(root, addr, newPage->bucket->numSystemPagesPerSlotSpan * kSystemPageSize); |
} else { |
// Third. If we get here, we need a brand new page. |
size_t numPartitionPages = partitionBucketPartitionPages(bucket); |
@@ -693,11 +708,11 @@ void* partitionAllocSlowPath(PartitionRootBase* root, int flags, size_t size, Pa |
return partitionPageAllocAndFillFreelist(newPage); |
} |
-static ALWAYS_INLINE void partitionFreePage(PartitionPage* page) |
+static ALWAYS_INLINE void partitionFreePage(PartitionRootBase* root, PartitionPage* page) |
{ |
ASSERT(page->freelistHead); |
ASSERT(!page->numAllocatedSlots); |
- partitionUnusePage(page); |
+ partitionUnusePage(root, page); |
// We actually leave the freed page in the active list. We'll sweep it on |
// to the free page list when we next walk the active page list. Pulling |
// this trick enables us to use a singly-linked page list for all cases, |
@@ -710,6 +725,7 @@ static ALWAYS_INLINE void partitionFreePage(PartitionPage* page) |
static ALWAYS_INLINE void partitionRegisterEmptyPage(PartitionPage* page) |
{ |
PartitionRootBase* root = partitionPageToRoot(page); |
+ |
// If the page is already registered as empty, give it another life. |
if (page->freeCacheIndex != -1) { |
ASSERT(page->freeCacheIndex >= 0); |
@@ -729,7 +745,7 @@ static ALWAYS_INLINE void partitionRegisterEmptyPage(PartitionPage* page) |
ASSERT(pageToFree == root->globalEmptyPageRing[pageToFree->freeCacheIndex]); |
if (!pageToFree->numAllocatedSlots && pageToFree->freelistHead) { |
// The page is still empty, and not freed, so _really_ free it. |
- partitionFreePage(pageToFree); |
+ partitionFreePage(root, pageToFree); |
} |
pageToFree->freeCacheIndex = -1; |
} |
@@ -757,7 +773,7 @@ void partitionFreeSlowPath(PartitionPage* page) |
partitionDirectUnmap(page); |
return; |
} |
- // If it's the current page, attempt to change it. We'd prefer to leave |
+ // If it's the current active page, attempt to change it. We'd prefer to leave |
// the page empty as a gentle force towards defragmentation. |
if (LIKELY(page == bucket->activePagesHead) && page->nextPage) { |
if (partitionSetNewActivePage(page->nextPage)) { |
@@ -827,14 +843,14 @@ bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPa |
// Shrink by decommitting unneeded pages and making them inaccessible. |
size_t decommitSize = currentSize - newSize; |
- decommitSystemPages(charPtr + newSize, decommitSize); |
+ partitionDecommitSystemPages(root, charPtr + newSize, decommitSize); |
setSystemPagesInaccessible(charPtr + newSize, decommitSize); |
} else if (newSize <= partitionPageToDirectMapExtent(page)->mapSize) { |
// Grow within the actually allocated memory. Just need to make the |
// pages accessible again. |
size_t recommitSize = newSize - currentSize; |
setSystemPagesAccessible(charPtr + currentSize, recommitSize); |
- recommitSystemPages(charPtr + currentSize, recommitSize); |
+ partitionRecommitSystemPages(root, charPtr + currentSize, recommitSize); |
#ifndef NDEBUG |
memset(charPtr + currentSize, kUninitializedByte, recommitSize); |