// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/heap/incremental-marking-job.h"

#include "src/base/platform/time.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
#include "src/heap/incremental-marking.h"
#include "src/isolate.h"
#include "src/v8.h"

namespace v8 {
namespace internal {


void IncrementalMarkingJob::Start(Heap* heap) {
  DCHECK(!heap->incremental_marking()->IsStopped());
  // We don't need to reset the flags because tasks from the previous job
  // can still be pending. We just want to ensure that tasks are posted
  // if they are not pending.
  // If delayed task is pending and made_progress_since_last_delayed_task_ is
  // true, then the delayed task will clear that flag when it is rescheduled.
  ScheduleIdleTask(heap);
  ScheduleDelayedTask(heap);
}


void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }


void IncrementalMarkingJob::NotifyDelayedTask() {
  delayed_task_pending_ = false;
}


void IncrementalMarkingJob::NotifyIdleTaskProgress() {
  made_progress_since_last_delayed_task_ = true;
}


void IncrementalMarkingJob::ScheduleIdleTask(Heap* heap) {
  if (!idle_task_pending_) {
    v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
    if (V8::GetCurrentPlatform()->IdleTasksEnabled(isolate)) {
      idle_task_pending_ = true;
      auto task = new IdleTask(heap->isolate(), this);
      V8::GetCurrentPlatform()->CallIdleOnForegroundThread(isolate, task);
    }
  }
}


void IncrementalMarkingJob::ScheduleDelayedTask(Heap* heap) {
  if (!delayed_task_pending_ && FLAG_memory_reducer) {
    v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
    delayed_task_pending_ = true;
    made_progress_since_last_delayed_task_ = false;
    auto task = new DelayedTask(heap->isolate(), this);
    V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task,
                                                            kDelayInSeconds);
  }
}


IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
    Heap* heap, double deadline_in_ms) {
  IncrementalMarking* incremental_marking = heap->incremental_marking();
  MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector();
  if (incremental_marking->IsStopped()) {
    return kDone;
  }
  if (mark_compact_collector->sweeping_in_progress()) {
    if (mark_compact_collector->IsSweepingCompleted()) {
      mark_compact_collector->EnsureSweepingCompleted();
    }
    return kMoreWork;
  }
  const double remaining_idle_time_in_ms =
      incremental_marking->AdvanceIncrementalMarking(
          0, deadline_in_ms, IncrementalMarking::IdleStepActions());
  if (remaining_idle_time_in_ms > 0.0) {
    heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms);
  }
  return incremental_marking->IsStopped() ? kDone : kMoreWork;
}


void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) {
  double deadline_in_ms =
      deadline_in_seconds *
      static_cast<double>(base::Time::kMillisecondsPerSecond);
  Heap* heap = isolate()->heap();
  double start_ms = heap->MonotonicallyIncreasingTimeInMs();
  job_->NotifyIdleTask();
  job_->NotifyIdleTaskProgress();
  if (Step(heap, deadline_in_ms) == kMoreWork) {
    job_->ScheduleIdleTask(heap);
  }
  if (FLAG_trace_idle_notification) {
    double current_time_ms = heap->MonotonicallyIncreasingTimeInMs();
    double idle_time_in_ms = deadline_in_ms - start_ms;
    double deadline_difference = deadline_in_ms - current_time_ms;
    PrintIsolate(isolate(), "%8.0f ms: ", isolate()->time_millis_since_init());
    PrintF(
        "Idle task: requested idle time %.2f ms, used idle time %.2f "
        "ms, deadline usage %.2f ms\n",
        idle_time_in_ms, idle_time_in_ms - deadline_difference,
        deadline_difference);
  }
}


void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
  const int kIncrementalMarkingDelayMs = 50;
  double deadline =
      heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
  heap->incremental_marking()->AdvanceIncrementalMarking(
      0, deadline, i::IncrementalMarking::StepActions(
                       i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
                       i::IncrementalMarking::FORCE_MARKING,
                       i::IncrementalMarking::FORCE_COMPLETION));
  heap->FinalizeIncrementalMarkingIfComplete(
      "Incremental marking task: finalize incremental marking");
}


void IncrementalMarkingJob::DelayedTask::RunInternal() {
  Heap* heap = isolate()->heap();
  job_->NotifyDelayedTask();
  IncrementalMarking* incremental_marking = heap->incremental_marking();
  if (!incremental_marking->IsStopped()) {
    if (job_->ShouldForceMarkingStep()) {
      Step(heap);
    }
    // The Step() above could have finished incremental marking.
    if (!incremental_marking->IsStopped()) {
      job_->ScheduleDelayedTask(heap);
    }
  }
}

}  // namespace internal
}  // namespace v8
