#ifndef V8_HEAP_ALLOCATION_STATS_H_
#define V8_HEAP_ALLOCATION_STATS_H_
#include <atomic>
#include <unordered_map>
#include "src/base/hashing.h"
#include "src/base/macros.h"
#include "src/heap/memory-chunk-metadata.h"
namespace v8 {
namespace internal {
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;
}
void Clear() {
capacity_ = 0;
max_capacity_ = 0;
ClearSize();
}
void ClearSize() {
size_ = 0;
#ifdef DEBUG
allocated_on_page_.clear();
#endif
}
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 MemoryChunkMetadata* page) const {
return allocated_on_page_.at(page);
}
#endif
void IncreaseAllocatedBytes(size_t bytes, const MemoryChunkMetadata* page) {
DCHECK_IMPLIES(V8_COMPRESS_POINTERS_8GB_BOOL,
IsAligned(bytes, kObjectAlignment8GbHeap));
#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 MemoryChunkMetadata* 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:
std::atomic<size_t> capacity_;
size_t max_capacity_;
std::atomic<size_t> size_;
#ifdef DEBUG
std::unordered_map<const MemoryChunkMetadata*, size_t,
base::hash<const MemoryChunkMetadata*>>
allocated_on_page_;
#endif
};
}
}
#endif