blob: fe14dd04c68bb09bb31e3e1d80741e180829ff38 [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();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 if (incremental_marking->IsStopped()) {
75 return kDone;
76 }
Ben Murdochc5610432016-08-08 18:44:38 +010077 if (incremental_marking->IsSweeping()) {
78 incremental_marking->FinalizeSweeping();
79 // TODO(hpayer): We can continue here if enough idle time is left.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 return kMoreWork;
81 }
82 const double remaining_idle_time_in_ms =
83 incremental_marking->AdvanceIncrementalMarking(
Ben Murdochda12d292016-06-02 14:46:10 +010084 deadline_in_ms, IncrementalMarking::IdleStepActions());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 if (remaining_idle_time_in_ms > 0.0) {
86 heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms);
87 }
88 return incremental_marking->IsStopped() ? kDone : kMoreWork;
89}
90
91
92void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) {
93 double deadline_in_ms =
94 deadline_in_seconds *
95 static_cast<double>(base::Time::kMillisecondsPerSecond);
96 Heap* heap = isolate()->heap();
97 double start_ms = heap->MonotonicallyIncreasingTimeInMs();
98 job_->NotifyIdleTask();
99 job_->NotifyIdleTaskProgress();
100 if (Step(heap, deadline_in_ms) == kMoreWork) {
101 job_->ScheduleIdleTask(heap);
102 }
103 if (FLAG_trace_idle_notification) {
104 double current_time_ms = heap->MonotonicallyIncreasingTimeInMs();
105 double idle_time_in_ms = deadline_in_ms - start_ms;
106 double deadline_difference = deadline_in_ms - current_time_ms;
107 PrintIsolate(isolate(), "%8.0f ms: ", isolate()->time_millis_since_init());
108 PrintF(
109 "Idle task: requested idle time %.2f ms, used idle time %.2f "
110 "ms, deadline usage %.2f ms\n",
111 idle_time_in_ms, idle_time_in_ms - deadline_difference,
112 deadline_difference);
113 }
114}
115
116
117void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
118 const int kIncrementalMarkingDelayMs = 50;
119 double deadline =
120 heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
121 heap->incremental_marking()->AdvanceIncrementalMarking(
Ben Murdochda12d292016-06-02 14:46:10 +0100122 deadline, i::IncrementalMarking::StepActions(
123 i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
124 i::IncrementalMarking::FORCE_MARKING,
125 i::IncrementalMarking::FORCE_COMPLETION));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 heap->FinalizeIncrementalMarkingIfComplete(
127 "Incremental marking task: finalize incremental marking");
128}
129
130
131void IncrementalMarkingJob::DelayedTask::RunInternal() {
132 Heap* heap = isolate()->heap();
133 job_->NotifyDelayedTask();
134 IncrementalMarking* incremental_marking = heap->incremental_marking();
135 if (!incremental_marking->IsStopped()) {
136 if (job_->ShouldForceMarkingStep()) {
137 Step(heap);
138 }
139 // The Step() above could have finished incremental marking.
140 if (!incremental_marking->IsStopped()) {
141 job_->ScheduleDelayedTask(heap);
142 }
143 }
144}
145
146} // namespace internal
147} // namespace v8