// 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/objects/code.h"
#include "src/objects/objects.h"

// These instance types do not exist for actual use but are merely introduced
// for object stats tracing. In contrast to Code and FixedArray sub types
// these types are not known to other counters outside of object stats
// tracing.
//
// Update LAST_VIRTUAL_TYPE below when changing this macro.
#define VIRTUAL_INSTANCE_TYPE_LIST(V)            \
  CODE_KIND_LIST(V)                              \
  V(ARRAY_BOILERPLATE_DESCRIPTION_ELEMENTS_TYPE) \
  V(ARRAY_DICTIONARY_ELEMENTS_TYPE)              \
  V(ARRAY_ELEMENTS_TYPE)                         \
  V(BOILERPLATE_ELEMENTS_TYPE)                   \
  V(BOILERPLATE_PROPERTY_ARRAY_TYPE)             \
  V(BOILERPLATE_PROPERTY_DICTIONARY_TYPE)        \
  V(BYTECODE_ARRAY_CONSTANT_POOL_TYPE)           \
  V(BYTECODE_ARRAY_HANDLER_TABLE_TYPE)           \
  V(COW_ARRAY_TYPE)                              \
  V(DEOPTIMIZATION_DATA_TYPE)                    \
  V(DEPENDENT_CODE_TYPE)                         \
  V(DEPRECATED_DESCRIPTOR_ARRAY_TYPE)            \
  V(EMBEDDED_OBJECT_TYPE)                        \
  V(ENUM_KEYS_CACHE_TYPE)                        \
  V(ENUM_INDICES_CACHE_TYPE)                     \
  V(FEEDBACK_VECTOR_ENTRY_TYPE)                  \
  V(FEEDBACK_VECTOR_HEADER_TYPE)                 \
  V(FEEDBACK_VECTOR_SLOT_CALL_TYPE)              \
  V(FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE)       \
  V(FEEDBACK_VECTOR_SLOT_ENUM_TYPE)              \
  V(FEEDBACK_VECTOR_SLOT_LOAD_TYPE)              \
  V(FEEDBACK_VECTOR_SLOT_LOAD_UNUSED_TYPE)       \
  V(FEEDBACK_VECTOR_SLOT_OTHER_TYPE)             \
  V(FEEDBACK_VECTOR_SLOT_STORE_TYPE)             \
  V(FEEDBACK_VECTOR_SLOT_STORE_UNUSED_TYPE)      \
  V(FUNCTION_TEMPLATE_INFO_ENTRIES_TYPE)         \
  V(GLOBAL_ELEMENTS_TYPE)                        \
  V(GLOBAL_PROPERTIES_TYPE)                      \
  V(JS_ARRAY_BOILERPLATE_TYPE)                   \
  V(JS_COLLECTION_TABLE_TYPE)                    \
  V(JS_OBJECT_BOILERPLATE_TYPE)                  \
  V(JS_UNCOMPILED_FUNCTION_TYPE)                 \
  V(MAP_ABANDONED_PROTOTYPE_TYPE)                \
  V(MAP_DEPRECATED_TYPE)                         \
  V(MAP_DICTIONARY_TYPE)                         \
  V(MAP_PROTOTYPE_DICTIONARY_TYPE)               \
  V(MAP_PROTOTYPE_TYPE)                          \
  V(MAP_STABLE_TYPE)                             \
  V(NOSCRIPT_SHARED_FUNCTION_INFOS_TYPE)         \
  V(NUMBER_STRING_CACHE_TYPE)                    \
  V(OBJECT_DICTIONARY_ELEMENTS_TYPE)             \
  V(OBJECT_ELEMENTS_TYPE)                        \
  V(OBJECT_PROPERTY_ARRAY_TYPE)                  \
  V(OBJECT_PROPERTY_DICTIONARY_TYPE)             \
  V(OBJECT_TO_CODE_TYPE)                         \
  V(OPTIMIZED_CODE_LITERALS_TYPE)                \
  V(OTHER_CONTEXT_TYPE)                          \
  V(PROTOTYPE_DESCRIPTOR_ARRAY_TYPE)             \
  V(PROTOTYPE_PROPERTY_ARRAY_TYPE)               \
  V(PROTOTYPE_PROPERTY_DICTIONARY_TYPE)          \
  V(PROTOTYPE_USERS_TYPE)                        \
  V(REGEXP_MULTIPLE_CACHE_TYPE)                  \
  V(RELOC_INFO_TYPE)                             \
  V(RETAINED_MAPS_TYPE)                          \
  V(SCRIPT_LIST_TYPE)                            \
  V(SCRIPT_SHARED_FUNCTION_INFOS_TYPE)           \
  V(SCRIPT_SOURCE_EXTERNAL_ONE_BYTE_TYPE)        \
  V(SCRIPT_SOURCE_EXTERNAL_TWO_BYTE_TYPE)        \
  V(SCRIPT_SOURCE_NON_EXTERNAL_ONE_BYTE_TYPE)    \
  V(SCRIPT_SOURCE_NON_EXTERNAL_TWO_BYTE_TYPE)    \
  V(SERIALIZED_OBJECTS_TYPE)                     \
  V(SINGLE_CHARACTER_STRING_CACHE_TYPE)          \
  V(STRING_SPLIT_CACHE_TYPE)                     \
  V(STRING_EXTERNAL_RESOURCE_ONE_BYTE_TYPE)      \
  V(STRING_EXTERNAL_RESOURCE_TWO_BYTE_TYPE)      \
  V(SOURCE_POSITION_TABLE_TYPE)                  \
  V(UNCOMPILED_SHARED_FUNCTION_INFO_TYPE)        \
  V(WEAK_NEW_SPACE_OBJECT_TO_CODE_TYPE)

