// 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.

#ifndef V8_HEAP_ALLOCATION_STATS_H_
#define V8_HEAP_ALLOCATION_STATS_H_

#include <atomic>
#include <unordered_map>

#include "src/base/macros.h"
#include "src/heap/basic-memory-chunk.h"

namespace v8 {
namespace internal {

// An abstraction of the accounting statistics of a page-structured space.
//
// The stats are only set by functions that ensure they stay balanced. These
// functions increase or decrease one of the non-capacity stats in conjunction
// with capacity, or else they always balance increases and decreases to the
// non-capacity stats.
class AllocationStats {
 public:
  AllocationStats() { Clear(); }

  AllocationStats& operator=(const AllocationStats& stats) V8_NOEXCEPT {
    capacity_ = stats.capacity_.load();
    max_capacity_ = stats.max_capacity_;
    size_.store(stats.size_);
#ifdef DEBUG
    allocated_on_page_ = stats.allocated_on_page_;
#endif
    return *this;
  }

  // Zero out all the allocation statistics (i.e., no capacity).
  void Clear() {
    capacity_ = 0;
    max_capacity_ = 0;
    ClearSize();
  }

  void ClearSize() {
    size_ = 0;
#ifdef DEBUG
    allocated_on_page_.clear();
#endif
  }

  // Accessors for the allocation statistics.
  size_t Capacity() const { return capacity_; }
  size_t MaxCapacity() const { return max_capacity_; }
  size_t Size() const { return size_; }
#ifdef DEBUG
  size_t AllocatedOnPage(const BasicMemoryChunk* page) const {
    return allocated_on_page_.at(page);
  }
#endif

  void IncreaseAllocatedBytes(size_t bytes, const BasicMemoryChunk* page) {
#ifdef DEBUG
    size_t size = size_;
    DCHECK_GE(size + bytes, size);
#endif
    size_.fetch_add(bytes);
#ifdef DEBUG
    allocated_on_page_[page] += bytes;
#endif
  }

  void DecreaseAllocatedBytes(size_t bytes, const BasicMemoryChunk* page) {
    DCHECK_GE(size_, bytes);
    size_.fetch_sub(bytes);
#ifdef DEBUG
    DCHECK_GE(allocated_on_page_[page], bytes);
    allocated_on_page_[page] -= bytes;
#endif
  }

  void DecreaseCapacity(size_t bytes) {
    DCHECK_GE(capacity_, bytes);
    DCHECK_GE(capacity_ - bytes, size_);
    capacity_ -= bytes;
  }

  void IncreaseCapacity(size_t bytes) {
    DCHECK_GE(capacity_ + bytes, capacity_);
    capacity_ += bytes;
    if (capacity_ > max_capacity_) {
      max_capacity_ = capacity_;
    }
  }

 private:
  // |capacity_|: The number of object-area bytes (i.e., not including page
  // bookkeeping structures) currently in the space.
  // During evacuation capacity of the main spaces is accessed from multiple
  // threads to check the old generation hard limit.
  std::atomic<size_t> capacity_;

  // |max_capacity_|: The maximum capacity ever observed.
  size_t max_capacity_;

  // |size_|: The number of allocated bytes.
  std::atomic<size_t> size_;

#ifdef DEBUG
  std::unordered_map<const BasicMemoryChunk*, size_t, BasicMemoryChunk::Hasher>
      allocated_on_page_;
#endif
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_ALLOCATION_STATS_H_
