• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
14 namespace v8 {
15 namespace internal {
16 
17 
Start(Heap * heap)18 void 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 
NotifyIdleTask()30 void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
31 
32 
NotifyDelayedTask()33 void IncrementalMarkingJob::NotifyDelayedTask() {
34   delayed_task_pending_ = false;
35 }
36 
37 
NotifyIdleTaskProgress()38 void IncrementalMarkingJob::NotifyIdleTaskProgress() {
39   made_progress_since_last_delayed_task_ = true;
40 }
41 
42 
ScheduleIdleTask(Heap * heap)43 void 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 
ScheduleDelayedTask(Heap * heap)55 void 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 
Step(Heap * heap,double deadline_in_ms)67 IncrementalMarkingJob::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 
RunInternal(double deadline_in_seconds)90 void 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 
Step(Heap * heap)115 void 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 
RunInternal()129 void 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
146