1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_OBJECT_STATS_H_ 6 #define V8_HEAP_OBJECT_STATS_H_ 7 8 #include "src/objects/code.h" 9 #include "src/objects/objects.h" 10 11 // These instance types do not exist for actual use but are merely introduced 12 // for object stats tracing. In contrast to Code and FixedArray sub types 13 // these types are not known to other counters outside of object stats 14 // tracing. 15 // 16 // Update LAST_VIRTUAL_TYPE below when changing this macro. 17 #define VIRTUAL_INSTANCE_TYPE_LIST(V) \ 18 CODE_KIND_LIST(V) \ 19 V(ARRAY_BOILERPLATE_DESCRIPTION_ELEMENTS_TYPE) \ 20 V(ARRAY_DICTIONARY_ELEMENTS_TYPE) \ 21 V(ARRAY_ELEMENTS_TYPE) \ 22 V(BOILERPLATE_ELEMENTS_TYPE) \ 23 V(BOILERPLATE_PROPERTY_ARRAY_TYPE) \ 24 V(BOILERPLATE_PROPERTY_DICTIONARY_TYPE) \ 25 V(BYTECODE_ARRAY_CONSTANT_POOL_TYPE) \ 26 V(BYTECODE_ARRAY_HANDLER_TABLE_TYPE) \ 27 V(COW_ARRAY_TYPE) \ 28 V(DEOPTIMIZATION_DATA_TYPE) \ 29 V(DEPENDENT_CODE_TYPE) \ 30 V(DEPRECATED_DESCRIPTOR_ARRAY_TYPE) \ 31 V(EMBEDDED_OBJECT_TYPE) \ 32 V(ENUM_KEYS_CACHE_TYPE) \ 33 V(ENUM_INDICES_CACHE_TYPE) \ 34 V(FEEDBACK_VECTOR_ENTRY_TYPE) \ 35 V(FEEDBACK_VECTOR_HEADER_TYPE) \ 36 V(FEEDBACK_VECTOR_SLOT_CALL_TYPE) \ 37 V(FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE) \ 38 V(FEEDBACK_VECTOR_SLOT_ENUM_TYPE) \ 39 V(FEEDBACK_VECTOR_SLOT_LOAD_TYPE) \ 40 V(FEEDBACK_VECTOR_SLOT_LOAD_UNUSED_TYPE) \ 41 V(FEEDBACK_VECTOR_SLOT_OTHER_TYPE) \ 42 V(FEEDBACK_VECTOR_SLOT_STORE_TYPE) \ 43 V(FEEDBACK_VECTOR_SLOT_STORE_UNUSED_TYPE) \ 44 V(FUNCTION_TEMPLATE_INFO_ENTRIES_TYPE) \ 45 V(GLOBAL_ELEMENTS_TYPE) \ 46 V(GLOBAL_PROPERTIES_TYPE) \ 47 V(JS_ARRAY_BOILERPLATE_TYPE) \ 48 V(JS_COLLECTION_TABLE_TYPE) \ 49 V(JS_OBJECT_BOILERPLATE_TYPE) \ 50 V(JS_UNCOMPILED_FUNCTION_TYPE) \ 51 V(MAP_ABANDONED_PROTOTYPE_TYPE) \ 52 V(MAP_DEPRECATED_TYPE) \ 53 V(MAP_DICTIONARY_TYPE) \ 54 V(MAP_PROTOTYPE_DICTIONARY_TYPE) \ 55 V(MAP_PROTOTYPE_TYPE) \ 56 V(MAP_STABLE_TYPE) \ 57 V(NUMBER_STRING_CACHE_TYPE) \ 58 V(OBJECT_DICTIONARY_ELEMENTS_TYPE) \ 59 V(OBJECT_ELEMENTS_TYPE) \ 60 V(OBJECT_PROPERTY_ARRAY_TYPE) \ 61 V(OBJECT_PROPERTY_DICTIONARY_TYPE) \ 62 V(OBJECT_TO_CODE_TYPE) \ 63 V(OPTIMIZED_CODE_LITERALS_TYPE) \ 64 V(OTHER_CONTEXT_TYPE) \ 65 V(PROTOTYPE_DESCRIPTOR_ARRAY_TYPE) \ 66 V(PROTOTYPE_PROPERTY_ARRAY_TYPE) \ 67 V(PROTOTYPE_PROPERTY_DICTIONARY_TYPE) \ 68 V(PROTOTYPE_USERS_TYPE) \ 69 V(REGEXP_MULTIPLE_CACHE_TYPE) \ 70 V(RELOC_INFO_TYPE) \ 71 V(RETAINED_MAPS_TYPE) \ 72 V(SCRIPT_LIST_TYPE) \ 73 V(SCRIPT_SHARED_FUNCTION_INFOS_TYPE) \ 74 V(SCRIPT_SOURCE_EXTERNAL_ONE_BYTE_TYPE) \ 75 V(SCRIPT_SOURCE_EXTERNAL_TWO_BYTE_TYPE) \ 76 V(SCRIPT_SOURCE_NON_EXTERNAL_ONE_BYTE_TYPE) \ 77 V(SCRIPT_SOURCE_NON_EXTERNAL_TWO_BYTE_TYPE) \ 78 V(SERIALIZED_OBJECTS_TYPE) \ 79 V(SINGLE_CHARACTER_STRING_CACHE_TYPE) \ 80 V(STRING_SPLIT_CACHE_TYPE) \ 81 V(STRING_EXTERNAL_RESOURCE_ONE_BYTE_TYPE) \ 82 V(STRING_EXTERNAL_RESOURCE_TWO_BYTE_TYPE) \ 83 V(SOURCE_POSITION_TABLE_TYPE) \ 84 V(UNCOMPILED_SHARED_FUNCTION_INFO_TYPE) \ 85 V(WEAK_NEW_SPACE_OBJECT_TO_CODE_TYPE) 86 87 namespace v8 { 88 namespace internal { 89 90 class Heap; 91 class Isolate; 92 93 class ObjectStats { 94 public: 95 static const size_t kNoOverAllocation = 0; 96 ObjectStats(Heap * heap)97 explicit ObjectStats(Heap* heap) : heap_(heap) { ClearObjectStats(true); } 98 99 // See description on VIRTUAL_INSTANCE_TYPE_LIST. 100 enum VirtualInstanceType { 101 #define DEFINE_VIRTUAL_INSTANCE_TYPE(type) type, 102 VIRTUAL_INSTANCE_TYPE_LIST(DEFINE_VIRTUAL_INSTANCE_TYPE) 103 #undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE 104 LAST_VIRTUAL_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_TYPE, 105 }; 106 107 // ObjectStats are kept in two arrays, counts and sizes. Related stats are 108 // stored in a contiguous linear buffer. Stats groups are stored one after 109 // another. 110 enum { 111 FIRST_VIRTUAL_TYPE = LAST_TYPE + 1, 112 OBJECT_STATS_COUNT = FIRST_VIRTUAL_TYPE + LAST_VIRTUAL_TYPE + 1, 113 }; 114 115 void ClearObjectStats(bool clear_last_time_stats = false); 116 117 void PrintJSON(const char* key); 118 void Dump(std::stringstream& stream); 119 120 void CheckpointObjectStats(); 121 void RecordObjectStats(InstanceType type, size_t size, 122 size_t over_allocated = kNoOverAllocation); 123 void RecordVirtualObjectStats(VirtualInstanceType type, size_t size, 124 size_t over_allocated); 125 object_count_last_gc(size_t index)126 size_t object_count_last_gc(size_t index) { 127 return object_counts_last_time_[index]; 128 } 129 object_size_last_gc(size_t index)130 size_t object_size_last_gc(size_t index) { 131 return object_sizes_last_time_[index]; 132 } 133 134 Isolate* isolate(); heap()135 Heap* heap() { return heap_; } 136 137 private: 138 static const int kFirstBucketShift = 5; // <32 139 static const int kLastBucketShift = 20; // >=1M 140 static const int kFirstBucket = 1 << kFirstBucketShift; 141 static const int kLastBucket = 1 << kLastBucketShift; 142 static const int kNumberOfBuckets = kLastBucketShift - kFirstBucketShift + 1; 143 static const int kLastValueBucketIndex = kLastBucketShift - kFirstBucketShift; 144 145 void PrintKeyAndId(const char* key, int gc_count); 146 // The following functions are excluded from inline to reduce the overall 147 // binary size of VB. On x64 this save around 80KB. 148 V8_NOINLINE void PrintInstanceTypeJSON(const char* key, int gc_count, 149 const char* name, int index); 150 V8_NOINLINE void DumpInstanceTypeData(std::stringstream& stream, 151 const char* name, int index); 152 153 int HistogramIndexFromSize(size_t size); 154 155 Heap* heap_; 156 // Object counts and used memory by InstanceType. 157 size_t object_counts_[OBJECT_STATS_COUNT]; 158 size_t object_counts_last_time_[OBJECT_STATS_COUNT]; 159 size_t object_sizes_[OBJECT_STATS_COUNT]; 160 size_t object_sizes_last_time_[OBJECT_STATS_COUNT]; 161 // Approximation of overallocated memory by InstanceType. 162 size_t over_allocated_[OBJECT_STATS_COUNT]; 163 // Detailed histograms by InstanceType. 164 size_t size_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets]; 165 size_t over_allocated_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets]; 166 167 size_t tagged_fields_count_; 168 size_t embedder_fields_count_; 169 size_t inobject_smi_fields_count_; 170 size_t boxed_double_fields_count_; 171 size_t string_data_count_; 172 size_t raw_fields_count_; 173 174 friend class ObjectStatsCollectorImpl; 175 }; 176 177 class ObjectStatsCollector { 178 public: ObjectStatsCollector(Heap * heap,ObjectStats * live,ObjectStats * dead)179 ObjectStatsCollector(Heap* heap, ObjectStats* live, ObjectStats* dead) 180 : heap_(heap), live_(live), dead_(dead) { 181 DCHECK_NOT_NULL(heap_); 182 DCHECK_NOT_NULL(live_); 183 DCHECK_NOT_NULL(dead_); 184 } 185 186 // Collects type information of live and dead objects. Requires mark bits to 187 // be present. 188 void Collect(); 189 190 private: 191 Heap* const heap_; 192 ObjectStats* const live_; 193 ObjectStats* const dead_; 194 }; 195 196 } // namespace internal 197 } // namespace v8 198 199 #endif // V8_HEAP_OBJECT_STATS_H_ 200