From 9977724cab9b9ad3a16df5134e5805d29e414164 Mon Sep 17 00:00:00 2001 From: Matt Loring Date: Thu, 3 Aug 2017 07:23:13 -0700 Subject: [PATCH] deps: backport f9c4b7a from upstream V8 Original commit message: [heap] Move UnmapFreeMemoryTask to CancelableTask This mitigates the problem of blocking on the main thread when the platform is unable to execute background tasks in a timely manner. Bug: v8:6671 Change-Id: I741d4b7594e8d62721dad32cbfb19551ffacd0c3 Reviewed-on: https://chromium-review.googlesource.com/599528 Commit-Queue: Michael Lippautz Reviewed-by: Ulan Degenbaev Cr-Commit-Position: refs/heads/master@{#47126} --- deps/v8/src/heap/heap.cc | 2 ++ deps/v8/src/heap/heap.h | 4 +++ deps/v8/src/heap/spaces.cc | 40 ++++++++++++++----------- deps/v8/src/heap/spaces.h | 13 +++++--- deps/v8/src/isolate.cc | 1 + deps/v8/test/cctest/heap/test-spaces.cc | 1 + 6 files changed, 40 insertions(+), 21 deletions(-) diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 2b26e0d1b9f0f7..fa47dc825b71d3 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -161,6 +161,7 @@ Heap::Heap() heap_iterator_depth_(0), local_embedder_heap_tracer_(nullptr), fast_promotion_mode_(false), + use_tasks_(true), force_oom_(false), delay_sweeper_tasks_for_testing_(false), pending_layout_change_object_(nullptr) { @@ -5823,6 +5824,7 @@ void Heap::RegisterExternallyReferencedObject(Object** object) { } void Heap::TearDown() { + use_tasks_ = false; #ifdef VERIFY_HEAP if (FLAG_verify_heap) { Verify(); diff --git a/deps/v8/src/heap/heap.h b/deps/v8/src/heap/heap.h index f18f3edd3f1231..7f213eff2724cf 100644 --- a/deps/v8/src/heap/heap.h +++ b/deps/v8/src/heap/heap.h @@ -1016,6 +1016,8 @@ class Heap { // Returns whether SetUp has been called. bool HasBeenSetUp(); + bool use_tasks() const { return use_tasks_; } + // =========================================================================== // Getters for spaces. ======================================================= // =========================================================================== @@ -2375,6 +2377,8 @@ class Heap { bool fast_promotion_mode_; + bool use_tasks_; + // Used for testing purposes. bool force_oom_; bool delay_sweeper_tasks_for_testing_; diff --git a/deps/v8/src/heap/spaces.cc b/deps/v8/src/heap/spaces.cc index 71e1b60be978ec..3e677888280e0c 100644 --- a/deps/v8/src/heap/spaces.cc +++ b/deps/v8/src/heap/spaces.cc @@ -300,7 +300,7 @@ MemoryAllocator::MemoryAllocator(Isolate* isolate) size_executable_(0), lowest_ever_allocated_(reinterpret_cast(-1)), highest_ever_allocated_(reinterpret_cast(0)), - unmapper_(this) {} + unmapper_(isolate->heap(), this) {} bool MemoryAllocator::SetUp(size_t capacity, size_t code_range_size) { capacity_ = RoundUp(capacity, Page::kPageSize); @@ -332,40 +332,46 @@ void MemoryAllocator::TearDown() { code_range_ = nullptr; } -class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public v8::Task { +class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public CancelableTask { public: - explicit UnmapFreeMemoryTask(Unmapper* unmapper) : unmapper_(unmapper) {} + explicit UnmapFreeMemoryTask(Isolate* isolate, Unmapper* unmapper) + : CancelableTask(isolate), unmapper_(unmapper) {} private: - // v8::Task overrides. - void Run() override { + void RunInternal() override { unmapper_->PerformFreeMemoryOnQueuedChunks(); unmapper_->pending_unmapping_tasks_semaphore_.Signal(); } - Unmapper* unmapper_; + Unmapper* const unmapper_; DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask); }; void MemoryAllocator::Unmapper::FreeQueuedChunks() { ReconsiderDelayedChunks(); - if (FLAG_concurrent_sweeping) { + if (heap_->use_tasks() && FLAG_concurrent_sweeping) { + if (concurrent_unmapping_tasks_active_ >= kMaxUnmapperTasks) { + // kMaxUnmapperTasks are already running. Avoid creating any more. + return; + } + UnmapFreeMemoryTask* task = new UnmapFreeMemoryTask(heap_->isolate(), this); + DCHECK_LT(concurrent_unmapping_tasks_active_, kMaxUnmapperTasks); + task_ids_[concurrent_unmapping_tasks_active_++] = task->id(); V8::GetCurrentPlatform()->CallOnBackgroundThread( - new UnmapFreeMemoryTask(this), v8::Platform::kShortRunningTask); - concurrent_unmapping_tasks_active_++; + task, v8::Platform::kShortRunningTask); } else { PerformFreeMemoryOnQueuedChunks(); } } -bool MemoryAllocator::Unmapper::WaitUntilCompleted() { - bool waited = false; - while (concurrent_unmapping_tasks_active_ > 0) { - pending_unmapping_tasks_semaphore_.Wait(); - concurrent_unmapping_tasks_active_--; - waited = true; +void MemoryAllocator::Unmapper::WaitUntilCompleted() { + for (int i = 0; i < concurrent_unmapping_tasks_active_; i++) { + if (heap_->isolate()->cancelable_task_manager()->TryAbort(task_ids_[i]) != + CancelableTaskManager::kTaskAborted) { + pending_unmapping_tasks_semaphore_.Wait(); + } + concurrent_unmapping_tasks_active_ = 0; } - return waited; } template @@ -392,7 +398,7 @@ void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() { } void MemoryAllocator::Unmapper::TearDown() { - WaitUntilCompleted(); + CHECK_EQ(0, concurrent_unmapping_tasks_active_); ReconsiderDelayedChunks(); CHECK(delayed_regular_chunks_.empty()); PerformFreeMemoryOnQueuedChunks(); diff --git a/deps/v8/src/heap/spaces.h b/deps/v8/src/heap/spaces.h index dc49f3d4a03973..5c37482ac2161b 100644 --- a/deps/v8/src/heap/spaces.h +++ b/deps/v8/src/heap/spaces.h @@ -15,6 +15,7 @@ #include "src/base/bits.h" #include "src/base/hashmap.h" #include "src/base/platform/mutex.h" +#include "src/cancelable-task.h" #include "src/flags.h" #include "src/globals.h" #include "src/heap/heap.h" @@ -1149,8 +1150,9 @@ class V8_EXPORT_PRIVATE MemoryAllocator { public: class UnmapFreeMemoryTask; - explicit Unmapper(MemoryAllocator* allocator) - : allocator_(allocator), + Unmapper(Heap* heap, MemoryAllocator* allocator) + : heap_(heap), + allocator_(allocator), pending_unmapping_tasks_semaphore_(0), concurrent_unmapping_tasks_active_(0) { chunks_[kRegular].reserve(kReservedQueueingSlots); @@ -1184,13 +1186,14 @@ class V8_EXPORT_PRIVATE MemoryAllocator { } void FreeQueuedChunks(); - bool WaitUntilCompleted(); + void WaitUntilCompleted(); void TearDown(); bool has_delayed_chunks() { return delayed_regular_chunks_.size() > 0; } private: static const int kReservedQueueingSlots = 64; + static const int kMaxUnmapperTasks = 24; enum ChunkQueueType { kRegular, // Pages of kPageSize that do not live in a CodeRange and @@ -1229,13 +1232,15 @@ class V8_EXPORT_PRIVATE MemoryAllocator { template void PerformFreeMemoryOnQueuedChunks(); + Heap* const heap_; + MemoryAllocator* const allocator_; base::Mutex mutex_; - MemoryAllocator* allocator_; std::vector chunks_[kNumberOfChunkQueues]; // Delayed chunks cannot be processed in the current unmapping cycle because // of dependencies such as an active sweeper. // See MemoryAllocator::CanFreeMemoryChunk. std::list delayed_regular_chunks_; + CancelableTaskManager::Id task_ids_[kMaxUnmapperTasks]; base::Semaphore pending_unmapping_tasks_semaphore_; intptr_t concurrent_unmapping_tasks_active_; diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index faa04848cff43c..366c14fb11dc2b 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -2455,6 +2455,7 @@ void Isolate::Deinit() { } heap_.mark_compact_collector()->EnsureSweepingCompleted(); + heap_.memory_allocator()->unmapper()->WaitUntilCompleted(); DumpAndResetStats(); diff --git a/deps/v8/test/cctest/heap/test-spaces.cc b/deps/v8/test/cctest/heap/test-spaces.cc index 0d625ca408078b..e9d2045f6f4f29 100644 --- a/deps/v8/test/cctest/heap/test-spaces.cc +++ b/deps/v8/test/cctest/heap/test-spaces.cc @@ -370,6 +370,7 @@ TEST(NewSpace) { } new_space.TearDown(); + memory_allocator->unmapper()->WaitUntilCompleted(); memory_allocator->TearDown(); delete memory_allocator; }