blob: 3ccbec23d6c6369f239a8941fdec48ff9e7f707f [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/heap/incremental-marking-job.h"
6
7#include "src/base/platform/time.h"
8#include "src/heap/heap-inl.h"
9#include "src/heap/heap.h"
10#include "src/heap/incremental-marking.h"
11#include "src/isolate.h"
12#include "src/v8.h"
13
14namespace v8 {
15namespace internal {
16
Ben Murdochda12d292016-06-02 14:46:10 +010017const double IncrementalMarkingJob::kLongDelayInSeconds = 5;
18const double IncrementalMarkingJob::kShortDelayInSeconds = 0.5;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019
20void IncrementalMarkingJob::Start(Heap* heap) {
21 DCHECK(!heap->incremental_marking()->IsStopped());
22 // We don't need to reset the flags because tasks from the previous job
23 // can still be pending. We just want to ensure that tasks are posted
24 // if they are not pending.
25 // If delayed task is pending and made_progress_since_last_delayed_task_ is
26 // true, then the delayed task will clear that flag when it is rescheduled.
27 ScheduleIdleTask(heap);
28 ScheduleDelayedTask(heap);
29}
30
31
32void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
33
34
35void IncrementalMarkingJob::NotifyDelayedTask() {
36 delayed_task_pending_ = false;
37}
38
39
40void IncrementalMarkingJob::NotifyIdleTaskProgress() {
41 made_progress_since_last_delayed_task_ = true;
42}
43
44
45void IncrementalMarkingJob::ScheduleIdleTask(Heap* heap) {
46 if (!idle_task_pending_) {
47 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
48 if (V8::GetCurrentPlatform()->IdleTasksEnabled(isolate)) {
49 idle_task_pending_ = true;
50 auto task = new IdleTask(heap->isolate(), this);
51 V8::GetCurrentPlatform()->CallIdleOnForegroundThread(isolate, task);
52 }
53 }
54}
55
56
57void IncrementalMarkingJob::ScheduleDelayedTask(Heap* heap) {
58 if (!delayed_task_pending_ && FLAG_memory_reducer) {
59 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
60 delayed_task_pending_ = true;
61 made_progress_since_last_delayed_task_ = false;
62 auto task = new DelayedTask(heap->isolate(), this);
Ben Murdochda12d292016-06-02 14:46:10 +010063 double delay =
64 heap->HighMemoryPressure() ? kShortDelayInSeconds : kLongDelayInSeconds;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task,
Ben Murdochda12d292016-06-02 14:46:10 +010066 delay);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 }
68}
69
70
71IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
72 Heap* heap, double deadline_in_ms) {
73 IncrementalMarking* incremental_marking = heap->incremental_marking();
74 MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector();
75 if (incremental_marking->IsStopped()) {
76 return kDone;
77 }
78 if (mark_compact_collector->sweeping_in_progress()) {
79 if (mark_compact_collector->IsSweepingCompleted()) {
80 mark_compact_collector->EnsureSweepingCompleted();
81 }
82 return kMoreWork;
83 }
84 const double remaining_idle_time_in_ms =
85 incremental_marking->AdvanceIncrementalMarking(
Ben Murdochda12d292016-06-02 14:46:10 +010086 deadline_in_ms, IncrementalMarking::IdleStepActions());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 if (remaining_idle_time_in_ms > 0.0) {
88 heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms);
89 }
90 return incremental_marking->IsStopped() ? kDone : kMoreWork;
91}
92
93
94void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) {
95 double deadline_in_ms =
96 deadline_in_seconds *
97 static_cast<double>(base::Time::kMillisecondsPerSecond);
98 Heap* heap = isolate()->heap();
99 double start_ms = heap->MonotonicallyIncreasingTimeInMs();
100 job_->NotifyIdleTask();
101 job_->NotifyIdleTaskProgress();
102 if (Step(heap, deadline_in_ms) == kMoreWork) {
103 job_->ScheduleIdleTask(heap);
104 }
105 if (FLAG_trace_idle_notification) {
106 double current_time_ms = heap->MonotonicallyIncreasingTimeInMs();
107 double idle_time_in_ms = deadline_in_ms - start_ms;
108 double deadline_difference = deadline_in_ms - current_time_ms;
109 PrintIsolate(isolate(), "%8.0f ms: ", isolate()->time_millis_since_init());
110 PrintF(
111 "Idle task: requested idle time %.2f ms, used idle time %.2f "
112 "ms, deadline usage %.2f ms\n",
113 idle_time_in_ms, idle_time_in_ms - deadline_difference,
114 deadline_difference);
115 }
116}
117
118
119void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
120 const int kIncrementalMarkingDelayMs = 50;
121 double deadline =
122 heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
123 heap->incremental_marking()->AdvanceIncrementalMarking(
Ben Murdochda12d292016-06-02 14:46:10 +0100124 deadline, i::IncrementalMarking::StepActions(
125 i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
126 i::IncrementalMarking::FORCE_MARKING,
127 i::IncrementalMarking::FORCE_COMPLETION));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 heap->FinalizeIncrementalMarkingIfComplete(
129 "Incremental marking task: finalize incremental marking");
130}
131
132
133void IncrementalMarkingJob::DelayedTask::RunInternal() {
134 Heap* heap = isolate()->heap();
135 job_->NotifyDelayedTask();
136 IncrementalMarking* incremental_marking = heap->incremental_marking();
137 if (!incremental_marking->IsStopped()) {
138 if (job_->ShouldForceMarkingStep()) {
139 Step(heap);
140 }
141 // The Step() above could have finished incremental marking.
142 if (!incremental_marking->IsStopped()) {
143 job_->ScheduleDelayedTask(heap);
144 }
145 }
146}
147
148} // namespace internal
149} // namespace v8