Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index e36e2f8f08f14e5a48e18e3949c0021030a017c5..7f4d539b057f64c7e275c3c2c9c77f143d27f148 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -135,6 +135,7 @@ Heap::Heap() |
current_gc_flags_(Heap::kNoGCFlags), |
external_string_table_(this), |
chunks_queued_for_free_(NULL), |
+ pending_unmap_job_semaphore_(0), |
gc_callbacks_depth_(0), |
deserialization_complete_(false), |
concurrent_sweeping_enabled_(false), |
@@ -6562,6 +6563,33 @@ void ExternalStringTable::TearDown() { |
} |
+class Heap::UnmapFreeMemoryTask : public v8::Task { |
+ public: |
+ UnmapFreeMemoryTask(Heap* heap, MemoryChunk* head) |
+ : heap_(heap), head_(head) {} |
+ virtual ~UnmapFreeMemoryTask() {} |
+ |
+ private: |
+ // v8::Task overrides. |
+ void Run() override { |
+ heap_->FreeQueuedChunks(head_); |
+ heap_->pending_unmap_job_semaphore_.Signal(); |
+ } |
+ |
+ Heap* heap_; |
+ MemoryChunk* head_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask); |
+}; |
+ |
+ |
+void Heap::WaitUntilUnmappingOfFreeChunksCompleted() { |
+ // We start an unmap job after sweeping and after compaction. |
+ pending_unmap_job_semaphore_.Wait(); |
+ pending_unmap_job_semaphore_.Wait(); |
+} |
+ |
+ |
void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
chunk->set_next_chunk(chunks_queued_for_free_); |
chunks_queued_for_free_ = chunk; |
@@ -6576,19 +6604,32 @@ void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { |
next = chunk->next_chunk(); |
chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); |
} |
- isolate_->heap()->store_buffer()->Compact(); |
- isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
+ store_buffer()->Compact(); |
+ store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
} |
void Heap::FreeQueuedChunks() { |
+ if (chunks_queued_for_free_ != NULL) { |
+ V8::GetCurrentPlatform()->CallOnBackgroundThread( |
+ new UnmapFreeMemoryTask(this, chunks_queued_for_free_), |
+ v8::Platform::kShortRunningTask); |
+ chunks_queued_for_free_ = NULL; |
+ } else { |
+ // If we do not have anything to unmap, we just signal the semaphore |
+ // that we are done. |
+ pending_unmap_job_semaphore_.Signal(); |
+ } |
+} |
+ |
+ |
+void Heap::FreeQueuedChunks(MemoryChunk* list_head) { |
MemoryChunk* next; |
MemoryChunk* chunk; |
- for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
+ for (chunk = list_head; chunk != NULL; chunk = next) { |
next = chunk->next_chunk(); |
isolate_->memory_allocator()->Free(chunk); |
} |
- chunks_queued_for_free_ = NULL; |
} |