// 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/allocation-observer.h"

#include "src/heap/heap.h"
#include "src/heap/spaces.h"

namespace v8 {
namespace internal {

void AllocationCounter::AddAllocationObserver(AllocationObserver* observer) {
#if DEBUG
  auto it = std::find_if(observers_.begin(), observers_.end(),
                         [observer](const AllocationObserverCounter& aoc) {
                           return aoc.observer_ == observer;
                         });
  DCHECK_EQ(observers_.end(), it);
#endif

  if (step_in_progress_) {
    pending_added_.push_back(AllocationObserverCounter(observer, 0, 0));
    return;
  }

  intptr_t step_size = observer->GetNextStepSize();
  size_t observer_next_counter = current_counter_ + step_size;

  observers_.push_back(AllocationObserverCounter(observer, current_counter_,
                                                 observer_next_counter));

  if (observers_.size() == 1) {
    DCHECK_EQ(current_counter_, next_counter_);
    next_counter_ = observer_next_counter;
  } else {
    size_t missing_bytes = next_counter_ - current_counter_;
    next_counter_ =
        current_counter_ + Min(static_cast<intptr_t>(missing_bytes), step_size);
  }
}

void AllocationCounter::RemoveAllocationObserver(AllocationObserver* observer) {
  auto it = std::find_if(observers_.begin(), observers_.end(),
                         [observer](const AllocationObserverCounter& aoc) {
                           return aoc.observer_ == observer;
                         });
  DCHECK_NE(observers_.end(), it);

  if (step_in_progress_) {
    DCHECK_EQ(pending_removed_.count(observer), 0);
    pending_removed_.insert(observer);
    return;
  }

  observers_.erase(it);

  if (observers_.size() == 0) {
    current_counter_ = next_counter_ = 0;
  } else {
    size_t step_size = 0;

    for (AllocationObserverCounter& observer : observers_) {
      size_t left_in_step = observer.next_counter_ - current_counter_;
      DCHECK_GT(left_in_step, 0);
      step_size = step_size ? Min(step_size, left_in_step) : left_in_step;
    }

    next_counter_ = current_counter_ + step_size;
  }
}

void AllocationCounter::AdvanceAllocationObservers(size_t allocated) {
  if (!IsActive()) {
    return;
  }

  DCHECK(!step_in_progress_);
  DCHECK_LT(allocated, next_counter_ - current_counter_);
  current_counter_ += allocated;
}

void AllocationCounter::InvokeAllocationObservers(Address soon_object,
                                                  size_t object_size,
                                                  size_t aligned_object_size) {
  if (!IsActive()) {
    return;
  }

  DCHECK(!step_in_progress_);
  DCHECK_GE(aligned_object_size, next_counter_ - current_counter_);
  DCHECK(soon_object);
  bool step_run = false;
  step_in_progress_ = true;
  size_t step_size = 0;

  DCHECK(pending_added_.empty());
  DCHECK(pending_removed_.empty());

  for (AllocationObserverCounter& aoc : observers_) {
    if (aoc.next_counter_ - current_counter_ <= aligned_object_size) {
      {
        DisallowHeapAllocation disallow_heap_allocation;
        aoc.observer_->Step(
            static_cast<int>(current_counter_ - aoc.prev_counter_), soon_object,
            object_size);
      }
      size_t observer_step_size = aoc.observer_->GetNextStepSize();

      aoc.prev_counter_ = current_counter_;
      aoc.next_counter_ =
          current_counter_ + aligned_object_size + observer_step_size;
      step_run = true;
    }

    size_t left_in_step = aoc.next_counter_ - current_counter_;
    step_size = step_size ? Min(step_size, left_in_step) : left_in_step;
  }

  CHECK(step_run);

  // Now process newly added allocation observers.
  for (AllocationObserverCounter& aoc : pending_added_) {
    size_t observer_step_size = aoc.observer_->GetNextStepSize();
    aoc.prev_counter_ = current_counter_;
    aoc.next_counter_ =
        current_counter_ + aligned_object_size + observer_step_size;

    DCHECK_NE(step_size, 0);
    step_size = Min(step_size, aligned_object_size + observer_step_size);

    observers_.push_back(aoc);
  }

  pending_added_.clear();

  if (!pending_removed_.empty()) {
    observers_.erase(
        std::remove_if(observers_.begin(), observers_.end(),
                       [this](const AllocationObserverCounter& aoc) {
                         return pending_removed_.count(aoc.observer_) != 0;
                       }));
    pending_removed_.clear();

    // Some observers were removed, recalculate step size.
    step_size = 0;
    for (AllocationObserverCounter& aoc : observers_) {
      size_t left_in_step = aoc.next_counter_ - current_counter_;
      step_size = step_size ? Min(step_size, left_in_step) : left_in_step;
    }

    if (observers_.empty()) {
      next_counter_ = current_counter_ = 0;
      step_in_progress_ = false;
      return;
    }
  }

  next_counter_ = current_counter_ + step_size;
  step_in_progress_ = false;
}

PauseAllocationObserversScope::PauseAllocationObserversScope(Heap* heap)
    : heap_(heap) {
  DCHECK_EQ(heap->gc_state(), Heap::NOT_IN_GC);

  for (SpaceIterator it(heap_); it.HasNext();) {
    it.Next()->PauseAllocationObservers();
  }
}

PauseAllocationObserversScope::~PauseAllocationObserversScope() {
  for (SpaceIterator it(heap_); it.HasNext();) {
    it.Next()->ResumeAllocationObservers();
  }
}

}  // namespace internal
}  // namespace v8
