Chromium Code Reviews| 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 |