Home | History | Annotate | Download | only in heap
      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 
     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 
     30 void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
     31 
     32 
     33 void IncrementalMarkingJob::NotifyDelayedTask() {
     34   delayed_task_pending_ = false;
     35 }
     36 
     37 
     38 void IncrementalMarkingJob::NotifyIdleTaskProgress() {
     39   made_progress_since_last_delayed_task_ = true;
     40 }
     41 
     42 
     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 
     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 
     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 
     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 
    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 
    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