#ifndef V8_ZONE_TYPE_STATS_H_
#define V8_ZONE_TYPE_STATS_H_
#include <iosfwd>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include "src/common/globals.h"
namespace v8 {
namespace internal {
class TypeStats;
#ifdef V8_ENABLE_PRECISE_ZONE_STATS
class TypeStats {
public:
TypeStats() = default;
template <typename TypeTag>
void AddAllocated(size_t bytes) {
StatsEntry& entry = map_[std::type_index(typeid(TypeTag))];
entry.allocation_count++;
entry.allocated_bytes += bytes;
constexpr bool kIsIncomplete =
std::is_same<TypeTag, void>::value || std::is_array<TypeTag>::value;
using TypeTagForSizeof =
typename std::conditional<kIsIncomplete, char, TypeTag>::type;
entry.instance_size = sizeof(TypeTagForSizeof);
}
template <typename TypeTag>
void AddDeallocated(size_t bytes) {
StatsEntry& entry = map_[std::type_index(typeid(TypeTag))];
entry.deallocated_bytes += bytes;
}
void MergeWith(const TypeStats& other);
void Dump() const;
private:
struct StatsEntry {
size_t allocation_count = 0;
size_t allocated_bytes = 0;
size_t deallocated_bytes = 0;
size_t instance_size = 0;
};
void Add(std::type_index type_id, const StatsEntry& other_entry) {
StatsEntry& entry = map_[type_id];
entry.allocation_count += other_entry.allocation_count;
entry.allocated_bytes += other_entry.allocated_bytes;
entry.deallocated_bytes += other_entry.deallocated_bytes;
entry.instance_size = other_entry.instance_size;
}
using HashMap = std::unordered_map<std::type_index, StatsEntry>;
HashMap map_;
};
#endif
}
}
#endif