| Index: Source/wtf/PartitionAlloc.cpp
|
| diff --git a/Source/wtf/PartitionAlloc.cpp b/Source/wtf/PartitionAlloc.cpp
|
| index e62a9a66235e23719cd2c5eb30ae29ed76cfdc52..de19f7db1e2624c159b7ddfec3d51cc30f86eaaa 100644
|
| --- a/Source/wtf/PartitionAlloc.cpp
|
| +++ b/Source/wtf/PartitionAlloc.cpp
|
| @@ -46,6 +46,7 @@ COMPILE_ASSERT(!(WTF::kSuperPageSize % WTF::kPartitionPageSize), ok_super_page_m
|
| COMPILE_ASSERT(WTF::kSystemPageSize * 4 <= WTF::kPartitionPageSize, ok_partition_page_size);
|
| COMPILE_ASSERT(!(WTF::kPartitionPageSize % WTF::kSystemPageSize), ok_partition_page_multiple);
|
| COMPILE_ASSERT(sizeof(WTF::PartitionPage) <= WTF::kPageMetadataSize, PartitionPage_not_too_big);
|
| +COMPILE_ASSERT(sizeof(WTF::PartitionBucket) <= WTF::kPageMetadataSize, PartitionBucket_not_too_big);
|
| COMPILE_ASSERT(sizeof(WTF::PartitionSuperPageExtentEntry) <= WTF::kPageMetadataSize, PartitionSuperPageExtentEntry_not_too_big);
|
| COMPILE_ASSERT(WTF::kPageMetadataSize * WTF::kNumPartitionPagesPerSuperPage <= WTF::kSystemPageSize, page_metadata_fits_in_hole);
|
| // Check that some of our zanier calculations worked out as expected.
|
| @@ -524,6 +525,16 @@ static ALWAYS_INLINE bool partitionSetNewActivePage(PartitionPage* page)
|
| return false;
|
| }
|
|
|
| +struct PartitionDirectMapExtent {
|
| + size_t mapSize; // Mapped size, not including guard pages and meta-data.
|
| +};
|
| +
|
| +static ALWAYS_INLINE PartitionDirectMapExtent* partitionPageToDirectMapExtent(PartitionPage* page)
|
| +{
|
| + ASSERT(partitionBucketIsDirectMapped(page->bucket));
|
| + return reinterpret_cast<PartitionDirectMapExtent*>(reinterpret_cast<char*>(page) + 2 * kPageMetadataSize);
|
| +}
|
| +
|
| static ALWAYS_INLINE void* partitionDirectMap(PartitionRootBase* root, int flags, size_t size)
|
| {
|
| size = partitionDirectMapSize(size);
|
| @@ -581,17 +592,21 @@ static ALWAYS_INLINE void* partitionDirectMap(PartitionRootBase* root, int flags
|
| bucket->numSystemPagesPerSlotSpan = 0;
|
| bucket->numFullPages = 0;
|
|
|
| + PartitionDirectMapExtent* mapExtent = partitionPageToDirectMapExtent(page);
|
| + mapExtent->mapSize = mapSize - kPartitionPageSize - kSystemPageSize;
|
| +
|
| return ret;
|
| }
|
|
|
| static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page)
|
| {
|
| - size_t unmapSize = page->bucket->slotSize;
|
| + size_t unmapSize = partitionPageToDirectMapExtent(page)->mapSize;
|
| +
|
| // Add on the size of the trailing guard page and preceeding partition
|
| - // page, then round up to allocation granularity.
|
| + // page.
|
| unmapSize += kPartitionPageSize + kSystemPageSize;
|
| - unmapSize += kPageAllocationGranularityOffsetMask;
|
| - unmapSize &= kPageAllocationGranularityBaseMask;
|
| +
|
| + ASSERT(!(unmapSize & kPageAllocationGranularityOffsetMask));
|
|
|
| char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page));
|
| // Account for the mapping starting a partition page before the actual
|
| @@ -763,6 +778,54 @@ void partitionFreeSlowPath(PartitionPage* page)
|
| }
|
| }
|
|
|
| +bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPage* page, size_t newSize)
|
| +{
|
| + ASSERT(partitionBucketIsDirectMapped(page->bucket));
|
| +
|
| + newSize = partitionCookieSizeAdjustAdd(newSize);
|
| +
|
| + // Note that the new size might be a bucketed size; this function is called
|
| + // whenever we're reallocating a direct mapped allocation.
|
| + newSize = partitionDirectMapSize(newSize);
|
| + if (newSize < kGenericMinDirectMappedDownsize)
|
| + return false;
|
| +
|
| + // bucket->slotSize is the current size of the allocation.
|
| + size_t currentSize = page->bucket->slotSize;
|
| + if (newSize == currentSize)
|
| + return true;
|
| +
|
| + char* charPtr = static_cast<char*>(partitionPageToPointer(page));
|
| +
|
| + if (newSize < currentSize) {
|
| + // Shrink by decommitting unneeded pages and making them inaccessible.
|
| + size_t decommitSize = currentSize - newSize;
|
| + decommitSystemPages(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);
|
| +
|
| +#ifndef NDEBUG
|
| + memset(charPtr + currentSize, kUninitializedByte, recommitSize);
|
| +#endif
|
| + } else {
|
| + // We can't perform the realloc in-place.
|
| + // TODO: support this too when possible.
|
| + return false;
|
| + }
|
| +
|
| +#ifndef NDEBUG
|
| + // Write a new trailing cookie.
|
| + partitionCookieWriteValue(charPtr + newSize - kCookieSize);
|
| +#endif
|
| +
|
| + page->bucket->slotSize = newSize;
|
| + return true;
|
| +}
|
| +
|
| void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newSize)
|
| {
|
| #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
|
| @@ -775,8 +838,20 @@ void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newS
|
| return 0;
|
| }
|
|
|
| + RELEASE_ASSERT(newSize <= kGenericMaxDirectMapped);
|
| +
|
| ASSERT(partitionPointerIsValid(partitionCookieFreePointerAdjust(ptr)));
|
|
|
| + PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
|
| +
|
| + if (UNLIKELY(partitionBucketIsDirectMapped(page->bucket))) {
|
| + // We may be able to perform the realloc in place by changing the
|
| + // accessibility of memory pages and, if reducing the size, decommitting
|
| + // them.
|
| + if (partitionReallocDirectMappedInPlace(root, page, newSize))
|
| + return ptr;
|
| + }
|
| +
|
| size_t actualNewSize = partitionAllocActualSize(root, newSize);
|
| size_t actualOldSize = partitionAllocGetSize(ptr);
|
|
|
| @@ -787,8 +862,6 @@ void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newS
|
| // Trying to allocate a block of size newSize would give us a block of
|
| // the same size as the one we've already got, so no point in doing
|
| // anything here.
|
| - // TODO: for an upsize or downsize on a direct mapped allocation, we
|
| - // should really try and resize it in-place.
|
| return ptr;
|
| }
|
|
|
|
|