Chromium Code Reviews| 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; |