Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index c94e15757965bca5b07c7ad2d335a7e64094ff15..a3df6c0af673b431edd91a67b26079b841e8ecbf 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -65,8 +65,7 @@ MarkCompactCollector::MarkCompactCollector(Heap* heap) |
sweeping_in_progress_(false), |
compaction_in_progress_(false), |
pending_sweeper_tasks_semaphore_(0), |
- pending_compaction_tasks_semaphore_(0), |
- concurrent_compaction_tasks_active_(0) { |
+ pending_compaction_tasks_semaphore_(0) { |
} |
#ifdef VERIFY_HEAP |
@@ -481,24 +480,24 @@ void MarkCompactCollector::ClearMarkbits() { |
} |
-class MarkCompactCollector::CompactionTask : public v8::Task { |
+class MarkCompactCollector::CompactionTask : public CancelableTask { |
public: |
explicit CompactionTask(Heap* heap, CompactionSpaceCollection* spaces) |
- : heap_(heap), spaces_(spaces) {} |
+ : CancelableTask(heap->isolate()), spaces_(spaces) {} |
virtual ~CompactionTask() {} |
private: |
- // v8::Task overrides. |
- void Run() override { |
- MarkCompactCollector* mark_compact = heap_->mark_compact_collector(); |
+ // v8::internal::CancelableTask overrides. |
+ void RunInternal() override { |
+ MarkCompactCollector* mark_compact = |
+ isolate()->heap()->mark_compact_collector(); |
SlotsBuffer* evacuation_slots_buffer = nullptr; |
mark_compact->EvacuatePages(spaces_, &evacuation_slots_buffer); |
mark_compact->AddEvacuationSlotsBufferSynchronized(evacuation_slots_buffer); |
mark_compact->pending_compaction_tasks_semaphore_.Signal(); |
} |
- Heap* heap_; |
CompactionSpaceCollection* spaces_; |
DISALLOW_COPY_AND_ASSIGN(CompactionTask); |
@@ -3199,7 +3198,6 @@ void MarkCompactCollector::EvacuatePagesInParallel() { |
} |
const int num_tasks = NumberOfParallelCompactionTasks(); |
- |
// Set up compaction spaces. |
CompactionSpaceCollection** compaction_spaces_for_tasks = |
new CompactionSpaceCollection*[num_tasks]; |
@@ -3212,19 +3210,12 @@ void MarkCompactCollector::EvacuatePagesInParallel() { |
heap()->code_space()->DivideUponCompactionSpaces(compaction_spaces_for_tasks, |
num_tasks); |
- compaction_in_progress_ = true; |
+ uint32_t* task_ids = new uint32_t[num_tasks - 1]; |
// Kick off parallel tasks. |
- for (int i = 1; i < num_tasks; i++) { |
- concurrent_compaction_tasks_active_++; |
- V8::GetCurrentPlatform()->CallOnBackgroundThread( |
- new CompactionTask(heap(), compaction_spaces_for_tasks[i]), |
- v8::Platform::kShortRunningTask); |
- } |
- |
- // Contribute in main thread. Counter and signal are in principal not needed. |
- EvacuatePages(compaction_spaces_for_tasks[0], &migration_slots_buffer_); |
- |
- WaitUntilCompactionCompleted(); |
+ StartParallelCompaction(compaction_spaces_for_tasks, task_ids, num_tasks); |
+ // Wait for unfinished and not-yet-started tasks. |
+ WaitUntilCompactionCompleted(task_ids, num_tasks - 1); |
+ delete[] task_ids; |
double compaction_duration = 0.0; |
intptr_t compacted_memory = 0; |
@@ -3290,10 +3281,32 @@ void MarkCompactCollector::EvacuatePagesInParallel() { |
} |
-void MarkCompactCollector::WaitUntilCompactionCompleted() { |
- while (concurrent_compaction_tasks_active_ > 0) { |
- pending_compaction_tasks_semaphore_.Wait(); |
- concurrent_compaction_tasks_active_--; |
+void MarkCompactCollector::StartParallelCompaction( |
+ CompactionSpaceCollection** compaction_spaces, uint32_t* task_ids, |
+ int len) { |
+ compaction_in_progress_ = true; |
+ for (int i = 1; i < len; i++) { |
+ CompactionTask* task = new CompactionTask(heap(), compaction_spaces[i]); |
+ task_ids[i - 1] = task->id(); |
+ V8::GetCurrentPlatform()->CallOnBackgroundThread( |
+ task, v8::Platform::kShortRunningTask); |
+ } |
+ |
+ // Contribute in main thread. |
+ EvacuatePages(compaction_spaces[0], &migration_slots_buffer_); |
+} |
+ |
+ |
+void MarkCompactCollector::WaitUntilCompactionCompleted(uint32_t* task_ids, |
+ int len) { |
+ // Try to cancel compaction tasks that have not been run (as they might be |
+ // stuck in a worker queue). Tasks that cannot be canceled, have either |
+ // already completed or are still running, hence we need to wait for their |
+ // semaphore signal. |
+ for (int i = 0; i < len; i++) { |
+ if (!heap()->isolate()->cancelable_task_manager()->TryAbort(task_ids[i])) { |
+ pending_compaction_tasks_semaphore_.Wait(); |
+ } |
} |
compaction_in_progress_ = false; |
} |