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 const double IncrementalMarkingJob::kLongDelayInSeconds = 5;
     18 const double IncrementalMarkingJob::kShortDelayInSeconds = 0.5;
     19 
     20 void 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 
     32 void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
     33 
     34 
     35 void IncrementalMarkingJob::NotifyDelayedTask() {
     36   delayed_task_pending_ = false;
     37 }
     38 
     39 
     40 void IncrementalMarkingJob::NotifyIdleTaskProgress() {
     41   made_progress_since_last_delayed_task_ = true;
     42 }
     43 
     44 
     45 void 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 
     57 void 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);
     63     double delay =
     64         heap->HighMemoryPressure() ? kShortDelayInSeconds : kLongDelayInSeconds;
     65     V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task,
     66                                                             delay);
     67   }
     68 }
     69 
     70 
     71 IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
     72     Heap* heap, double deadline_in_ms) {
     73   IncrementalMarking* incremental_marking = heap->incremental_marking();
     74   if (incremental_marking->IsStopped()) {
     75     return kDone;
     76   }
     77   if (incremental_marking->IsSweeping()) {
     78     incremental_marking->FinalizeSweeping();
     79     // TODO(hpayer): We can continue here if enough idle time is left.
     80     return kMoreWork;
     81   }
     82   const double remaining_idle_time_in_ms =
     83       incremental_marking->AdvanceIncrementalMarking(
     84           deadline_in_ms, IncrementalMarking::IdleStepActions());
     85   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 
     92 void 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 
    117 void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
    118   const int kIncrementalMarkingDelayMs = 50;
    119   double deadline =
    120       heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
    121   heap->incremental_marking()->AdvanceIncrementalMarking(
    122       deadline, i::IncrementalMarking::StepActions(
    123                     i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
    124                     i::IncrementalMarking::FORCE_MARKING,
    125                     i::IncrementalMarking::FORCE_COMPLETION));
    126   heap->FinalizeIncrementalMarkingIfComplete(
    127       "Incremental marking task: finalize incremental marking");
    128 }
    129 
    130 
    131 void 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
    148