OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 #endif // ENABLE_LOGGING_AND_PROFILING | 49 #endif // ENABLE_LOGGING_AND_PROFILING |
50 | 50 |
51 // The HeapProfiler writes data to the log files, which can be postprocessed | 51 // The HeapProfiler writes data to the log files, which can be postprocessed |
52 // to generate .hp files for use by the GHC/Valgrind tool hp2ps. | 52 // to generate .hp files for use by the GHC/Valgrind tool hp2ps. |
53 class HeapProfiler { | 53 class HeapProfiler { |
54 public: | 54 public: |
55 static void Setup(); | 55 static void Setup(); |
56 static void TearDown(); | 56 static void TearDown(); |
57 | 57 |
58 #ifdef ENABLE_LOGGING_AND_PROFILING | 58 #ifdef ENABLE_LOGGING_AND_PROFILING |
59 static HeapSnapshot* TakeSnapshot(const char* name); | 59 static HeapSnapshot* TakeSnapshot(const char* name, int type); |
60 static HeapSnapshot* TakeSnapshot(String* name); | 60 static HeapSnapshot* TakeSnapshot(String* name, int type); |
61 static int GetSnapshotsCount(); | 61 static int GetSnapshotsCount(); |
62 static HeapSnapshot* GetSnapshot(int index); | 62 static HeapSnapshot* GetSnapshot(int index); |
63 static HeapSnapshot* FindSnapshot(unsigned uid); | 63 static HeapSnapshot* FindSnapshot(unsigned uid); |
64 | 64 |
65 static void ObjectMoveEvent(Address from, Address to); | 65 static void ObjectMoveEvent(Address from, Address to); |
66 | 66 |
67 static INLINE(bool is_profiling()) { | 67 static INLINE(bool is_profiling()) { |
68 return singleton_ != NULL && singleton_->snapshots_->is_tracking_objects(); | 68 return singleton_ != NULL && singleton_->snapshots_->is_tracking_objects(); |
69 } | 69 } |
70 | 70 |
71 // Obsolete interface. | 71 // Obsolete interface. |
72 // Write a single heap sample to the log file. | 72 // Write a single heap sample to the log file. |
73 static void WriteSample(); | 73 static void WriteSample(); |
74 | 74 |
75 private: | 75 private: |
76 HeapProfiler(); | 76 HeapProfiler(); |
77 ~HeapProfiler(); | 77 ~HeapProfiler(); |
78 HeapSnapshot* TakeSnapshotImpl(const char* name); | 78 HeapSnapshot* TakeSnapshotImpl(const char* name, int type); |
79 HeapSnapshot* TakeSnapshotImpl(String* name); | 79 HeapSnapshot* TakeSnapshotImpl(String* name, int type); |
80 | |
81 // Obsolete interface. | |
82 // Update the array info with stats from obj. | |
83 static void CollectStats(HeapObject* obj, HistogramInfo* info); | |
84 | 80 |
85 HeapSnapshotsCollection* snapshots_; | 81 HeapSnapshotsCollection* snapshots_; |
86 unsigned next_snapshot_uid_; | 82 unsigned next_snapshot_uid_; |
87 | 83 |
88 static HeapProfiler* singleton_; | 84 static HeapProfiler* singleton_; |
89 #endif // ENABLE_LOGGING_AND_PROFILING | 85 #endif // ENABLE_LOGGING_AND_PROFILING |
90 }; | 86 }; |
91 | 87 |
92 | 88 |
93 #ifdef ENABLE_LOGGING_AND_PROFILING | 89 #ifdef ENABLE_LOGGING_AND_PROFILING |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 (a.instance_ == b.instance_ ? 0 : (a.instance_ < b.instance_ ? -1 : 1)) | 121 (a.instance_ == b.instance_ ? 0 : (a.instance_ < b.instance_ ? -1 : 1)) |
126 : cons_cmp; | 122 : cons_cmp; |
127 } | 123 } |
128 static int Compare(const JSObjectsCluster* a, const JSObjectsCluster* b) { | 124 static int Compare(const JSObjectsCluster* a, const JSObjectsCluster* b) { |
129 return Compare(*a, *b); | 125 return Compare(*a, *b); |
130 } | 126 } |
131 | 127 |
132 bool is_null() const { return constructor_ == NULL; } | 128 bool is_null() const { return constructor_ == NULL; } |
133 bool can_be_coarsed() const { return instance_ != NULL; } | 129 bool can_be_coarsed() const { return instance_ != NULL; } |
134 String* constructor() const { return constructor_; } | 130 String* constructor() const { return constructor_; } |
| 131 Object* instance() const { return instance_; } |
135 | 132 |
| 133 const char* GetSpecialCaseName() const; |
136 void Print(StringStream* accumulator) const; | 134 void Print(StringStream* accumulator) const; |
137 // Allows null clusters to be printed. | 135 // Allows null clusters to be printed. |
138 void DebugPrint(StringStream* accumulator) const; | 136 void DebugPrint(StringStream* accumulator) const; |
139 | 137 |
140 private: | 138 private: |
141 static String* FromSpecialCase(SpecialCase special) { | 139 static String* FromSpecialCase(SpecialCase special) { |
142 // We use symbols that are illegal JS identifiers to identify special cases. | 140 // We use symbols that are illegal JS identifiers to identify special cases. |
143 // Their actual value is irrelevant for us. | 141 // Their actual value is irrelevant for us. |
144 switch (special) { | 142 switch (special) { |
145 case ROOTS: return Heap::result_symbol(); | 143 case ROOTS: return Heap::result_symbol(); |
(...skipping 26 matching lines...) Expand all Loading... |
172 // ConstructorHeapProfile is responsible for gathering and logging | 170 // ConstructorHeapProfile is responsible for gathering and logging |
173 // "constructor profile" of JS objects allocated on heap. | 171 // "constructor profile" of JS objects allocated on heap. |
174 // It is run during garbage collection cycle, thus it doesn't need | 172 // It is run during garbage collection cycle, thus it doesn't need |
175 // to use handles. | 173 // to use handles. |
176 class ConstructorHeapProfile BASE_EMBEDDED { | 174 class ConstructorHeapProfile BASE_EMBEDDED { |
177 public: | 175 public: |
178 ConstructorHeapProfile(); | 176 ConstructorHeapProfile(); |
179 virtual ~ConstructorHeapProfile() {} | 177 virtual ~ConstructorHeapProfile() {} |
180 void CollectStats(HeapObject* obj); | 178 void CollectStats(HeapObject* obj); |
181 void PrintStats(); | 179 void PrintStats(); |
| 180 |
| 181 template<class Callback> |
| 182 void ForEach(Callback* callback) { js_objects_info_tree_.ForEach(callback); } |
182 // Used by ZoneSplayTree::ForEach. Made virtual to allow overriding in tests. | 183 // Used by ZoneSplayTree::ForEach. Made virtual to allow overriding in tests. |
183 virtual void Call(const JSObjectsCluster& cluster, | 184 virtual void Call(const JSObjectsCluster& cluster, |
184 const NumberAndSizeInfo& number_and_size); | 185 const NumberAndSizeInfo& number_and_size); |
185 | 186 |
186 private: | 187 private: |
187 ZoneScope zscope_; | 188 ZoneScope zscope_; |
188 JSObjectsClusterTree js_objects_info_tree_; | 189 JSObjectsClusterTree js_objects_info_tree_; |
189 }; | 190 }; |
190 | 191 |
191 | 192 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 ClusterBackRefs* current_pair_; | 276 ClusterBackRefs* current_pair_; |
276 JSObjectsRetainerTree* current_set_; | 277 JSObjectsRetainerTree* current_set_; |
277 const JSObjectsCluster* self_; | 278 const JSObjectsCluster* self_; |
278 }; | 279 }; |
279 | 280 |
280 | 281 |
281 // RetainerHeapProfile is responsible for gathering and logging | 282 // RetainerHeapProfile is responsible for gathering and logging |
282 // "retainer profile" of JS objects allocated on heap. | 283 // "retainer profile" of JS objects allocated on heap. |
283 // It is run during garbage collection cycle, thus it doesn't need | 284 // It is run during garbage collection cycle, thus it doesn't need |
284 // to use handles. | 285 // to use handles. |
| 286 class RetainerTreeAggregator; |
| 287 |
285 class RetainerHeapProfile BASE_EMBEDDED { | 288 class RetainerHeapProfile BASE_EMBEDDED { |
286 public: | 289 public: |
287 class Printer { | 290 class Printer { |
288 public: | 291 public: |
289 virtual ~Printer() {} | 292 virtual ~Printer() {} |
290 virtual void PrintRetainers(const JSObjectsCluster& cluster, | 293 virtual void PrintRetainers(const JSObjectsCluster& cluster, |
291 const StringStream& retainers) = 0; | 294 const StringStream& retainers) = 0; |
292 }; | 295 }; |
293 | 296 |
294 RetainerHeapProfile(); | 297 RetainerHeapProfile(); |
| 298 ~RetainerHeapProfile(); |
| 299 |
| 300 RetainerTreeAggregator* aggregator() { return aggregator_; } |
| 301 ClustersCoarser* coarser() { return &coarser_; } |
| 302 JSObjectsRetainerTree* retainers_tree() { return &retainers_tree_; } |
| 303 |
295 void CollectStats(HeapObject* obj); | 304 void CollectStats(HeapObject* obj); |
| 305 void CoarseAndAggregate(); |
296 void PrintStats(); | 306 void PrintStats(); |
297 void DebugPrintStats(Printer* printer); | 307 void DebugPrintStats(Printer* printer); |
298 void StoreReference(const JSObjectsCluster& cluster, HeapObject* ref); | 308 void StoreReference(const JSObjectsCluster& cluster, HeapObject* ref); |
299 | 309 |
300 private: | 310 private: |
301 ZoneScope zscope_; | 311 ZoneScope zscope_; |
302 JSObjectsRetainerTree retainers_tree_; | 312 JSObjectsRetainerTree retainers_tree_; |
303 ClustersCoarser coarser_; | 313 ClustersCoarser coarser_; |
| 314 RetainerTreeAggregator* aggregator_; |
304 }; | 315 }; |
305 | 316 |
306 | 317 |
| 318 class AggregatedHeapSnapshot { |
| 319 public: |
| 320 AggregatedHeapSnapshot(); |
| 321 ~AggregatedHeapSnapshot(); |
| 322 |
| 323 HistogramInfo* info() { return info_; } |
| 324 ConstructorHeapProfile* js_cons_profile() { return &js_cons_profile_; } |
| 325 RetainerHeapProfile* js_retainer_profile() { return &js_retainer_profile_; } |
| 326 |
| 327 private: |
| 328 HistogramInfo* info_; |
| 329 ConstructorHeapProfile js_cons_profile_; |
| 330 RetainerHeapProfile js_retainer_profile_; |
| 331 }; |
| 332 |
| 333 |
| 334 class HeapEntriesMap; |
| 335 class HeapSnapshot; |
| 336 |
| 337 class AggregatedHeapSnapshotGenerator { |
| 338 public: |
| 339 explicit AggregatedHeapSnapshotGenerator(AggregatedHeapSnapshot* snapshot); |
| 340 void GenerateSnapshot(); |
| 341 void FillHeapSnapshot(HeapSnapshot* snapshot); |
| 342 |
| 343 static const int kAllStringsType = LAST_TYPE + 1; |
| 344 |
| 345 private: |
| 346 void CalculateStringsStats(); |
| 347 void CollectStats(HeapObject* obj); |
| 348 template<class Iterator> |
| 349 void IterateRetainers(HeapEntriesMap* entries_map); |
| 350 |
| 351 AggregatedHeapSnapshot* agg_snapshot_; |
| 352 }; |
| 353 |
| 354 |
307 class ProducerHeapProfile : public AllStatic { | 355 class ProducerHeapProfile : public AllStatic { |
308 public: | 356 public: |
309 static void Setup(); | 357 static void Setup(); |
310 static void RecordJSObjectAllocation(Object* obj) { | 358 static void RecordJSObjectAllocation(Object* obj) { |
311 if (FLAG_log_producers) DoRecordJSObjectAllocation(obj); | 359 if (FLAG_log_producers) DoRecordJSObjectAllocation(obj); |
312 } | 360 } |
313 | 361 |
314 private: | 362 private: |
315 static void DoRecordJSObjectAllocation(Object* obj); | 363 static void DoRecordJSObjectAllocation(Object* obj); |
316 static bool can_log_; | 364 static bool can_log_; |
317 }; | 365 }; |
318 | 366 |
319 #endif // ENABLE_LOGGING_AND_PROFILING | 367 #endif // ENABLE_LOGGING_AND_PROFILING |
320 | 368 |
321 } } // namespace v8::internal | 369 } } // namespace v8::internal |
322 | 370 |
323 #endif // V8_HEAP_PROFILER_H_ | 371 #endif // V8_HEAP_PROFILER_H_ |
OLD | NEW |