OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3464 (snapshot_->raw_entries_size() + MB - 1) / MB); | 3464 (snapshot_->raw_entries_size() + MB - 1) / MB); |
3465 HeapEntry* message = result->AddEntry( | 3465 HeapEntry* message = result->AddEntry( |
3466 HeapEntry::kString, text, 0, 4, 0, 0); | 3466 HeapEntry::kString, text, 0, 4, 0, 0); |
3467 root->SetUnidirElementReference(0, 1, message); | 3467 root->SetUnidirElementReference(0, 1, message); |
3468 result->SetDominatorsToSelf(); | 3468 result->SetDominatorsToSelf(); |
3469 return result; | 3469 return result; |
3470 } | 3470 } |
3471 | 3471 |
3472 | 3472 |
3473 void HeapSnapshotJSONSerializer::SerializeImpl() { | 3473 void HeapSnapshotJSONSerializer::SerializeImpl() { |
3474 const int node_fields_count = 7; | |
3475 // type,name,id,self_size,retained_size,dominator,children_index. | |
3476 | |
3477 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.
| |
3478 // Root must be the first. | |
3479 ASSERT(nodes.first() == snapshot_->root()); | |
3480 // Rewrite node indexes, so they refer to actual array positions. Do this | |
3481 // only once. | |
3482 if (nodes[0]->entry_index() == -1) { | |
3483 // Nodes start from array index 1. | |
3484 int index = 0; | |
3485 for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) { | |
3486 nodes[i]->set_entry_index(index); | |
3487 } | |
3488 } | |
3489 | |
3474 writer_->AddCharacter('{'); | 3490 writer_->AddCharacter('{'); |
3475 writer_->AddString("\"snapshot\":{"); | 3491 writer_->AddString("\"snapshot\":{"); |
3476 SerializeSnapshot(); | 3492 SerializeSnapshot(); |
3477 if (writer_->aborted()) return; | 3493 if (writer_->aborted()) return; |
3478 writer_->AddString("},\n"); | 3494 writer_->AddString("},\n"); |
3479 writer_->AddString("\"nodes\":["); | 3495 writer_->AddString("\"nodes\":["); |
3480 SerializeNodes(); | 3496 SerializeNodes(nodes); |
3497 if (writer_->aborted()) return; | |
3498 writer_->AddString("],\n"); | |
3499 writer_->AddString("\"edges\":["); | |
3500 SerializeEdges(nodes); | |
3481 if (writer_->aborted()) return; | 3501 if (writer_->aborted()) return; |
3482 writer_->AddString("],\n"); | 3502 writer_->AddString("],\n"); |
3483 writer_->AddString("\"strings\":["); | 3503 writer_->AddString("\"strings\":["); |
3484 SerializeStrings(); | 3504 SerializeStrings(); |
3485 if (writer_->aborted()) return; | 3505 if (writer_->aborted()) return; |
3486 writer_->AddCharacter(']'); | 3506 writer_->AddCharacter(']'); |
3487 writer_->AddCharacter('}'); | 3507 writer_->AddCharacter('}'); |
3488 writer_->Finalize(); | 3508 writer_->Finalize(); |
3489 } | 3509 } |
3490 | 3510 |
(...skipping 26 matching lines...) Expand all Loading... | |
3517 int result = buffer_pos; | 3537 int result = buffer_pos; |
3518 do { | 3538 do { |
3519 int last_digit = value % 10; | 3539 int last_digit = value % 10; |
3520 buffer[--buffer_pos] = '0' + last_digit; | 3540 buffer[--buffer_pos] = '0' + last_digit; |
3521 value /= 10; | 3541 value /= 10; |
3522 } while (value); | 3542 } while (value); |
3523 return result; | 3543 return result; |
3524 } | 3544 } |
3525 | 3545 |
3526 | 3546 |
3527 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { | 3547 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
3548 bool first_edge) { | |
3528 // The buffer needs space for 3 ints, 3 commas and \0 | 3549 // The buffer needs space for 3 ints, 3 commas and \0 |
3529 static const int kBufferSize = | 3550 static const int kBufferSize = |
3530 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT | 3551 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT |
3531 EmbeddedVector<char, kBufferSize> buffer; | 3552 EmbeddedVector<char, kBufferSize> buffer; |
3532 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement | 3553 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement |
3533 || edge->type() == HeapGraphEdge::kHidden | 3554 || edge->type() == HeapGraphEdge::kHidden |
3534 || edge->type() == HeapGraphEdge::kWeak | 3555 || edge->type() == HeapGraphEdge::kWeak |
3535 ? edge->index() : GetStringId(edge->name()); | 3556 ? edge->index() : GetStringId(edge->name()); |
3536 int buffer_pos = 0; | 3557 int buffer_pos = 0; |
3537 buffer[buffer_pos++] = ','; | 3558 if (!first_edge) { |
3559 buffer[buffer_pos++] = ','; | |
3560 } | |
3538 buffer_pos = itoa(edge->type(), buffer, buffer_pos); | 3561 buffer_pos = itoa(edge->type(), buffer, buffer_pos); |
3539 buffer[buffer_pos++] = ','; | 3562 buffer[buffer_pos++] = ','; |
3540 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); | 3563 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); |
3541 buffer[buffer_pos++] = ','; | 3564 buffer[buffer_pos++] = ','; |
3542 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); | 3565 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); |
3543 buffer[buffer_pos++] = '\0'; | 3566 buffer[buffer_pos++] = '\0'; |
3544 writer_->AddString(buffer.start()); | 3567 writer_->AddString(buffer.start()); |
3545 } | 3568 } |
3546 | 3569 |
3547 | 3570 |
3548 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 3571 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) { |
3572 bool first_edge = true; | |
3573 for (int i = 0; i < nodes.length(); ++i) { | |
3574 HeapEntry* entry = nodes[i]; | |
3575 Vector<HeapGraphEdge> children = entry->children(); | |
3576 for (int j = 0; j < children.length(); ++j) { | |
3577 SerializeEdge(&children[j], first_edge); | |
3578 first_edge = false; | |
3579 if (writer_->aborted()) return; | |
3580 } | |
3581 } | |
3582 } | |
3583 | |
3584 | |
3585 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry, | |
3586 int edges_index) { | |
3549 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 | 3587 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 |
3550 static const int kBufferSize = | 3588 static const int kBufferSize = |
3551 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT | 3589 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT |
3552 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT | 3590 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT |
3553 + 7 + 1 + 1; | 3591 + 7 + 1 + 1; |
3554 EmbeddedVector<char, kBufferSize> buffer; | 3592 EmbeddedVector<char, kBufferSize> buffer; |
3555 Vector<HeapGraphEdge> children = entry->children(); | |
3556 int buffer_pos = 0; | 3593 int buffer_pos = 0; |
3557 buffer[buffer_pos++] = '\n'; | 3594 buffer[buffer_pos++] = '\n'; |
3558 buffer[buffer_pos++] = ','; | 3595 buffer[buffer_pos++] = ','; |
3559 buffer_pos = itoa(entry->type(), buffer, buffer_pos); | 3596 buffer_pos = itoa(entry->type(), buffer, buffer_pos); |
3560 buffer[buffer_pos++] = ','; | 3597 buffer[buffer_pos++] = ','; |
3561 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); | 3598 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); |
3562 buffer[buffer_pos++] = ','; | 3599 buffer[buffer_pos++] = ','; |
3563 buffer_pos = itoa(entry->id(), buffer, buffer_pos); | 3600 buffer_pos = itoa(entry->id(), buffer, buffer_pos); |
3564 buffer[buffer_pos++] = ','; | 3601 buffer[buffer_pos++] = ','; |
3565 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); | 3602 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); |
3566 buffer[buffer_pos++] = ','; | 3603 buffer[buffer_pos++] = ','; |
3567 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); | 3604 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); |
3568 buffer[buffer_pos++] = ','; | 3605 buffer[buffer_pos++] = ','; |
3569 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); | 3606 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); |
3570 buffer[buffer_pos++] = ','; | 3607 buffer[buffer_pos++] = ','; |
3571 buffer_pos = itoa(children.length(), buffer, buffer_pos); | 3608 buffer_pos = itoa(edges_index, buffer, buffer_pos); |
3572 buffer[buffer_pos++] = '\0'; | 3609 buffer[buffer_pos++] = '\0'; |
3573 writer_->AddString(buffer.start()); | 3610 writer_->AddString(buffer.start()); |
3574 for (int i = 0; i < children.length(); ++i) { | |
3575 SerializeEdge(&children[i]); | |
3576 if (writer_->aborted()) return; | |
3577 } | |
3578 } | 3611 } |
3579 | 3612 |
3580 | 3613 |
3581 void HeapSnapshotJSONSerializer::SerializeNodes() { | 3614 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) { |
3582 // The first (zero) item of nodes array is an object describing node | 3615 // The first (zero) item of nodes array is an object describing node |
3583 // serialization layout. We use a set of macros to improve | 3616 // serialization layout. We use a set of macros to improve |
3584 // readability. | 3617 // readability. |
3585 #define JSON_A(s) "["s"]" | 3618 #define JSON_A(s) "["s"]" |
3586 #define JSON_O(s) "{"s"}" | 3619 #define JSON_O(s) "{"s"}" |
3587 #define JSON_S(s) "\""s"\"" | 3620 #define JSON_S(s) "\""s"\"" |
3588 writer_->AddString(JSON_O( | 3621 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.
| |
3589 JSON_S("fields") ":" JSON_A( | 3622 JSON_S("separate_edges") ":true," |
3590 JSON_S("type") | 3623 JSON_S("node_fields") ":" JSON_A( |
3591 "," JSON_S("name") | 3624 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
| |
3592 "," JSON_S("id") | 3625 JSON_S("name") "," |
3593 "," JSON_S("self_size") | 3626 JSON_S("id") "," |
3594 "," JSON_S("retained_size") | 3627 JSON_S("self_size") "," |
3595 "," JSON_S("dominator") | 3628 JSON_S("retained_size") "," |
3596 "," JSON_S("children_count") | 3629 JSON_S("dominator") "," |
3597 "," JSON_S("children")) | 3630 JSON_S("edges_index")) "," |
3598 "," JSON_S("types") ":" JSON_A( | 3631 JSON_S("node_types") ":" JSON_A( |
3599 JSON_A( | 3632 JSON_A( |
3600 JSON_S("hidden") | 3633 JSON_S("hidden") "," |
3601 "," JSON_S("array") | 3634 JSON_S("array") "," |
3602 "," JSON_S("string") | 3635 JSON_S("string") "," |
3603 "," JSON_S("object") | 3636 JSON_S("object") "," |
3604 "," JSON_S("code") | 3637 JSON_S("code") "," |
3605 "," JSON_S("closure") | 3638 JSON_S("closure") "," |
3606 "," JSON_S("regexp") | 3639 JSON_S("regexp") "," |
3607 "," JSON_S("number") | 3640 JSON_S("number") "," |
3608 "," JSON_S("native") | 3641 JSON_S("native") "," |
3609 "," JSON_S("synthetic")) | 3642 JSON_S("synthetic")) "," |
3610 "," JSON_S("string") | 3643 JSON_S("string") "," |
3611 "," JSON_S("number") | 3644 JSON_S("number") "," |
3612 "," JSON_S("number") | 3645 JSON_S("number") "," |
3613 "," JSON_S("number") | 3646 JSON_S("number") "," |
3614 "," JSON_S("number") | 3647 JSON_S("number") "," |
3615 "," JSON_S("number") | 3648 JSON_S("number")) "," |
3616 "," JSON_O( | 3649 JSON_S("edge_fields") ":" JSON_A( |
3617 JSON_S("fields") ":" JSON_A( | 3650 JSON_S("type") "," |
3618 JSON_S("type") | 3651 JSON_S("name_or_index") "," |
3619 "," JSON_S("name_or_index") | 3652 JSON_S("to_node")) "," |
3620 "," JSON_S("to_node")) | 3653 JSON_S("edge_types") ":" JSON_A( |
3621 "," JSON_S("types") ":" JSON_A( | 3654 JSON_A( |
3622 JSON_A( | 3655 JSON_S("context") "," |
3623 JSON_S("context") | 3656 JSON_S("element") "," |
3624 "," JSON_S("element") | 3657 JSON_S("property") "," |
3625 "," JSON_S("property") | 3658 JSON_S("internal") "," |
3626 "," JSON_S("internal") | 3659 JSON_S("hidden") "," |
3627 "," JSON_S("hidden") | 3660 JSON_S("shortcut") "," |
3628 "," JSON_S("shortcut") | 3661 JSON_S("weak")) "," |
3629 "," JSON_S("weak")) | 3662 JSON_S("string_or_number") "," |
3630 "," JSON_S("string_or_number") | 3663 JSON_S("node")))); |
3631 "," JSON_S("node")))))); | |
3632 #undef JSON_S | 3664 #undef JSON_S |
3633 #undef JSON_O | 3665 #undef JSON_O |
3634 #undef JSON_A | 3666 #undef JSON_A |
3635 | 3667 |
3636 const int node_fields_count = 7; | |
3637 // type,name,id,self_size,retained_size,dominator,children_count. | |
3638 const int edge_fields_count = 3; // type,name|index,to_node. | 3668 const int edge_fields_count = 3; // type,name|index,to_node. |
3639 | 3669 int edges_index = 0; |
3640 List<HeapEntry*>& nodes = *(snapshot_->entries()); | |
3641 // Root must be the first. | |
3642 ASSERT(nodes.first() == snapshot_->root()); | |
3643 // Rewrite node indexes, so they refer to actual array positions. Do this | |
3644 // only once. | |
3645 if (nodes[0]->entry_index() == -1) { | |
3646 // Nodes start from array index 1. | |
3647 int index = 1; | |
3648 for (int i = 0; i < nodes.length(); ++i) { | |
3649 HeapEntry* node = nodes[i]; | |
3650 node->set_entry_index(index); | |
3651 index += node_fields_count + | |
3652 node->children().length() * edge_fields_count; | |
3653 } | |
3654 } | |
3655 | |
3656 for (int i = 0; i < nodes.length(); ++i) { | 3670 for (int i = 0; i < nodes.length(); ++i) { |
3657 SerializeNode(nodes[i]); | 3671 HeapEntry* entry = nodes[i]; |
3672 SerializeNode(entry, edges_index); | |
3673 edges_index += entry->children().length() * edge_fields_count; | |
3658 if (writer_->aborted()) return; | 3674 if (writer_->aborted()) return; |
3659 } | 3675 } |
3660 } | 3676 } |
3661 | 3677 |
3662 | 3678 |
3663 void HeapSnapshotJSONSerializer::SerializeSnapshot() { | 3679 void HeapSnapshotJSONSerializer::SerializeSnapshot() { |
3664 writer_->AddString("\"title\":\""); | 3680 writer_->AddString("\"title\":\""); |
3665 writer_->AddString(snapshot_->title()); | 3681 writer_->AddString(snapshot_->title()); |
3666 writer_->AddString("\""); | 3682 writer_->AddString("\""); |
3667 writer_->AddString(",\"uid\":"); | 3683 writer_->AddString(",\"uid\":"); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3756 | 3772 |
3757 | 3773 |
3758 void HeapSnapshotJSONSerializer::SortHashMap( | 3774 void HeapSnapshotJSONSerializer::SortHashMap( |
3759 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3775 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3760 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3776 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3761 sorted_entries->Add(p); | 3777 sorted_entries->Add(p); |
3762 sorted_entries->Sort(SortUsingEntryValue); | 3778 sorted_entries->Sort(SortUsingEntryValue); |
3763 } | 3779 } |
3764 | 3780 |
3765 } } // namespace v8::internal | 3781 } } // namespace v8::internal |
OLD | NEW |