namespace v8 {
namespace internal {

class Heap;
class Isolate;

class ObjectStats {
 public:
  static const size_t kNoOverAllocation = 0;

  explicit ObjectStats(Heap* heap) : heap_(heap) { ClearObjectStats(); }

  // See description on VIRTUAL_INSTANCE_TYPE_LIST.
  enum VirtualInstanceType {
#define DEFINE_VIRTUAL_INSTANCE_TYPE(type) type,
    VIRTUAL_INSTANCE_TYPE_LIST(DEFINE_VIRTUAL_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
        LAST_VIRTUAL_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_TYPE,
  };

  // 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_VIRTUAL_TYPE = LAST_TYPE + 1,
    OBJECT_STATS_COUNT = FIRST_VIRTUAL_TYPE + LAST_VIRTUAL_TYPE + 1,
  };

  void ClearObjectStats(bool clear_last_time_stats = false);

  void PrintJSON(const char* key);
  void Dump(std::stringstream& stream);

  void CheckpointObjectStats();
  void RecordObjectStats(InstanceType type, size_t size,
                         size_t over_allocated = kNoOverAllocation);
  void RecordVirtualObjectStats(VirtualInstanceType type, size_t size,
                                size_t over_allocated);

  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:
  static const int kFirstBucketShift = 5;  // <32
  static const int kLastBucketShift = 20;  // >=1M
  static const int kFirstBucket = 1 << kFirstBucketShift;
  static const int kLastBucket = 1 << kLastBucketShift;
  static const int kNumberOfBuckets = kLastBucketShift - kFirstBucketShift + 1;
  static const int kLastValueBucketIndex = kLastBucketShift - kFirstBucketShift;

  void PrintKeyAndId(const char* key, int gc_count);
  // The following functions are excluded from inline to reduce the overall
  // binary size of VB. On x64 this save around 80KB.
  V8_NOINLINE void PrintInstanceTypeJSON(const char* key, int gc_count,
                                         const char* name, int index);
  V8_NOINLINE void DumpInstanceTypeData(std::stringstream& stream,
                                        const char* name, int index);

  int HistogramIndexFromSize(size_t size);

  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];
  // Approximation of overallocated memory by InstanceType.
  size_t over_allocated_[OBJECT_STATS_COUNT];
  // Detailed histograms by InstanceType.
  size_t size_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets];
  size_t over_allocated_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets];

  size_t tagged_fields_count_;
  size_t embedder_fields_count_;
  size_t unboxed_double_fields_count_;
  size_t raw_fields_count_;

  friend class ObjectStatsCollectorImpl;
};

class ObjectStatsCollector {
 public:
  ObjectStatsCollector(Heap* heap, ObjectStats* live, ObjectStats* dead)
      : heap_(heap), live_(live), dead_(dead) {
    DCHECK_NOT_NULL(heap_);
    DCHECK_NOT_NULL(live_);
    DCHECK_NOT_NULL(dead_);
  }

  // Collects type information of live and dead objects. Requires mark bits to
  // be present.
  void Collect();

 private:
  Heap* const heap_;
  ObjectStats* const live_;
  ObjectStats* const dead_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_OBJECT_STATS_H_
