// Copyright 2015 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_OBJECT_STATS_H_
#define V8_HEAP_OBJECT_STATS_H_

#include "src/heap/heap.h"
#include "src/heap/objects-visiting.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

class ObjectStats {
 public:
  explicit ObjectStats(Heap* heap) : heap_(heap) {}

  // ObjectStats are kept in two arrays, counts and sizes. Related stats are
  // stored in a contiguous linear buffer. Stats groups are stored one after
  // another.
  enum {
    FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1,
    FIRST_FIXED_ARRAY_SUB_TYPE =
        FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS,
    FIRST_CODE_AGE_SUB_TYPE =
        FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1,
    OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kCodeAgeCount + 1
  };

  void ClearObjectStats(bool clear_last_time_stats = false);

  void TraceObjectStats();
  void TraceObjectStat(const char* name, int count, int size, double time);
  void CheckpointObjectStats();

  void RecordObjectStats(InstanceType type, size_t size) {
    DCHECK(type <= LAST_TYPE);
    object_counts_[type]++;
    object_sizes_[type] += size;
  }

  void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) {
    int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type;
    int code_age_index =
        FIRST_CODE_AGE_SUB_TYPE + code_age - Code::kFirstCodeAge;
    DCHECK(code_sub_type_index >= FIRST_CODE_KIND_SUB_TYPE &&
           code_sub_type_index < FIRST_CODE_AGE_SUB_TYPE);
    DCHECK(code_age_index >= FIRST_CODE_AGE_SUB_TYPE &&
           code_age_index < OBJECT_STATS_COUNT);
    object_counts_[code_sub_type_index]++;
    object_sizes_[code_sub_type_index] += size;
    object_counts_[code_age_index]++;
    object_sizes_[code_age_index] += size;
  }

  void RecordFixedArraySubTypeStats(int array_sub_type, size_t size) {
    DCHECK(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE);
    object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++;
    object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size;
  }

  size_t object_count_last_gc(size_t index) {
    return object_counts_last_time_[index];
  }

  size_t object_size_last_gc(size_t index) {
    return object_sizes_last_time_[index];
  }

  Isolate* isolate();
  Heap* heap() { return heap_; }

 private:
  Heap* heap_;

  // Object counts and used memory by InstanceType
  size_t object_counts_[OBJECT_STATS_COUNT];
  size_t object_counts_last_time_[OBJECT_STATS_COUNT];
  size_t object_sizes_[OBJECT_STATS_COUNT];
  size_t object_sizes_last_time_[OBJECT_STATS_COUNT];
};

class ObjectStatsCollector {
 public:
  static void CollectStatistics(StaticVisitorBase::VisitorId id, Map* map,
                                HeapObject* obj);
  static void CollectFixedArrayStatistics(HeapObject* obj);

  static void CountFixedArray(FixedArrayBase* fixed_array,
                              FixedArraySubInstanceType fast_type,
                              FixedArraySubInstanceType dictionary_type);
  static void RecordMapStats(Map* map, HeapObject* obj);
  static void RecordCodeStats(Map* map, HeapObject* obj);
  static void RecordSharedFunctionInfoStats(Map* map, HeapObject* obj);
  static void RecordFixedArrayStats(Map* map, HeapObject* obj);
};

class MarkCompactObjectStatsVisitor
    : public StaticMarkingVisitor<MarkCompactObjectStatsVisitor> {
 public:
  static void Initialize(VisitorDispatchTable<Callback>* original);

  template <VisitorId id>
  static inline void Visit(Map* map, HeapObject* obj);
};

class IncrementalMarkingObjectStatsVisitor
    : public StaticMarkingVisitor<IncrementalMarkingObjectStatsVisitor> {
 public:
  static void Initialize(VisitorDispatchTable<Callback>* original);

  template <VisitorId id>
  static inline void Visit(Map* map, HeapObject* obj);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_OBJECT_STATS_H_
