OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/profiler/heap-snapshot-generator.h" | 5 #include "src/profiler/heap-snapshot-generator.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/objects-body-descriptors.h" | 10 #include "src/objects-body-descriptors.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 snapshot_(snapshot), | 56 snapshot_(snapshot), |
57 name_(name), | 57 name_(name), |
58 id_(id), | 58 id_(id), |
59 trace_node_id_(trace_node_id) { } | 59 trace_node_id_(trace_node_id) { } |
60 | 60 |
61 | 61 |
62 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, | 62 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
63 const char* name, | 63 const char* name, |
64 HeapEntry* entry) { | 64 HeapEntry* entry) { |
65 HeapGraphEdge edge(type, name, this->index(), entry->index()); | 65 HeapGraphEdge edge(type, name, this->index(), entry->index()); |
66 snapshot_->edges().Add(edge); | 66 snapshot_->edges().push_back(edge); |
67 ++children_count_; | 67 ++children_count_; |
68 } | 68 } |
69 | 69 |
70 | 70 |
71 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, | 71 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
72 int index, | 72 int index, |
73 HeapEntry* entry) { | 73 HeapEntry* entry) { |
74 HeapGraphEdge edge(type, index, this->index(), entry->index()); | 74 HeapGraphEdge edge(type, index, this->index(), entry->index()); |
75 snapshot_->edges().Add(edge); | 75 snapshot_->edges().push_back(edge); |
76 ++children_count_; | 76 ++children_count_; |
77 } | 77 } |
78 | 78 |
79 | 79 |
80 void HeapEntry::Print( | 80 void HeapEntry::Print( |
81 const char* prefix, const char* edge_name, int max_depth, int indent) { | 81 const char* prefix, const char* edge_name, int max_depth, int indent) { |
82 STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); | 82 STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); |
83 base::OS::Print("%6" PRIuS " @%6u %*c %s%s: ", self_size(), id(), indent, ' ', | 83 base::OS::Print("%6" PRIuS " @%6u %*c %s%s: ", self_size(), id(), indent, ' ', |
84 prefix, edge_name); | 84 prefix, edge_name); |
85 if (type() != kString) { | 85 if (type() != kString) { |
86 base::OS::Print("%s %.40s\n", TypeAsString(), name_); | 86 base::OS::Print("%s %.40s\n", TypeAsString(), name_); |
87 } else { | 87 } else { |
88 base::OS::Print("\""); | 88 base::OS::Print("\""); |
89 const char* c = name_; | 89 const char* c = name_; |
90 while (*c && (c - name_) <= 40) { | 90 while (*c && (c - name_) <= 40) { |
91 if (*c != '\n') | 91 if (*c != '\n') |
92 base::OS::Print("%c", *c); | 92 base::OS::Print("%c", *c); |
93 else | 93 else |
94 base::OS::Print("\\n"); | 94 base::OS::Print("\\n"); |
95 ++c; | 95 ++c; |
96 } | 96 } |
97 base::OS::Print("\"\n"); | 97 base::OS::Print("\"\n"); |
98 } | 98 } |
99 if (--max_depth == 0) return; | 99 if (--max_depth == 0) return; |
100 Vector<HeapGraphEdge*> ch = children(); | 100 for (auto i = children_begin(); i != children_end(); ++i) { |
101 for (int i = 0; i < ch.length(); ++i) { | 101 HeapGraphEdge& edge = **i; |
102 HeapGraphEdge& edge = *ch[i]; | |
103 const char* edge_prefix = ""; | 102 const char* edge_prefix = ""; |
104 EmbeddedVector<char, 64> index; | 103 EmbeddedVector<char, 64> index; |
105 const char* edge_name = index.start(); | 104 const char* edge_name = index.start(); |
106 switch (edge.type()) { | 105 switch (edge.type()) { |
107 case HeapGraphEdge::kContextVariable: | 106 case HeapGraphEdge::kContextVariable: |
108 edge_prefix = "#"; | 107 edge_prefix = "#"; |
109 edge_name = edge.name(); | 108 edge_name = edge.name(); |
110 break; | 109 break; |
111 case HeapGraphEdge::kElement: | 110 case HeapGraphEdge::kElement: |
112 SNPrintF(index, "%d", edge.index()); | 111 SNPrintF(index, "%d", edge.index()); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 SnapshotObjectId id, | 262 SnapshotObjectId id, |
264 size_t size, | 263 size_t size, |
265 unsigned trace_node_id) { | 264 unsigned trace_node_id) { |
266 HeapEntry entry(this, type, name, id, size, trace_node_id); | 265 HeapEntry entry(this, type, name, id, size, trace_node_id); |
267 entries_.Add(entry); | 266 entries_.Add(entry); |
268 return &entries_.last(); | 267 return &entries_.last(); |
269 } | 268 } |
270 | 269 |
271 | 270 |
272 void HeapSnapshot::FillChildren() { | 271 void HeapSnapshot::FillChildren() { |
273 DCHECK(children().is_empty()); | 272 DCHECK(children().empty()); |
274 children().Allocate(edges().length()); | 273 children().resize(edges().size()); |
275 int children_index = 0; | 274 int children_index = 0; |
276 for (int i = 0; i < entries().length(); ++i) { | 275 for (int i = 0; i < entries().length(); ++i) { |
277 HeapEntry* entry = &entries()[i]; | 276 HeapEntry* entry = &entries()[i]; |
278 children_index = entry->set_children_index(children_index); | 277 children_index = entry->set_children_index(children_index); |
279 } | 278 } |
280 DCHECK(edges().length() == children_index); | 279 DCHECK_EQ(edges().size(), static_cast<size_t>(children_index)); |
281 for (int i = 0; i < edges().length(); ++i) { | 280 for (size_t i = 0; i < edges().size(); ++i) { |
282 HeapGraphEdge* edge = &edges()[i]; | 281 HeapGraphEdge* edge = &edges()[i]; |
283 edge->ReplaceToIndexWithEntry(this); | 282 edge->ReplaceToIndexWithEntry(this); |
284 edge->from()->add_child(edge); | 283 edge->from()->add_child(edge); |
285 } | 284 } |
286 } | 285 } |
287 | 286 |
288 | 287 |
289 class FindEntryById { | 288 class FindEntryById { |
290 public: | 289 public: |
291 explicit FindEntryById(SnapshotObjectId id) : id_(id) { } | 290 explicit FindEntryById(SnapshotObjectId id) : id_(id) { } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 return &sorted_entries_; | 327 return &sorted_entries_; |
329 } | 328 } |
330 | 329 |
331 | 330 |
332 void HeapSnapshot::Print(int max_depth) { | 331 void HeapSnapshot::Print(int max_depth) { |
333 root()->Print("", "", max_depth, 0); | 332 root()->Print("", "", max_depth, 0); |
334 } | 333 } |
335 | 334 |
336 | 335 |
337 size_t HeapSnapshot::RawSnapshotSize() const { | 336 size_t HeapSnapshot::RawSnapshotSize() const { |
338 return | 337 return sizeof(*this) + GetMemoryUsedByList(entries_) + |
339 sizeof(*this) + | 338 edges_.size() * sizeof(decltype(edges_)::value_type) + |
340 GetMemoryUsedByList(entries_) + | 339 children_.size() * sizeof(decltype(children_)::value_type) + |
341 GetMemoryUsedByList(edges_) + | 340 GetMemoryUsedByList(sorted_entries_); |
342 GetMemoryUsedByList(children_) + | |
343 GetMemoryUsedByList(sorted_entries_); | |
344 } | 341 } |
345 | 342 |
346 | 343 |
347 // We split IDs on evens for embedder objects (see | 344 // We split IDs on evens for embedder objects (see |
348 // HeapObjectsMap::GenerateId) and odds for native objects. | 345 // HeapObjectsMap::GenerateId) and odds for native objects. |
349 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; | 346 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; |
350 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = | 347 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = |
351 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; | 348 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; |
352 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = | 349 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = |
353 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; | 350 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; |
(...skipping 2436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2790 buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); | 2787 buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); |
2791 buffer[buffer_pos++] = ','; | 2788 buffer[buffer_pos++] = ','; |
2792 buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); | 2789 buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); |
2793 buffer[buffer_pos++] = '\n'; | 2790 buffer[buffer_pos++] = '\n'; |
2794 buffer[buffer_pos++] = '\0'; | 2791 buffer[buffer_pos++] = '\0'; |
2795 writer_->AddString(buffer.start()); | 2792 writer_->AddString(buffer.start()); |
2796 } | 2793 } |
2797 | 2794 |
2798 | 2795 |
2799 void HeapSnapshotJSONSerializer::SerializeEdges() { | 2796 void HeapSnapshotJSONSerializer::SerializeEdges() { |
2800 List<HeapGraphEdge*>& edges = snapshot_->children(); | 2797 std::deque<HeapGraphEdge*>& edges = snapshot_->children(); |
2801 for (int i = 0; i < edges.length(); ++i) { | 2798 for (size_t i = 0; i < edges.size(); ++i) { |
2802 DCHECK(i == 0 || | 2799 DCHECK(i == 0 || |
2803 edges[i - 1]->from()->index() <= edges[i]->from()->index()); | 2800 edges[i - 1]->from()->index() <= edges[i]->from()->index()); |
2804 SerializeEdge(edges[i], i == 0); | 2801 SerializeEdge(edges[i], i == 0); |
2805 if (writer_->aborted()) return; | 2802 if (writer_->aborted()) return; |
2806 } | 2803 } |
2807 } | 2804 } |
2808 | 2805 |
2809 | 2806 |
2810 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 2807 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
2811 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 | 2808 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2909 JSON_S("children")) "," | 2906 JSON_S("children")) "," |
2910 JSON_S("sample_fields") ":" JSON_A( | 2907 JSON_S("sample_fields") ":" JSON_A( |
2911 JSON_S("timestamp_us") "," | 2908 JSON_S("timestamp_us") "," |
2912 JSON_S("last_assigned_id")))); | 2909 JSON_S("last_assigned_id")))); |
2913 #undef JSON_S | 2910 #undef JSON_S |
2914 #undef JSON_O | 2911 #undef JSON_O |
2915 #undef JSON_A | 2912 #undef JSON_A |
2916 writer_->AddString(",\"node_count\":"); | 2913 writer_->AddString(",\"node_count\":"); |
2917 writer_->AddNumber(snapshot_->entries().length()); | 2914 writer_->AddNumber(snapshot_->entries().length()); |
2918 writer_->AddString(",\"edge_count\":"); | 2915 writer_->AddString(",\"edge_count\":"); |
2919 writer_->AddNumber(snapshot_->edges().length()); | 2916 writer_->AddNumber(static_cast<double>(snapshot_->edges().size())); |
2920 writer_->AddString(",\"trace_function_count\":"); | 2917 writer_->AddString(",\"trace_function_count\":"); |
2921 uint32_t count = 0; | 2918 uint32_t count = 0; |
2922 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); | 2919 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
2923 if (tracker) { | 2920 if (tracker) { |
2924 count = tracker->function_info_list().length(); | 2921 count = tracker->function_info_list().length(); |
2925 } | 2922 } |
2926 writer_->AddNumber(count); | 2923 writer_->AddNumber(count); |
2927 } | 2924 } |
2928 | 2925 |
2929 | 2926 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3114 for (int i = 1; i < sorted_strings.length(); ++i) { | 3111 for (int i = 1; i < sorted_strings.length(); ++i) { |
3115 writer_->AddCharacter(','); | 3112 writer_->AddCharacter(','); |
3116 SerializeString(sorted_strings[i]); | 3113 SerializeString(sorted_strings[i]); |
3117 if (writer_->aborted()) return; | 3114 if (writer_->aborted()) return; |
3118 } | 3115 } |
3119 } | 3116 } |
3120 | 3117 |
3121 | 3118 |
3122 } // namespace internal | 3119 } // namespace internal |
3123 } // namespace v8 | 3120 } // namespace v8 |
OLD | NEW |