| Index: src/heap/heap.cc
|
| diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
| index fb7e0325ac7cb4f0914c44294a8c269324a62a2e..51d09edf32b2f77286a23fa85edcd703f15af12c 100644
|
| --- a/src/heap/heap.cc
|
| +++ b/src/heap/heap.cc
|
| @@ -157,6 +157,9 @@
|
| current_gc_flags_(Heap::kNoGCFlags),
|
| current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags),
|
| external_string_table_(this),
|
| + chunks_queued_for_free_(NULL),
|
| + concurrent_unmapping_tasks_active_(0),
|
| + pending_unmapping_tasks_semaphore_(0),
|
| gc_callbacks_depth_(0),
|
| deserialization_complete_(false),
|
| strong_roots_list_(NULL),
|
| @@ -5442,6 +5445,8 @@
|
| delete scavenge_job_;
|
| scavenge_job_ = nullptr;
|
|
|
| + WaitUntilUnmappingOfFreeChunksCompleted();
|
| +
|
| delete array_buffer_tracker_;
|
| array_buffer_tracker_ = nullptr;
|
|
|
| @@ -6244,6 +6249,75 @@
|
| heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i]));
|
| }
|
| old_space_strings_.Free();
|
| +}
|
| +
|
| +
|
| +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_unmapping_tasks_semaphore_.Signal();
|
| + }
|
| +
|
| + Heap* heap_;
|
| + MemoryChunk* head_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask);
|
| +};
|
| +
|
| +
|
| +void Heap::WaitUntilUnmappingOfFreeChunksCompleted() {
|
| + while (concurrent_unmapping_tasks_active_ > 0) {
|
| + pending_unmapping_tasks_semaphore_.Wait();
|
| + concurrent_unmapping_tasks_active_--;
|
| + }
|
| +}
|
| +
|
| +
|
| +void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
|
| + // PreFree logically frees the memory chunk. However, the actual freeing
|
| + // will happen on a separate thread sometime later.
|
| + memory_allocator()->PreFreeMemory(chunk);
|
| +
|
| + // The chunks added to this queue will be freed by a concurrent thread.
|
| + chunk->set_next_chunk(chunks_queued_for_free_);
|
| + chunks_queued_for_free_ = chunk;
|
| +}
|
| +
|
| +
|
| +void Heap::FreeQueuedChunks() {
|
| + if (chunks_queued_for_free_ != NULL) {
|
| + if (FLAG_concurrent_sweeping) {
|
| + V8::GetCurrentPlatform()->CallOnBackgroundThread(
|
| + new UnmapFreeMemoryTask(this, chunks_queued_for_free_),
|
| + v8::Platform::kShortRunningTask);
|
| + } else {
|
| + FreeQueuedChunks(chunks_queued_for_free_);
|
| + pending_unmapping_tasks_semaphore_.Signal();
|
| + }
|
| + chunks_queued_for_free_ = NULL;
|
| + } else {
|
| + // If we do not have anything to unmap, we just signal the semaphore
|
| + // that we are done.
|
| + pending_unmapping_tasks_semaphore_.Signal();
|
| + }
|
| + concurrent_unmapping_tasks_active_++;
|
| +}
|
| +
|
| +
|
| +void Heap::FreeQueuedChunks(MemoryChunk* list_head) {
|
| + MemoryChunk* next;
|
| + MemoryChunk* chunk;
|
| + for (chunk = list_head; chunk != NULL; chunk = next) {
|
| + next = chunk->next_chunk();
|
| + memory_allocator()->PerformFreeMemory(chunk);
|
| + }
|
| }
|
|
|
|
|
|
|