Index: src/heap/incremental-marking-job.cc |
diff --git a/src/heap/incremental-marking-job.cc b/src/heap/incremental-marking-job.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..308d1b9a29f114ddfc7c613edf1a895b8696fccc |
--- /dev/null |
+++ b/src/heap/incremental-marking-job.cc |
@@ -0,0 +1,144 @@ |
+// Copyright 2012 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/heap/incremental-marking-job.h" |
+ |
+#include "src/base/platform/time.h" |
+#include "src/heap/heap-inl.h" |
+#include "src/heap/heap.h" |
+#include "src/heap/incremental-marking.h" |
+#include "src/isolate.h" |
+#include "src/v8.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+ |
+void IncrementalMarkingJob::Start(Heap* heap) { |
+ DCHECK(!heap->incremental_marking()->IsStopped()); |
+ // We don't need to reset the flags because tasks from the previous job |
+ // can still be pending. We just want to ensure that tasks are posted |
+ // if they are not pending. |
+ // If delayed task is pending and made_progress_since_last_delayed_task_ is |
+ // true, then the delayed task will clear that flag when it is rescheduled. |
+ ScheduleIdleTask(heap); |
+ ScheduleDelayedTask(heap); |
+} |
+ |
+ |
+void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; } |
+ |
+ |
+void IncrementalMarkingJob::NotifyDelayedTask() { |
+ delayed_task_pending_ = false; |
+} |
+ |
+ |
+void IncrementalMarkingJob::NotifyIdleTaskProgress() { |
+ made_progress_since_last_delayed_task_ = true; |
+} |
+ |
+ |
+void IncrementalMarkingJob::ScheduleIdleTask(Heap* heap) { |
+ if (!idle_task_pending_) { |
+ v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate()); |
+ if (V8::GetCurrentPlatform()->IdleTasksEnabled(isolate)) { |
+ idle_task_pending_ = true; |
+ auto task = new IdleTask(heap->isolate(), this); |
+ V8::GetCurrentPlatform()->CallIdleOnForegroundThread(isolate, task); |
+ } |
+ } |
+} |
+ |
+ |
+void IncrementalMarkingJob::ScheduleDelayedTask(Heap* heap) { |
+ if (!delayed_task_pending_) { |
+ v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate()); |
+ delayed_task_pending_ = true; |
+ made_progress_since_last_delayed_task_ = false; |
+ auto task = new DelayedTask(heap->isolate(), this); |
+ V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task, |
+ kDelayInSeconds); |
+ } |
+} |
+ |
+ |
+IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step( |
+ Heap* heap, double deadline_in_ms) { |
+ IncrementalMarking* incremental_marking = heap->incremental_marking(); |
+ MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector(); |
+ if (incremental_marking->IsStopped()) { |
+ return kDone; |
+ } |
+ if (mark_compact_collector->sweeping_in_progress()) { |
+ if (mark_compact_collector->IsSweepingCompleted()) { |
+ mark_compact_collector->EnsureSweepingCompleted(); |
+ } |
+ return kMoreWork; |
+ } |
+ const double remaining_idle_time_in_ms = heap->AdvanceIncrementalMarking( |
+ 0, deadline_in_ms, IncrementalMarking::IdleStepActions()); |
+ if (remaining_idle_time_in_ms > 0.0) { |
+ heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms); |
+ } |
+ return incremental_marking->IsStopped() ? kDone : kMoreWork; |
+} |
+ |
+ |
+void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) { |
+ double deadline_in_ms = |
+ deadline_in_seconds * |
+ static_cast<double>(base::Time::kMillisecondsPerSecond); |
+ Heap* heap = isolate_->heap(); |
+ double start_ms = heap->MonotonicallyIncreasingTimeInMs(); |
+ job_->NotifyIdleTask(); |
+ job_->NotifyIdleTaskProgress(); |
+ if (Step(heap, deadline_in_ms) == kMoreWork) { |
+ job_->ScheduleIdleTask(heap); |
+ } |
+ if (FLAG_trace_idle_notification) { |
+ double current_time_ms = heap->MonotonicallyIncreasingTimeInMs(); |
+ double idle_time_in_ms = deadline_in_ms - start_ms; |
+ double deadline_difference = deadline_in_ms - current_time_ms; |
+ PrintIsolate(isolate_, "%8.0f ms: ", isolate_->time_millis_since_init()); |
+ PrintF( |
+ "Idle task: requested idle time %.2f ms, used idle time %.2f " |
+ "ms, deadline usage %.2f ms\n", |
+ idle_time_in_ms, idle_time_in_ms - deadline_difference, |
+ deadline_difference); |
+ } |
+} |
+ |
+ |
+void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) { |
+ const int kIncrementalMarkingDelayMs = 50; |
+ double deadline = |
+ heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs; |
+ heap->AdvanceIncrementalMarking( |
+ 0, deadline, i::IncrementalMarking::StepActions( |
+ i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, |
+ i::IncrementalMarking::FORCE_MARKING, |
+ i::IncrementalMarking::FORCE_COMPLETION)); |
+ heap->FinalizeIncrementalMarkingIfComplete( |
+ "Incremental marking task: finalize incremental marking"); |
+} |
+ |
+ |
+void IncrementalMarkingJob::DelayedTask::RunInternal() { |
+ Heap* heap = isolate_->heap(); |
+ job_->NotifyDelayedTask(); |
+ IncrementalMarking* incremental_marking = heap->incremental_marking(); |
+ if (!incremental_marking->IsStopped()) { |
+ if (job_->ShouldForceMarkingStep()) { |
+ Step(heap); |
+ } |
+ // The Step() above could have finished incremental marking. |
+ if (!incremental_marking->IsStopped()) { |
+ job_->ScheduleDelayedTask(heap); |
+ } |
+ } |
+} |
+ |
+} // namespace internal |
+} // namespace v8 |