Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: src/heap/object-stats.cc

Issue 2129173002: [heap] Rework and improve object stats tracing (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix compilation on Windows Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/object-stats.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/heap/object-stats.h" 5 #include "src/heap/object-stats.h"
6 6
7 #include "src/counters.h" 7 #include "src/counters.h"
8 #include "src/heap/heap-inl.h" 8 #include "src/heap/heap-inl.h"
9 #include "src/isolate.h" 9 #include "src/isolate.h"
10 #include "src/utils.h" 10 #include "src/utils.h"
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 static base::LazyMutex object_stats_mutex = LAZY_MUTEX_INITIALIZER; 15 static base::LazyMutex object_stats_mutex = LAZY_MUTEX_INITIALIZER;
16 16
17 17
18 void ObjectStats::ClearObjectStats(bool clear_last_time_stats) { 18 void ObjectStats::ClearObjectStats(bool clear_last_time_stats) {
19 memset(object_counts_, 0, sizeof(object_counts_)); 19 memset(object_counts_, 0, sizeof(object_counts_));
20 memset(object_sizes_, 0, sizeof(object_sizes_)); 20 memset(object_sizes_, 0, sizeof(object_sizes_));
21 memset(over_allocated_, 0, sizeof(over_allocated_));
22 memset(size_histogram_, 0, sizeof(size_histogram_));
23 memset(over_allocated_histogram_, 0, sizeof(over_allocated_histogram_));
21 if (clear_last_time_stats) { 24 if (clear_last_time_stats) {
22 memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_)); 25 memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_));
23 memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_)); 26 memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_));
24 } 27 }
25 } 28 }
26 29
27 30 static void PrintJSONArray(size_t* array, const int len) {
28 void ObjectStats::TraceObjectStat(const char* name, int count, int size, 31 PrintF("[ ");
29 double time) { 32 for (int i = 0; i < len; i++) {
30 int ms_count = heap()->ms_count(); 33 PrintF("%zu", array[i]);
31 PrintIsolate(isolate(), 34 if (i != (len - 1)) PrintF(", ");
32 "heap:%p, time:%f, gc:%d, type:%s, count:%d, size:%d\n", 35 }
33 static_cast<void*>(heap()), time, ms_count, name, count, size); 36 PrintF(" ]");
34 } 37 }
35 38
39 void ObjectStats::PrintJSON(const char* key) {
40 double time = isolate()->time_millis_since_init();
41 int gc_count = heap()->gc_count();
36 42
37 void ObjectStats::TraceObjectStats() { 43 #define PRINT_KEY_AND_ID() \
38 base::LockGuard<base::Mutex> lock_guard(object_stats_mutex.Pointer()); 44 PrintF("\"isolate\": \"%p\", \"id\": %d, \"key\": \"%s\", ", \
39 int index; 45 reinterpret_cast<void*>(isolate()), gc_count, key);
40 int count; 46
41 int size; 47 // gc_descriptor
42 int total_size = 0; 48 PrintF("{ ");
43 double time = isolate()->time_millis_since_init(); 49 PRINT_KEY_AND_ID();
44 #define TRACE_OBJECT_COUNT(name) \ 50 PrintF("\"type\": \"gc_descriptor\", \"time\": %f }\n", time);
45 count = static_cast<int>(object_counts_[name]); \ 51 // bucket_sizes
46 size = static_cast<int>(object_sizes_[name]) / KB; \ 52 PrintF("{ ");
47 total_size += size; \ 53 PRINT_KEY_AND_ID();
48 TraceObjectStat(#name, count, size, time); 54 PrintF("\"type\": \"bucket_sizes\", \"sizes\": [ ");
49 INSTANCE_TYPE_LIST(TRACE_OBJECT_COUNT) 55 for (int i = 0; i < kNumberOfBuckets; i++) {
50 #undef TRACE_OBJECT_COUNT 56 PrintF("%d", 1 << (kFirstBucketShift + i));
51 #define TRACE_OBJECT_COUNT(name) \ 57 if (i != (kNumberOfBuckets - 1)) PrintF(", ");
52 index = FIRST_CODE_KIND_SUB_TYPE + Code::name; \ 58 }
53 count = static_cast<int>(object_counts_[index]); \ 59 PrintF(" ] }\n");
54 size = static_cast<int>(object_sizes_[index]) / KB; \ 60 // instance_type_data
55 TraceObjectStat("*CODE_" #name, count, size, time); 61 #define PRINT_INSTANCE_TYPE_DATA(name, index) \
56 CODE_KIND_LIST(TRACE_OBJECT_COUNT) 62 PrintF("{ "); \
57 #undef TRACE_OBJECT_COUNT 63 PRINT_KEY_AND_ID(); \
58 #define TRACE_OBJECT_COUNT(name) \ 64 PrintF("\"type\": \"instance_type_data\", "); \
59 index = FIRST_FIXED_ARRAY_SUB_TYPE + name; \ 65 PrintF("\"instance_type\": %d, ", index); \
60 count = static_cast<int>(object_counts_[index]); \ 66 PrintF("\"instance_type_name\": \"%s\", ", name); \
61 size = static_cast<int>(object_sizes_[index]) / KB; \ 67 PrintF("\"overall\": %zu, ", object_sizes_[index]); \
62 TraceObjectStat("*FIXED_ARRAY_" #name, count, size, time); 68 PrintF("\"count\": %zu, ", object_counts_[index]); \
63 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(TRACE_OBJECT_COUNT) 69 PrintF("\"over_allocated\": %zu, ", over_allocated_[index]); \
64 #undef TRACE_OBJECT_COUNT 70 PrintF("\"histogram\": "); \
65 #define TRACE_OBJECT_COUNT(name) \ 71 PrintJSONArray(size_histogram_[index], kNumberOfBuckets); \
66 index = \ 72 PrintF(","); \
67 FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - Code::kFirstCodeAge; \ 73 PrintF("\"over_allocated_histogram\": "); \
68 count = static_cast<int>(object_counts_[index]); \ 74 PrintJSONArray(over_allocated_histogram_[index], kNumberOfBuckets); \
69 size = static_cast<int>(object_sizes_[index]) / KB; \ 75 PrintF(" }\n");
70 TraceObjectStat("*CODE_AGE_" #name, count, size, time); 76
71 CODE_AGE_LIST_COMPLETE(TRACE_OBJECT_COUNT) 77 #define INSTANCE_TYPE_WRAPPER(name) PRINT_INSTANCE_TYPE_DATA(#name, name)
72 #undef TRACE_OBJECT_COUNT 78 #define CODE_KIND_WRAPPER(name) \
79 PRINT_INSTANCE_TYPE_DATA("*CODE_" #name, \
80 FIRST_CODE_KIND_SUB_TYPE + Code::name)
81 #define FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER(name) \
82 PRINT_INSTANCE_TYPE_DATA("*FIXED_ARRAY_" #name, \
83 FIRST_FIXED_ARRAY_SUB_TYPE + name)
84 #define CODE_AGE_WRAPPER(name) \
85 PRINT_INSTANCE_TYPE_DATA( \
86 "*CODE_AGE_" #name, \
87 FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - Code::kFirstCodeAge)
88
89 INSTANCE_TYPE_LIST(INSTANCE_TYPE_WRAPPER)
90 CODE_KIND_LIST(CODE_KIND_WRAPPER)
91 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER)
92 CODE_AGE_LIST_COMPLETE(CODE_AGE_WRAPPER)
93
94 #undef INSTANCE_TYPE_WRAPPER
95 #undef CODE_KIND_WRAPPER
96 #undef FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER
97 #undef CODE_AGE_WRAPPER
98 #undef PRINT_INSTANCE_TYPE_DATA
73 } 99 }
74 100
75
76 void ObjectStats::CheckpointObjectStats() { 101 void ObjectStats::CheckpointObjectStats() {
77 base::LockGuard<base::Mutex> lock_guard(object_stats_mutex.Pointer()); 102 base::LockGuard<base::Mutex> lock_guard(object_stats_mutex.Pointer());
78 Counters* counters = isolate()->counters(); 103 Counters* counters = isolate()->counters();
79 #define ADJUST_LAST_TIME_OBJECT_COUNT(name) \ 104 #define ADJUST_LAST_TIME_OBJECT_COUNT(name) \
80 counters->count_of_##name()->Increment( \ 105 counters->count_of_##name()->Increment( \
81 static_cast<int>(object_counts_[name])); \ 106 static_cast<int>(object_counts_[name])); \
82 counters->count_of_##name()->Decrement( \ 107 counters->count_of_##name()->Decrement( \
83 static_cast<int>(object_counts_last_time_[name])); \ 108 static_cast<int>(object_counts_last_time_[name])); \
84 counters->size_of_##name()->Increment( \ 109 counters->size_of_##name()->Increment( \
85 static_cast<int>(object_sizes_[name])); \ 110 static_cast<int>(object_sizes_[name])); \
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 #undef ADJUST_LAST_TIME_OBJECT_COUNT 152 #undef ADJUST_LAST_TIME_OBJECT_COUNT
128 153
129 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); 154 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
130 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); 155 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
131 ClearObjectStats(); 156 ClearObjectStats();
132 } 157 }
133 158
134 159
135 Isolate* ObjectStats::isolate() { return heap()->isolate(); } 160 Isolate* ObjectStats::isolate() { return heap()->isolate(); }
136 161
137 void ObjectStatsCollector::CountFixedArray( 162 void ObjectStatsCollector::CollectStatistics(ObjectStats* stats,
138 FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, 163 HeapObject* obj) {
139 FixedArraySubInstanceType dictionary_type) { 164 Map* map = obj->map();
140 Heap* heap = fixed_array->map()->GetHeap(); 165 Heap* heap = obj->GetHeap();
141 if (fixed_array->map() != heap->fixed_cow_array_map() && 166
142 fixed_array->map() != heap->fixed_double_array_map() && 167 // Record for the InstanceType.
143 fixed_array != heap->empty_fixed_array()) { 168 int object_size = obj->Size();
144 if (fixed_array->IsDictionary()) { 169 stats->RecordObjectStats(map->instance_type(), object_size);
145 heap->object_stats_->RecordFixedArraySubTypeStats(dictionary_type, 170
146 fixed_array->Size()); 171 // Record specific sub types where possible.
172 if (obj->IsMap()) {
173 RecordMapDetails(stats, heap, obj);
174 }
175 if (obj->IsCode()) {
176 RecordCodeDetails(stats, heap, obj);
177 }
178 if (obj->IsSharedFunctionInfo()) {
179 RecordSharedFunctionInfoDetails(stats, heap, obj);
180 }
181 if (obj->IsFixedArray()) {
182 RecordFixedArrayDetails(stats, heap, obj);
183 }
184 if (obj->IsJSObject()) {
185 RecordJSObjectDetails(stats, heap, JSObject::cast(obj));
186 }
187 if (obj->IsJSWeakCollection()) {
188 RecordJSWeakCollectionDetails(stats, heap, JSWeakCollection::cast(obj));
189 }
190 }
191
192 static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
193 return array->map() != heap->fixed_cow_array_map() &&
194 array->map() != heap->fixed_double_array_map() &&
195 array != heap->empty_fixed_array();
196 }
197
198 void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
199 JSObject* object) {
200 DCHECK(object->IsJSObject());
201
202 size_t overhead = 0;
203 FixedArrayBase* elements = object->elements();
204 if (CanRecordFixedArray(heap, elements)) {
205 if (elements->IsDictionary()) {
206 SeededNumberDictionary* dict = object->element_dictionary();
207 int used = dict->NumberOfElements() * SeededNumberDictionary::kEntrySize;
208 CHECK_GE(elements->Size(), used);
209 overhead = elements->Size() - used;
210 stats->RecordFixedArraySubTypeStats(DICTIONARY_ELEMENTS_SUB_TYPE,
211 elements->Size(), overhead);
147 } else { 212 } else {
148 heap->object_stats_->RecordFixedArraySubTypeStats(fast_type, 213 if (IsFastHoleyElementsKind(object->GetElementsKind())) {
149 fixed_array->Size()); 214 int used = object->GetFastElementsUsage() * kPointerSize;
150 } 215 if (object->GetElementsKind() == FAST_HOLEY_DOUBLE_ELEMENTS) used *= 2;
151 } 216 CHECK_GE(elements->Size(), used);
152 } 217 overhead = elements->Size() - used;
153 218 }
154 void ObjectStatsCollector::CollectStatistics(StaticVisitorBase::VisitorId id, 219 stats->RecordFixedArraySubTypeStats(FAST_ELEMENTS_SUB_TYPE,
155 Map* map, HeapObject* obj) { 220 elements->Size(), overhead);
156 // Record any type specific statistics here. 221 }
157 switch (id) { 222 }
158 case StaticVisitorBase::kVisitMap: 223
159 RecordMapStats(map, obj); 224 overhead = 0;
160 break; 225 FixedArrayBase* properties = object->properties();
161 case StaticVisitorBase::kVisitCode: 226 if (CanRecordFixedArray(heap, properties)) {
162 RecordCodeStats(map, obj); 227 if (properties->IsDictionary()) {
163 break; 228 NameDictionary* dict = object->property_dictionary();
164 case StaticVisitorBase::kVisitSharedFunctionInfo: 229 int used = dict->NumberOfElements() * NameDictionary::kEntrySize;
165 RecordSharedFunctionInfoStats(map, obj); 230 CHECK_GE(properties->Size(), used);
166 break; 231 overhead = properties->Size() - used;
167 case StaticVisitorBase::kVisitFixedArray: 232 stats->RecordFixedArraySubTypeStats(DICTIONARY_PROPERTIES_SUB_TYPE,
168 RecordFixedArrayStats(map, obj); 233 properties->Size(), overhead);
169 break; 234 } else {
170 default: 235 stats->RecordFixedArraySubTypeStats(FAST_PROPERTIES_SUB_TYPE,
171 break; 236 properties->Size(), overhead);
172 } 237 }
173 238 }
174 Heap* heap = map->GetHeap(); 239 }
175 int object_size = obj->Size(); 240
176 heap->object_stats_->RecordObjectStats(map->instance_type(), object_size); 241 void ObjectStatsCollector::RecordJSWeakCollectionDetails(
177 } 242 ObjectStats* stats, Heap* heap, JSWeakCollection* obj) {
178 243 if (obj->table()->IsHashTable()) {
179 void ObjectStatsCollector::CollectFixedArrayStatistics(HeapObject* obj) { 244 ObjectHashTable* table = ObjectHashTable::cast(obj->table());
180 if (obj->IsJSObject()) { 245 int used = table->NumberOfElements() * ObjectHashTable::kEntrySize;
181 JSObject* object = JSObject::cast(obj); 246 size_t overhead = table->Size() - used;
182 CountFixedArray(object->elements(), DICTIONARY_ELEMENTS_SUB_TYPE, 247 stats->RecordFixedArraySubTypeStats(WEAK_COLLECTION_SUB_TYPE, table->Size(),
183 FAST_ELEMENTS_SUB_TYPE); 248 overhead);
184 CountFixedArray(object->properties(), DICTIONARY_PROPERTIES_SUB_TYPE, 249 }
185 FAST_PROPERTIES_SUB_TYPE); 250 }
186 } 251
187 } 252 void ObjectStatsCollector::RecordMapDetails(ObjectStats* stats, Heap* heap,
188 253 HeapObject* obj) {
189 void ObjectStatsCollector::RecordMapStats(Map* map, HeapObject* obj) {
190 Heap* heap = map->GetHeap();
191 Map* map_obj = Map::cast(obj); 254 Map* map_obj = Map::cast(obj);
192 DCHECK(map->instance_type() == MAP_TYPE); 255 DCHECK(obj->map()->instance_type() == MAP_TYPE);
193 DescriptorArray* array = map_obj->instance_descriptors(); 256 DescriptorArray* array = map_obj->instance_descriptors();
194 if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) { 257 if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) {
195 int fixed_array_size = array->Size(); 258 int fixed_array_size = array->Size();
196 heap->object_stats_->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, 259 stats->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE,
197 fixed_array_size); 260 fixed_array_size, 0);
198 } 261 if (array->HasEnumCache()) {
262 stats->RecordFixedArraySubTypeStats(ENUM_CACHE_SUB_TYPE,
263 array->GetEnumCache()->Size(), 0);
264 }
265 if (array->HasEnumIndicesCache()) {
266 stats->RecordFixedArraySubTypeStats(
267 ENUM_INDICES_CACHE_SUB_TYPE, array->GetEnumIndicesCache()->Size(), 0);
268 }
269 }
270
199 if (map_obj->has_code_cache()) { 271 if (map_obj->has_code_cache()) {
200 FixedArray* cache = map_obj->code_cache(); 272 FixedArray* cache = map_obj->code_cache();
201 heap->object_stats_->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, 273 stats->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, cache->Size(),
202 cache->Size()); 274 0);
203 } 275 }
204 } 276 }
205 277
206 void ObjectStatsCollector::RecordCodeStats(Map* map, HeapObject* obj) { 278 void ObjectStatsCollector::RecordCodeDetails(ObjectStats* stats, Heap* heap,
207 Heap* heap = map->GetHeap(); 279 HeapObject* obj) {
208 int object_size = obj->Size(); 280 int object_size = obj->Size();
209 DCHECK(map->instance_type() == CODE_TYPE); 281 DCHECK(obj->map()->instance_type() == CODE_TYPE);
210 Code* code_obj = Code::cast(obj); 282 Code* code_obj = Code::cast(obj);
211 heap->object_stats_->RecordCodeSubTypeStats(code_obj->kind(), 283 stats->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetAge(),
212 code_obj->GetAge(), object_size); 284 object_size);
213 } 285 Code* code = Code::cast(obj);
214 286 if (code->deoptimization_data() != heap->empty_fixed_array()) {
215 void ObjectStatsCollector::RecordSharedFunctionInfoStats(Map* map, 287 stats->RecordFixedArraySubTypeStats(DEOPTIMIZATION_DATA_SUB_TYPE,
216 HeapObject* obj) { 288 code->deoptimization_data()->Size(), 0);
217 Heap* heap = map->GetHeap(); 289 }
290 FixedArrayBase* reloc_info =
291 reinterpret_cast<FixedArrayBase*>(code->unchecked_relocation_info());
292 if (reloc_info != heap->empty_fixed_array()) {
293 stats->RecordFixedArraySubTypeStats(RELOC_INFO_SUB_TYPE,
294 code->relocation_info()->Size(), 0);
295 }
296 FixedArrayBase* source_pos_table =
297 reinterpret_cast<FixedArrayBase*>(code->source_position_table());
298 if (source_pos_table != heap->empty_fixed_array()) {
299 stats->RecordFixedArraySubTypeStats(SOURCE_POS_SUB_TYPE,
300 source_pos_table->Size(), 0);
301 }
302 }
303
304 void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats,
305 Heap* heap,
306 HeapObject* obj) {
218 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); 307 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
219 if (sfi->scope_info() != heap->empty_fixed_array()) { 308 if (sfi->scope_info() != heap->empty_fixed_array()) {
220 heap->object_stats_->RecordFixedArraySubTypeStats( 309 stats->RecordFixedArraySubTypeStats(SCOPE_INFO_SUB_TYPE,
221 SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size()); 310 sfi->scope_info()->Size(), 0);
222 } 311 }
223 } 312 if (sfi->feedback_metadata() != heap->empty_fixed_array()) {
224 313 stats->RecordFixedArraySubTypeStats(TYPE_FEEDBACK_METADATA_SUB_TYPE,
225 void ObjectStatsCollector::RecordFixedArrayStats(Map* map, HeapObject* obj) { 314 sfi->feedback_metadata()->Size(), 0);
226 Heap* heap = map->GetHeap(); 315 }
316 if (!sfi->OptimizedCodeMapIsCleared()) {
317 FixedArray* optimized_code_map = sfi->optimized_code_map();
318 // Optimized code map should be small, so skip accounting.
319 int len = optimized_code_map->length();
320 for (int i = SharedFunctionInfo::kEntriesStart; i < len;
321 i += SharedFunctionInfo::kEntryLength) {
322 Object* slot =
323 optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset);
324 LiteralsArray* literals = nullptr;
325 if (slot->IsWeakCell()) {
326 WeakCell* cell = WeakCell::cast(slot);
327 if (!cell->cleared()) {
328 literals = LiteralsArray::cast(cell->value());
329 }
330 } else {
331 literals = LiteralsArray::cast(slot);
332 }
333 if (literals != nullptr) {
334 stats->RecordFixedArraySubTypeStats(LITERALS_ARRAY_SUB_TYPE,
335 literals->Size(), 0);
336 TypeFeedbackVector* tfv = literals->feedback_vector();
337
338 stats->RecordFixedArraySubTypeStats(TYPE_FEEDBACK_VECTOR_SUB_TYPE,
339 tfv->Size(), 0);
340 }
341 }
342 }
343 }
344
345 void ObjectStatsCollector::RecordFixedArrayDetails(ObjectStats* stats,
346 Heap* heap,
347 HeapObject* obj) {
227 FixedArray* fixed_array = FixedArray::cast(obj); 348 FixedArray* fixed_array = FixedArray::cast(obj);
228 if (fixed_array == heap->string_table()) { 349 if (fixed_array == heap->string_table()) {
229 heap->object_stats_->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE, 350 stats->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE,
230 fixed_array->Size()); 351 fixed_array->Size(), 0);
231 } 352 }
232 } 353 if (fixed_array == heap->weak_object_to_code_table()) {
233 354 WeakHashTable* table = reinterpret_cast<WeakHashTable*>(fixed_array);
234 void MarkCompactObjectStatsVisitor::Initialize( 355 int used = table->NumberOfElements() * WeakHashTable::kEntrySize;
235 VisitorDispatchTable<Callback>* original) { 356 CHECK_GE(fixed_array->Size(), used);
236 // Copy the original visitor table to make call-through possible. After we 357 size_t overhead = fixed_array->Size() - used;
237 // preserved a copy locally, we patch the original table to call us. 358 stats->RecordFixedArraySubTypeStats(OBJECT_TO_CODE_SUB_TYPE,
238 table_.CopyFrom(original); 359 fixed_array->Size(), overhead);
239 #define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>); 360 }
240 VISITOR_ID_LIST(COUNT_FUNCTION) 361 if (obj->IsContext()) {
241 #undef COUNT_FUNCTION 362 stats->RecordFixedArraySubTypeStats(CONTEXT_SUB_TYPE, fixed_array->Size(),
242 } 363 0);
243 364 }
244 template <MarkCompactObjectStatsVisitor::VisitorId id> 365 if (fixed_array->map() == heap->fixed_cow_array_map()) {
245 void MarkCompactObjectStatsVisitor::Visit(Map* map, HeapObject* obj) { 366 stats->RecordFixedArraySubTypeStats(COPY_ON_WRITE_SUB_TYPE,
246 ObjectStatsCollector::CollectStatistics(id, map, obj); 367 fixed_array->Size(), 0);
247 table_.GetVisitorById(id)(map, obj); 368 }
248 ObjectStatsCollector::CollectFixedArrayStatistics(obj);
249 }
250
251 void IncrementalMarkingObjectStatsVisitor::Initialize(
252 VisitorDispatchTable<Callback>* original) {
253 // Copy the original visitor table to make call-through possible. After we
254 // preserved a copy locally, we patch the original table to call us.
255 table_.CopyFrom(original);
256 #define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>);
257 VISITOR_ID_LIST(COUNT_FUNCTION)
258 #undef COUNT_FUNCTION
259 }
260
261 template <IncrementalMarkingObjectStatsVisitor::VisitorId id>
262 void IncrementalMarkingObjectStatsVisitor::Visit(Map* map, HeapObject* obj) {
263 ObjectStatsCollector::CollectStatistics(id, map, obj);
264 table_.GetVisitorById(id)(map, obj);
265 ObjectStatsCollector::CollectFixedArrayStatistics(obj);
266 } 369 }
267 370
268 } // namespace internal 371 } // namespace internal
269 } // namespace v8 372 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/object-stats.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698