// Copyright 2020 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/cppgc/incremental-marking-schedule.h"

#include <cmath>

#include "src/heap/cppgc/globals.h"

namespace cppgc {
namespace internal {

// static
constexpr size_t IncrementalMarkingSchedule::kInvalidLastEstimatedLiveBytes;

const double IncrementalMarkingSchedule::kEstimatedMarkingTimeMs = 500.0;
const size_t IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep =
    64 * kKB;

void IncrementalMarkingSchedule::NotifyIncrementalMarkingStart() {
  DCHECK(incremental_marking_start_time_.IsNull());
  incremental_marking_start_time_ = v8::base::TimeTicks::Now();
}

void IncrementalMarkingSchedule::UpdateIncrementalMarkedBytes(
    size_t overall_marked_bytes) {
  DCHECK(!incremental_marking_start_time_.IsNull());
  incrementally_marked_bytes_ = overall_marked_bytes;
}

void IncrementalMarkingSchedule::AddConcurrentlyMarkedBytes(
    size_t marked_bytes) {
  DCHECK(!incremental_marking_start_time_.IsNull());
  concurrently_marked_bytes_.fetch_add(marked_bytes, std::memory_order_relaxed);
}

size_t IncrementalMarkingSchedule::GetOverallMarkedBytes() const {
  return incrementally_marked_bytes_ + GetConcurrentlyMarkedBytes();
}

size_t IncrementalMarkingSchedule::GetConcurrentlyMarkedBytes() const {
  return concurrently_marked_bytes_.load(std::memory_order_relaxed);
}

double IncrementalMarkingSchedule::GetElapsedTimeInMs(
    v8::base::TimeTicks start_time) {
  if (elapsed_time_for_testing_ != kNoSetElapsedTimeForTesting) {
    double elapsed_time = elapsed_time_for_testing_;
    elapsed_time_for_testing_ = kNoSetElapsedTimeForTesting;
    return elapsed_time;
  }
  return (v8::base::TimeTicks::Now() - start_time).InMillisecondsF();
}

size_t IncrementalMarkingSchedule::GetNextIncrementalStepDuration(
    size_t estimated_live_bytes) {
  last_estimated_live_bytes_ = estimated_live_bytes;
  DCHECK(!incremental_marking_start_time_.IsNull());
  double elapsed_time_in_ms =
      GetElapsedTimeInMs(incremental_marking_start_time_);
  size_t actual_marked_bytes = GetOverallMarkedBytes();
  size_t expected_marked_bytes = std::ceil(
      estimated_live_bytes * elapsed_time_in_ms / kEstimatedMarkingTimeMs);
  if (expected_marked_bytes < actual_marked_bytes) {
    // Marking is ahead of schedule, incremental marking should do the minimum.
    return kMinimumMarkedBytesPerIncrementalStep;
  }
  // Assuming marking will take |kEstimatedMarkingTime|, overall there will
  // be |estimated_live_bytes| live bytes to mark, and that marking speed is
  // constant, after |elapsed_time| the number of marked_bytes should be
  // |estimated_live_bytes| * (|elapsed_time| / |kEstimatedMarkingTime|),
  // denoted as |expected_marked_bytes|.  If |actual_marked_bytes| is less,
  // i.e. marking is behind schedule, incremental marking should help "catch
  // up" by marking (|expected_marked_bytes| - |actual_marked_bytes|).
  return std::max(kMinimumMarkedBytesPerIncrementalStep,
                  expected_marked_bytes - actual_marked_bytes);
}

constexpr double
    IncrementalMarkingSchedule::kEphemeronPairsFlushingRatioIncrements;
bool IncrementalMarkingSchedule::ShouldFlushEphemeronPairs() {
  DCHECK_NE(kInvalidLastEstimatedLiveBytes, last_estimated_live_bytes_);
  if (GetOverallMarkedBytes() <
      (ephemeron_pairs_flushing_ratio_target * last_estimated_live_bytes_))
    return false;
  ephemeron_pairs_flushing_ratio_target +=
      kEphemeronPairsFlushingRatioIncrements;
  return true;
}

}  // namespace internal
}  // namespace cppgc
