Index: Source/wtf/PartitionAlloc.cpp |
diff --git a/Source/wtf/PartitionAlloc.cpp b/Source/wtf/PartitionAlloc.cpp |
index e62a9a66235e23719cd2c5eb30ae29ed76cfdc52..caba0de5a7cc0c93db713a57346a66c5259bf672 100644 |
--- a/Source/wtf/PartitionAlloc.cpp |
+++ b/Source/wtf/PartitionAlloc.cpp |
@@ -576,7 +576,7 @@ static ALWAYS_INLINE void* partitionDirectMap(PartitionRootBase* root, int flags |
page->freeCacheIndex = 0; |
bucket->activePagesHead = 0; |
- bucket->freePagesHead = 0; |
+ bucket->freePagesHead = reinterpret_cast<PartitionPage*>(ret + size); |
bucket->slotSize = size; |
bucket->numSystemPagesPerSlotSpan = 0; |
bucket->numFullPages = 0; |
@@ -763,6 +763,47 @@ void partitionFreeSlowPath(PartitionPage* page) |
} |
} |
+bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, void* ptr, size_t newSize) |
+{ |
+ newSize = partitionCookieSizeAdjustAdd(newSize); |
+ ASSERT(partitionDirectMapSize(newSize) == newSize); |
+ |
+ char* realPtr = static_cast<char*>(partitionCookieFreePointerAdjust(ptr)); |
+ PartitionBucket* bucket = partitionPointerToPage(realPtr)->bucket; |
+ |
+ // bucket->slotSize is the current size of the allocation. |
+ // bucket->freePagesHead points to the first system page beyond what we |
+ // first allocated; we can grow the allocation up to that point. |
+ |
+ ASSERT(partitionBucketIsDirectMapped(bucket)); |
+ |
+ if (newSize < bucket->slotSize) { |
+ // Shrink by decommitting unneeded pages and making them inaccessible. |
+ // TODO: maybe refuse if the new size is too much smaller? |
+ decommitSystemPages(realPtr + newSize, bucket->slotSize - newSize); |
+ setSystemPagesInaccessible(realPtr + newSize, kSystemPageSize); |
Jens Widell
2014/02/27 17:10:53
Ought to make all decommitted pages inaccessible (
|
+ } else if (realPtr + newSize <= reinterpret_cast<char*>(bucket->freePagesHead)) { |
+ // Grow within the actually allocated memory. Just need to make the |
+ // pages accessible again. |
+ setSystemPagesAccessible(realPtr + bucket->slotSize, newSize - bucket->slotSize); |
+ |
+#ifndef NDEBUG |
+ memset(realPtr + bucket->slotSize, kUninitializedByte, newSize - bucket->slotSize); |
+#endif |
+ } else { |
+ // We can't perform the realloc in-place. |
+ return false; |
+ } |
+ |
+#ifndef NDEBUG |
+ // Write a new trailing cookie. |
+ partitionCookieWriteValue(realPtr + newSize - kCookieSize); |
+#endif |
+ |
+ bucket->slotSize = newSize; |
+ return true; |
+} |
+ |
void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newSize) |
{ |
#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
@@ -787,11 +828,17 @@ 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; |
} |
+ if (partitionSizeIsDirectMapped(actualOldSize) && partitionSizeIsDirectMapped(actualNewSize)) { |
+ // 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, ptr, actualNewSize)) |
+ return ptr; |
+ } |
+ |
// This realloc cannot be resized in-place. Sadness. |
void* ret = partitionAllocGeneric(root, newSize); |
size_t copySize = actualOldSize; |