Index: src/heap/spaces.cc |
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc |
index b6d41e03a1e1c276888f43b2b698e262f9307529..f05dae4f911c31a07a8e38e1c79e07b7b619a7c8 100644 |
--- a/src/heap/spaces.cc |
+++ b/src/heap/spaces.cc |
@@ -335,7 +335,7 @@ class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public v8::Task { |
private: |
// v8::Task overrides. |
void Run() override { |
- unmapper_->PerformFreeMemoryOnQueuedChunks(); |
+ unmapper_->PerformFreeMemoryOnQueuedChunks<FreeMode::kUncommitPooled>(); |
unmapper_->pending_unmapping_tasks_semaphore_.Signal(); |
} |
@@ -350,7 +350,7 @@ void MemoryAllocator::Unmapper::FreeQueuedChunks() { |
new UnmapFreeMemoryTask(this), v8::Platform::kShortRunningTask); |
concurrent_unmapping_tasks_active_++; |
} else { |
- PerformFreeMemoryOnQueuedChunks(); |
+ PerformFreeMemoryOnQueuedChunks<FreeMode::kUncommitPooled>(); |
} |
} |
@@ -364,6 +364,7 @@ bool MemoryAllocator::Unmapper::WaitUntilCompleted() { |
return waited; |
} |
+template <MemoryAllocator::Unmapper::FreeMode mode> |
void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() { |
MemoryChunk* chunk = nullptr; |
// Regular chunks. |
@@ -372,6 +373,14 @@ void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() { |
allocator_->PerformFreeMemory(chunk); |
if (pooled) AddMemoryChunkSafe<kPooled>(chunk); |
} |
+ if (mode == MemoryAllocator::Unmapper::FreeMode::kReleasePooled) { |
+ // The previous loop uncommitted any pages marked as pooled and added them |
+ // to the pooled list. In case of kReleasePooled we need to free them |
+ // though. |
+ while ((chunk = GetMemoryChunkSafe<kPooled>()) != nullptr) { |
+ allocator_->Free<MemoryAllocator::kAlreadyPooled>(chunk); |
+ } |
+ } |
// Non-regular chunks. |
while ((chunk = GetMemoryChunkSafe<kNonRegular>()) != nullptr) { |
allocator_->PerformFreeMemory(chunk); |
@@ -382,7 +391,10 @@ void MemoryAllocator::Unmapper::TearDown() { |
WaitUntilCompleted(); |
ReconsiderDelayedChunks(); |
CHECK(delayed_regular_chunks_.empty()); |
- PerformFreeMemoryOnQueuedChunks(); |
+ PerformFreeMemoryOnQueuedChunks<FreeMode::kReleasePooled>(); |
+ for (int i = 0; i < kNumberOfChunkQueues; i++) { |
+ DCHECK(chunks_[i].empty()); |
+ } |
} |
void MemoryAllocator::Unmapper::ReconsiderDelayedChunks() { |
@@ -909,6 +921,11 @@ void MemoryAllocator::Free(MemoryChunk* chunk) { |
PreFreeMemory(chunk); |
PerformFreeMemory(chunk); |
break; |
+ case kAlreadyPooled: |
+ // Pooled pages cannot be touched anymore as their memory is uncommitted. |
+ FreeMemory(chunk->address(), static_cast<size_t>(MemoryChunk::kPageSize), |
+ Executability::NOT_EXECUTABLE); |
+ break; |
case kPooledAndQueue: |
DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize)); |
DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE); |
@@ -919,13 +936,14 @@ void MemoryAllocator::Free(MemoryChunk* chunk) { |
// The chunks added to this queue will be freed by a concurrent thread. |
unmapper()->AddMemoryChunkSafe(chunk); |
break; |
- default: |
- UNREACHABLE(); |
} |
} |
template void MemoryAllocator::Free<MemoryAllocator::kFull>(MemoryChunk* chunk); |
+template void MemoryAllocator::Free<MemoryAllocator::kAlreadyPooled>( |
+ MemoryChunk* chunk); |
+ |
template void MemoryAllocator::Free<MemoryAllocator::kPreFreeAndQueue>( |
MemoryChunk* chunk); |