Chromium Code Reviews| Index: src/profile-generator.cc |
| diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
| index be9c5d7dd77b00b867bce1ed6508a848713f321c..d12eb03d960086074fd2e9921b5f0bf6bc15ef5b 100644 |
| --- a/src/profile-generator.cc |
| +++ b/src/profile-generator.cc |
| @@ -3471,13 +3471,33 @@ HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() { |
| void HeapSnapshotJSONSerializer::SerializeImpl() { |
| + const int node_fields_count = 7; |
| + // type,name,id,self_size,retained_size,dominator,children_index. |
| + |
| + List<HeapEntry*>& nodes = *(snapshot_->entries()); |
|
yurys
2012/04/11 05:20:05
Consider extracting this loop in a separate method
alexeif
2012/04/11 12:49:57
Done.
|
| + // Root must be the first. |
| + ASSERT(nodes.first() == snapshot_->root()); |
| + // Rewrite node indexes, so they refer to actual array positions. Do this |
| + // only once. |
| + if (nodes[0]->entry_index() == -1) { |
| + // Nodes start from array index 1. |
| + int index = 0; |
| + for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) { |
| + nodes[i]->set_entry_index(index); |
| + } |
| + } |
| + |
| writer_->AddCharacter('{'); |
| writer_->AddString("\"snapshot\":{"); |
| SerializeSnapshot(); |
| if (writer_->aborted()) return; |
| writer_->AddString("},\n"); |
| writer_->AddString("\"nodes\":["); |
| - SerializeNodes(); |
| + SerializeNodes(nodes); |
| + if (writer_->aborted()) return; |
| + writer_->AddString("],\n"); |
| + writer_->AddString("\"edges\":["); |
| + SerializeEdges(nodes); |
| if (writer_->aborted()) return; |
| writer_->AddString("],\n"); |
| writer_->AddString("\"strings\":["); |
| @@ -3524,7 +3544,8 @@ static int itoa(int value, const Vector<char>& buffer, int buffer_pos) { |
| } |
| -void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
| +void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
| + bool first_edge) { |
| // The buffer needs space for 3 ints, 3 commas and \0 |
| static const int kBufferSize = |
| MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT |
| @@ -3534,7 +3555,9 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
| || edge->type() == HeapGraphEdge::kWeak |
| ? edge->index() : GetStringId(edge->name()); |
| int buffer_pos = 0; |
| - buffer[buffer_pos++] = ','; |
| + if (!first_edge) { |
| + buffer[buffer_pos++] = ','; |
| + } |
| buffer_pos = itoa(edge->type(), buffer, buffer_pos); |
| buffer[buffer_pos++] = ','; |
| buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); |
| @@ -3545,14 +3568,28 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
| } |
| -void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
| +void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) { |
| + bool first_edge = true; |
| + for (int i = 0; i < nodes.length(); ++i) { |
| + HeapEntry* entry = nodes[i]; |
| + Vector<HeapGraphEdge> children = entry->children(); |
| + for (int j = 0; j < children.length(); ++j) { |
| + SerializeEdge(&children[j], first_edge); |
| + first_edge = false; |
| + if (writer_->aborted()) return; |
| + } |
| + } |
| +} |
| + |
| + |
| +void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry, |
| + int edges_index) { |
| // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 |
| static const int kBufferSize = |
| 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT |
| + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT |
| + 7 + 1 + 1; |
| EmbeddedVector<char, kBufferSize> buffer; |
| - Vector<HeapGraphEdge> children = entry->children(); |
| int buffer_pos = 0; |
| buffer[buffer_pos++] = '\n'; |
| buffer[buffer_pos++] = ','; |
| @@ -3568,17 +3605,13 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
| buffer[buffer_pos++] = ','; |
| buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); |
| buffer[buffer_pos++] = ','; |
| - buffer_pos = itoa(children.length(), buffer, buffer_pos); |
| + buffer_pos = itoa(edges_index, buffer, buffer_pos); |
| buffer[buffer_pos++] = '\0'; |
| writer_->AddString(buffer.start()); |
| - for (int i = 0; i < children.length(); ++i) { |
| - SerializeEdge(&children[i]); |
| - if (writer_->aborted()) return; |
| - } |
| } |
| -void HeapSnapshotJSONSerializer::SerializeNodes() { |
| +void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) { |
| // The first (zero) item of nodes array is an object describing node |
| // serialization layout. We use a set of macros to improve |
| // readability. |
| @@ -3586,75 +3619,58 @@ void HeapSnapshotJSONSerializer::SerializeNodes() { |
| #define JSON_O(s) "{"s"}" |
| #define JSON_S(s) "\""s"\"" |
| writer_->AddString(JSON_O( |
|
mnaganov (inactive)
2012/04/10 22:28:09
Is this object still the first item of 'nodes' arr
yurys
2012/04/11 05:20:05
I'd rather put the array length at the first item
alexeif
2012/04/11 12:49:57
moved meta info to the snapshot object.
alexeif
2012/04/11 12:49:57
Added node and edges count to the snapshot info.
yurys
2012/04/11 13:07:17
What about the front-end part?
alexeif
2012/04/11 13:10:23
It will follow as soon as we agree on the BE part.
|
| - JSON_S("fields") ":" JSON_A( |
| - JSON_S("type") |
| - "," JSON_S("name") |
| - "," JSON_S("id") |
| - "," JSON_S("self_size") |
| - "," JSON_S("retained_size") |
| - "," JSON_S("dominator") |
| - "," JSON_S("children_count") |
| - "," JSON_S("children")) |
| - "," JSON_S("types") ":" JSON_A( |
| + JSON_S("separate_edges") ":true," |
| + JSON_S("node_fields") ":" JSON_A( |
| + JSON_S("type") "," |
|
mnaganov (inactive)
2012/04/10 22:28:09
Why are you moving commas to the suffix position?
alexeif
2012/04/11 12:49:57
Unless this it the first field. :-)
So in this sen
|
| + JSON_S("name") "," |
| + JSON_S("id") "," |
| + JSON_S("self_size") "," |
| + JSON_S("retained_size") "," |
| + JSON_S("dominator") "," |
| + JSON_S("edges_index")) "," |
| + JSON_S("node_types") ":" JSON_A( |
| + JSON_A( |
| + JSON_S("hidden") "," |
| + JSON_S("array") "," |
| + JSON_S("string") "," |
| + JSON_S("object") "," |
| + JSON_S("code") "," |
| + JSON_S("closure") "," |
| + JSON_S("regexp") "," |
| + JSON_S("number") "," |
| + JSON_S("native") "," |
| + JSON_S("synthetic")) "," |
| + JSON_S("string") "," |
| + JSON_S("number") "," |
| + JSON_S("number") "," |
| + JSON_S("number") "," |
| + JSON_S("number") "," |
| + JSON_S("number")) "," |
| + JSON_S("edge_fields") ":" JSON_A( |
| + JSON_S("type") "," |
| + JSON_S("name_or_index") "," |
| + JSON_S("to_node")) "," |
| + JSON_S("edge_types") ":" JSON_A( |
| JSON_A( |
| - JSON_S("hidden") |
| - "," JSON_S("array") |
| - "," JSON_S("string") |
| - "," JSON_S("object") |
| - "," JSON_S("code") |
| - "," JSON_S("closure") |
| - "," JSON_S("regexp") |
| - "," JSON_S("number") |
| - "," JSON_S("native") |
| - "," JSON_S("synthetic")) |
| - "," JSON_S("string") |
| - "," JSON_S("number") |
| - "," JSON_S("number") |
| - "," JSON_S("number") |
| - "," JSON_S("number") |
| - "," JSON_S("number") |
| - "," JSON_O( |
| - JSON_S("fields") ":" JSON_A( |
| - JSON_S("type") |
| - "," JSON_S("name_or_index") |
| - "," JSON_S("to_node")) |
| - "," JSON_S("types") ":" JSON_A( |
| - JSON_A( |
| - JSON_S("context") |
| - "," JSON_S("element") |
| - "," JSON_S("property") |
| - "," JSON_S("internal") |
| - "," JSON_S("hidden") |
| - "," JSON_S("shortcut") |
| - "," JSON_S("weak")) |
| - "," JSON_S("string_or_number") |
| - "," JSON_S("node")))))); |
| + JSON_S("context") "," |
| + JSON_S("element") "," |
| + JSON_S("property") "," |
| + JSON_S("internal") "," |
| + JSON_S("hidden") "," |
| + JSON_S("shortcut") "," |
| + JSON_S("weak")) "," |
| + JSON_S("string_or_number") "," |
| + JSON_S("node")))); |
| #undef JSON_S |
| #undef JSON_O |
| #undef JSON_A |
| - const int node_fields_count = 7; |
| - // type,name,id,self_size,retained_size,dominator,children_count. |
| const int edge_fields_count = 3; // type,name|index,to_node. |
| - |
| - List<HeapEntry*>& nodes = *(snapshot_->entries()); |
| - // Root must be the first. |
| - ASSERT(nodes.first() == snapshot_->root()); |
| - // Rewrite node indexes, so they refer to actual array positions. Do this |
| - // only once. |
| - if (nodes[0]->entry_index() == -1) { |
| - // Nodes start from array index 1. |
| - int index = 1; |
| - for (int i = 0; i < nodes.length(); ++i) { |
| - HeapEntry* node = nodes[i]; |
| - node->set_entry_index(index); |
| - index += node_fields_count + |
| - node->children().length() * edge_fields_count; |
| - } |
| - } |
| - |
| + int edges_index = 0; |
| for (int i = 0; i < nodes.length(); ++i) { |
| - SerializeNode(nodes[i]); |
| + HeapEntry* entry = nodes[i]; |
| + SerializeNode(entry, edges_index); |
| + edges_index += entry->children().length() * edge_fields_count; |
| if (writer_->aborted()) return; |
| } |
| } |