blob: a69dfac2fa6da95c428088b6f674b7be379c9f3c [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
17
18void IncrementalMarkingJob::Start(Heap* heap) {
19 DCHECK(!heap->incremental_marking()->IsStopped());
20 // We don't need to reset the flags because tasks from the previous job
21 // can still be pending. We just want to ensure that tasks are posted
22 // if they are not pending.
23 // If delayed task is pending and made_progress_since_last_delayed_task_ is
24 // true, then the delayed task will clear that flag when it is rescheduled.
25 ScheduleIdleTask(heap);
26 ScheduleDelayedTask(heap);
27}
28
29
30void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
31
32
33void IncrementalMarkingJob::NotifyDelayedTask() {
34 delayed_task_pending_ = false;
35}
36
37
38void IncrementalMarkingJob::NotifyIdleTaskProgress() {
39 made_progress_since_last_delayed_task_ = true;
40}
41
42
43void IncrementalMarkingJob::ScheduleIdleTask(Heap* heap) {
44 if (!idle_task_pending_) {
45 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
46 if (V8::GetCurrentPlatform()->IdleTasksEnabled(isolate)) {
47 idle_task_pending_ = true;
48 auto task = new IdleTask(heap->isolate(), this);
49 V8::GetCurrentPlatform()->CallIdleOnForegroundThread(isolate, task);
50 }
51 }
52}
53
54
55void IncrementalMarkingJob::ScheduleDelayedTask(Heap* heap) {
56 if (!delayed_task_pending_ && FLAG_memory_reducer) {
57 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
58 delayed_task_pending_ = true;
59 made_progress_since_last_delayed_task_ = false;
60 auto task = new DelayedTask(heap->isolate(), this);
61 V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task,
62 kDelayInSeconds);
63 }
64}
65
66
67IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
68 Heap* heap, double deadline_in_ms) {
69 IncrementalMarking* incremental_marking = heap->incremental_marking();
70 MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector();
71 if (incremental_marking->IsStopped()) {
72 return kDone;
73 }
74 if (mark_compact_collector->sweeping_in_progress()) {
75 if (mark_compact_collector->IsSweepingCompleted()) {
76 mark_compact_collector->EnsureSweepingCompleted();
77 }
78 return kMoreWork;
79 }
80 const double remaining_idle_time_in_ms =
81 incremental_marking->AdvanceIncrementalMarking(
82 0, deadline_in_ms, IncrementalMarking::IdleStepActions());
83 if (remaining_idle_time_in_ms > 0.0) {
84 heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms);
85 }
86 return incremental_marking->IsStopped() ? kDone : kMoreWork;
87}
88
89
90void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) {
91 double deadline_in_ms =
92 deadline_in_seconds *
93 static_cast<double>(base::Time::kMillisecondsPerSecond);
94 Heap* heap = isolate()->heap();
95 double start_ms = heap->MonotonicallyIncreasingTimeInMs();
96 job_->NotifyIdleTask();
97 job_->NotifyIdleTaskProgress();
98 if (Step(heap, deadline_in_ms) == kMoreWork) {
99 job_->ScheduleIdleTask(heap);
100 }
101 if (FLAG_trace_idle_notification) {
102 double current_time_ms = heap->MonotonicallyIncreasingTimeInMs();
103 double idle_time_in_ms = deadline_in_ms - start_ms;
104 double deadline_difference = deadline_in_ms - current_time_ms;
105 PrintIsolate(isolate(), "%8.0f ms: ", isolate()->time_millis_since_init());
106 PrintF(
107 "Idle task: requested idle time %.2f ms, used idle time %.2f "
108 "ms, deadline usage %.2f ms\n",
109 idle_time_in_ms, idle_time_in_ms - deadline_difference,
110 deadline_difference);
111 }
112}
113
114
115void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
116 const int kIncrementalMarkingDelayMs = 50;
117 double deadline =
118 heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
119 heap->incremental_marking()->AdvanceIncrementalMarking(
120 0, deadline, i::IncrementalMarking::StepActions(
121 i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
122 i::IncrementalMarking::FORCE_MARKING,
123 i::IncrementalMarking::FORCE_COMPLETION));
124 heap->FinalizeIncrementalMarkingIfComplete(
125 "Incremental marking task: finalize incremental marking");
126}
127
128
129void IncrementalMarkingJob::DelayedTask::RunInternal() {
130 Heap* heap = isolate()->heap();
131 job_->NotifyDelayedTask();
132 IncrementalMarking* incremental_marking = heap->incremental_marking();
133 if (!incremental_marking->IsStopped()) {
134 if (job_->ShouldForceMarkingStep()) {
135 Step(heap);
136 }
137 // The Step() above could have finished incremental marking.
138 if (!incremental_marking->IsStopped()) {
139 job_->ScheduleDelayedTask(heap);
140 }
141 }
142}
143
144} // namespace internal
145} // namespace v8