Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(554)

Side by Side Diff: src/profile-generator.cc

Issue 10012013: Get rid of HeapEntry to ID map in heap profile serializer (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 957 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 SnapshotObjectId id, 968 SnapshotObjectId id,
969 int self_size, 969 int self_size,
970 int children_count, 970 int children_count,
971 int retainers_count) { 971 int retainers_count) {
972 snapshot_ = snapshot; 972 snapshot_ = snapshot;
973 type_ = type; 973 type_ = type;
974 painted_ = false; 974 painted_ = false;
975 name_ = name; 975 name_ = name;
976 self_size_ = self_size; 976 self_size_ = self_size;
977 retained_size_ = 0; 977 retained_size_ = 0;
978 entry_index_ = -1;
978 children_count_ = children_count; 979 children_count_ = children_count;
979 retainers_count_ = retainers_count; 980 retainers_count_ = retainers_count;
980 dominator_ = NULL; 981 dominator_ = NULL;
981 id_ = id; 982 id_ = id;
982 } 983 }
983 984
984 985
985 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, 986 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
986 int child_index, 987 int child_index,
987 const char* name, 988 const char* name,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 1102
1102 1103
1103 // It is very important to keep objects that form a heap snapshot 1104 // It is very important to keep objects that form a heap snapshot
1104 // as small as possible. 1105 // as small as possible.
1105 namespace { // Avoid littering the global namespace. 1106 namespace { // Avoid littering the global namespace.
1106 1107
1107 template <size_t ptr_size> struct SnapshotSizeConstants; 1108 template <size_t ptr_size> struct SnapshotSizeConstants;
1108 1109
1109 template <> struct SnapshotSizeConstants<4> { 1110 template <> struct SnapshotSizeConstants<4> {
1110 static const int kExpectedHeapGraphEdgeSize = 12; 1111 static const int kExpectedHeapGraphEdgeSize = 12;
1111 static const int kExpectedHeapEntrySize = 32; 1112 static const int kExpectedHeapEntrySize = 36;
1112 static const size_t kMaxSerializableSnapshotRawSize = 256 * MB; 1113 static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
1113 }; 1114 };
1114 1115
1115 template <> struct SnapshotSizeConstants<8> { 1116 template <> struct SnapshotSizeConstants<8> {
1116 static const int kExpectedHeapGraphEdgeSize = 24; 1117 static const int kExpectedHeapGraphEdgeSize = 24;
1117 static const int kExpectedHeapEntrySize = 48; 1118 static const int kExpectedHeapEntrySize = 48;
1118 static const uint64_t kMaxSerializableSnapshotRawSize = 1119 static const uint64_t kMaxSerializableSnapshotRawSize =
1119 static_cast<uint64_t>(6000) * MB; 1120 static_cast<uint64_t>(6000) * MB;
1120 }; 1121 };
1121 1122
1122 } // namespace 1123 } // namespace
1123 1124
1124 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1125 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1125 HeapSnapshot::Type type, 1126 HeapSnapshot::Type type,
1126 const char* title, 1127 const char* title,
1127 unsigned uid) 1128 unsigned uid)
1128 : collection_(collection), 1129 : collection_(collection),
1129 type_(type), 1130 type_(type),
1130 title_(title), 1131 title_(title),
1131 uid_(uid), 1132 uid_(uid),
1132 root_entry_(NULL), 1133 root_entry_(NULL),
1133 gc_roots_entry_(NULL), 1134 gc_roots_entry_(NULL),
1134 natives_root_entry_(NULL), 1135 natives_root_entry_(NULL),
1135 raw_entries_(NULL), 1136 raw_entries_(NULL),
1136 entries_sorted_(false),
1137 max_snapshot_js_object_id_(0) { 1137 max_snapshot_js_object_id_(0) {
1138 STATIC_CHECK( 1138 STATIC_CHECK(
1139 sizeof(HeapGraphEdge) == 1139 sizeof(HeapGraphEdge) ==
1140 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1140 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1141 STATIC_CHECK( 1141 STATIC_CHECK(
1142 sizeof(HeapEntry) == 1142 sizeof(HeapEntry) ==
1143 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1143 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1144 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1144 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1145 gc_subroot_entries_[i] = NULL; 1145 gc_subroot_entries_[i] = NULL;
1146 } 1146 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 } 1178 }
1179 1179
1180 1180
1181 void HeapSnapshot::ClearPaint() { 1181 void HeapSnapshot::ClearPaint() {
1182 entries_.Iterate(HeapEntryClearPaint); 1182 entries_.Iterate(HeapEntryClearPaint);
1183 } 1183 }
1184 1184
1185 1185
1186 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) { 1186 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1187 ASSERT(root_entry_ == NULL); 1187 ASSERT(root_entry_ == NULL);
1188 ASSERT(entries_.is_empty()); // Root entry must be the first one.
1188 return (root_entry_ = AddEntry(HeapEntry::kObject, 1189 return (root_entry_ = AddEntry(HeapEntry::kObject,
1189 "", 1190 "",
1190 HeapObjectsMap::kInternalRootObjectId, 1191 HeapObjectsMap::kInternalRootObjectId,
1191 0, 1192 0,
1192 children_count, 1193 children_count,
1193 0)); 1194 0));
1194 } 1195 }
1195 1196
1196 1197
1197 HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count, 1198 HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 1279
1279 template<class T> 1280 template<class T>
1280 static int SortByIds(const T* entry1_ptr, 1281 static int SortByIds(const T* entry1_ptr,
1281 const T* entry2_ptr) { 1282 const T* entry2_ptr) {
1282 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 1283 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0;
1283 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 1284 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1;
1284 } 1285 }
1285 1286
1286 1287
1287 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 1288 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1288 if (!entries_sorted_) { 1289 if (sorted_entries_.is_empty()) {
1289 entries_.Sort(SortByIds); 1290 sorted_entries_.AddAll(entries_);
1290 entries_sorted_ = true; 1291 sorted_entries_.Sort(SortByIds);
1291 } 1292 }
1292 return &entries_; 1293 return &sorted_entries_;
1293 } 1294 }
1294 1295
1295 1296
1296 void HeapSnapshot::Print(int max_depth) { 1297 void HeapSnapshot::Print(int max_depth) {
1297 root()->Print("", "", max_depth, 0); 1298 root()->Print("", "", max_depth, 0);
1298 } 1299 }
1299 1300
1300 1301
1301 // We split IDs on evens for embedder objects (see 1302 // We split IDs on evens for embedder objects (see
1302 // HeapObjectsMap::GenerateId) and odds for native objects. 1303 // HeapObjectsMap::GenerateId) and odds for native objects.
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 } 1508 }
1508 1509
1509 1510
1510 HeapEntriesMap::~HeapEntriesMap() { 1511 HeapEntriesMap::~HeapEntriesMap() {
1511 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { 1512 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
1512 delete reinterpret_cast<EntryInfo*>(p->value); 1513 delete reinterpret_cast<EntryInfo*>(p->value);
1513 } 1514 }
1514 } 1515 }
1515 1516
1516 1517
1517 void HeapEntriesMap::AllocateEntries() { 1518 void HeapEntriesMap::AllocateHeapEntryForMapEntry(HashMap::Entry* map_entry) {
1518 for (HashMap::Entry* p = entries_.Start(); 1519 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(map_entry->value);
1519 p != NULL;
1520 p = entries_.Next(p)) {
1521 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1522 entry_info->entry = entry_info->allocator->AllocateEntry( 1520 entry_info->entry = entry_info->allocator->AllocateEntry(
1523 p->key, 1521 map_entry->key,
1524 entry_info->children_count, 1522 entry_info->children_count,
1525 entry_info->retainers_count); 1523 entry_info->retainers_count);
1526 ASSERT(entry_info->entry != NULL); 1524 ASSERT(entry_info->entry != NULL);
1527 ASSERT(entry_info->entry != kHeapEntryPlaceholder); 1525 ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1528 entry_info->children_count = 0; 1526 entry_info->children_count = 0;
1529 entry_info->retainers_count = 0; 1527 entry_info->retainers_count = 0;
1530 }
1531 } 1528 }
1532 1529
1533 1530
1531 void HeapEntriesMap::AllocateEntries(HeapThing root_object) {
1532 HashMap::Entry* root_entry =
1533 entries_.Lookup(root_object, Hash(root_object), false);
1534 ASSERT(root_entry != NULL);
1535 // Make sure root entry is allocated first.
1536 AllocateHeapEntryForMapEntry(root_entry);
1537 void* root_entry_value = root_entry->value;
1538 // Remove the root object from map while iterating through other entries.
1539 entries_.Remove(root_object, Hash(root_object));
1540 root_entry = NULL;
1541
1542 for (HashMap::Entry* p = entries_.Start();
1543 p != NULL;
1544 p = entries_.Next(p)) {
1545 AllocateHeapEntryForMapEntry(p);
1546 }
1547
1548 // Insert root entry back.
1549 root_entry = entries_.Lookup(root_object, Hash(root_object), true);
1550 root_entry->value = root_entry_value;
1551 }
1552
1553
1534 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { 1554 HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1535 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); 1555 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1536 if (cache_entry != NULL) { 1556 if (cache_entry != NULL) {
1537 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); 1557 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1538 return entry_info->entry; 1558 return entry_info->entry;
1539 } else { 1559 } else {
1540 return NULL; 1560 return NULL;
1541 } 1561 }
1542 } 1562 }
1543 1563
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 #ifdef DEBUG 3119 #ifdef DEBUG
3100 debug_heap->Verify(); 3120 debug_heap->Verify();
3101 #endif 3121 #endif
3102 3122
3103 // Allocate memory for entries and references. 3123 // Allocate memory for entries and references.
3104 snapshot_->AllocateEntries(entries_.entries_count(), 3124 snapshot_->AllocateEntries(entries_.entries_count(),
3105 entries_.total_children_count(), 3125 entries_.total_children_count(),
3106 entries_.total_retainers_count()); 3126 entries_.total_retainers_count());
3107 3127
3108 // Allocate heap objects to entries hash map. 3128 // Allocate heap objects to entries hash map.
3109 entries_.AllocateEntries(); 3129 entries_.AllocateEntries(V8HeapExplorer::kInternalRootObject);
3110 3130
3111 // Pass 2. Fill references. 3131 // Pass 2. Fill references.
3112 if (!FillReferences()) return false; 3132 if (!FillReferences()) return false;
3113 3133
3114 snapshot_->RememberLastJSObjectId(); 3134 snapshot_->RememberLastJSObjectId();
3115 3135
3116 if (!SetEntriesDominators()) return false; 3136 if (!SetEntriesDominators()) return false;
3117 if (!CalculateRetainedSizes()) return false; 3137 if (!CalculateRetainedSizes()) return false;
3118 3138
3119 progress_counter_ = progress_total_; 3139 progress_counter_ = progress_total_;
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
3410 3430
3411 HeapSnapshot* original_snapshot = NULL; 3431 HeapSnapshot* original_snapshot = NULL;
3412 if (snapshot_->raw_entries_size() >= 3432 if (snapshot_->raw_entries_size() >=
3413 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) { 3433 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) {
3414 // The snapshot is too big. Serialize a fake snapshot. 3434 // The snapshot is too big. Serialize a fake snapshot.
3415 original_snapshot = snapshot_; 3435 original_snapshot = snapshot_;
3416 snapshot_ = CreateFakeSnapshot(); 3436 snapshot_ = CreateFakeSnapshot();
3417 } 3437 }
3418 // Since nodes graph is cyclic, we need the first pass to enumerate 3438 // Since nodes graph is cyclic, we need the first pass to enumerate
3419 // them. Strings can be serialized in one pass. 3439 // them. Strings can be serialized in one pass.
3420 EnumerateNodes();
3421 SerializeImpl(); 3440 SerializeImpl();
3422 3441
3423 delete writer_; 3442 delete writer_;
3424 writer_ = NULL; 3443 writer_ = NULL;
3425 3444
3426 if (original_snapshot != NULL) { 3445 if (original_snapshot != NULL) {
3427 delete snapshot_; 3446 delete snapshot_;
3428 snapshot_ = original_snapshot; 3447 snapshot_ = original_snapshot;
3429 } 3448 }
3430 } 3449 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3463 writer_->AddString("],\n"); 3482 writer_->AddString("],\n");
3464 writer_->AddString("\"strings\":["); 3483 writer_->AddString("\"strings\":[");
3465 SerializeStrings(); 3484 SerializeStrings();
3466 if (writer_->aborted()) return; 3485 if (writer_->aborted()) return;
3467 writer_->AddCharacter(']'); 3486 writer_->AddCharacter(']');
3468 writer_->AddCharacter('}'); 3487 writer_->AddCharacter('}');
3469 writer_->Finalize(); 3488 writer_->Finalize();
3470 } 3489 }
3471 3490
3472 3491
3473 class HeapSnapshotJSONSerializerEnumerator {
3474 public:
3475 explicit HeapSnapshotJSONSerializerEnumerator(HeapSnapshotJSONSerializer* s)
3476 : s_(s) {
3477 }
3478 void Apply(HeapEntry** entry) {
3479 s_->GetNodeId(*entry);
3480 }
3481 private:
3482 HeapSnapshotJSONSerializer* s_;
3483 };
3484
3485 void HeapSnapshotJSONSerializer::EnumerateNodes() {
3486 GetNodeId(snapshot_->root()); // Make sure root gets the first id.
3487 HeapSnapshotJSONSerializerEnumerator iter(this);
3488 snapshot_->IterateEntries(&iter);
3489 }
3490
3491
3492 int HeapSnapshotJSONSerializer::GetNodeId(HeapEntry* entry) {
3493 HashMap::Entry* cache_entry = nodes_.Lookup(entry, ObjectHash(entry), true);
3494 if (cache_entry->value == NULL) {
3495 cache_entry->value = reinterpret_cast<void*>(next_node_id_++);
3496 }
3497 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
3498 }
3499
3500
3501 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { 3492 int HeapSnapshotJSONSerializer::GetStringId(const char* s) {
3502 HashMap::Entry* cache_entry = strings_.Lookup( 3493 HashMap::Entry* cache_entry = strings_.Lookup(
3503 const_cast<char*>(s), ObjectHash(s), true); 3494 const_cast<char*>(s), ObjectHash(s), true);
3504 if (cache_entry->value == NULL) { 3495 if (cache_entry->value == NULL) {
3505 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 3496 cache_entry->value = reinterpret_cast<void*>(next_string_id_++);
3506 } 3497 }
3507 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 3498 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
3508 } 3499 }
3509 3500
3510 3501
(...skipping 30 matching lines...) Expand all
3541 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 3532 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
3542 || edge->type() == HeapGraphEdge::kHidden 3533 || edge->type() == HeapGraphEdge::kHidden
3543 || edge->type() == HeapGraphEdge::kWeak 3534 || edge->type() == HeapGraphEdge::kWeak
3544 ? edge->index() : GetStringId(edge->name()); 3535 ? edge->index() : GetStringId(edge->name());
3545 int buffer_pos = 0; 3536 int buffer_pos = 0;
3546 buffer[buffer_pos++] = ','; 3537 buffer[buffer_pos++] = ',';
3547 buffer_pos = itoa(edge->type(), buffer, buffer_pos); 3538 buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3548 buffer[buffer_pos++] = ','; 3539 buffer[buffer_pos++] = ',';
3549 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); 3540 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3550 buffer[buffer_pos++] = ','; 3541 buffer[buffer_pos++] = ',';
3551 buffer_pos = itoa(GetNodeId(edge->to()), buffer, buffer_pos); 3542 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
3552 buffer[buffer_pos++] = '\0'; 3543 buffer[buffer_pos++] = '\0';
3553 writer_->AddString(buffer.start()); 3544 writer_->AddString(buffer.start());
3554 } 3545 }
3555 3546
3556 3547
3557 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 3548 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
3558 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 3549 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3559 static const int kBufferSize = 3550 static const int kBufferSize =
3560 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT 3551 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3561 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT 3552 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3562 + 7 + 1 + 1; 3553 + 7 + 1 + 1;
3563 EmbeddedVector<char, kBufferSize> buffer; 3554 EmbeddedVector<char, kBufferSize> buffer;
3564 Vector<HeapGraphEdge> children = entry->children(); 3555 Vector<HeapGraphEdge> children = entry->children();
3565 int buffer_pos = 0; 3556 int buffer_pos = 0;
3566 buffer[buffer_pos++] = '\n'; 3557 buffer[buffer_pos++] = '\n';
3567 buffer[buffer_pos++] = ','; 3558 buffer[buffer_pos++] = ',';
3568 buffer_pos = itoa(entry->type(), buffer, buffer_pos); 3559 buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3569 buffer[buffer_pos++] = ','; 3560 buffer[buffer_pos++] = ',';
3570 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); 3561 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3571 buffer[buffer_pos++] = ','; 3562 buffer[buffer_pos++] = ',';
3572 buffer_pos = itoa(entry->id(), buffer, buffer_pos); 3563 buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3573 buffer[buffer_pos++] = ','; 3564 buffer[buffer_pos++] = ',';
3574 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); 3565 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3575 buffer[buffer_pos++] = ','; 3566 buffer[buffer_pos++] = ',';
3576 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); 3567 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3577 buffer[buffer_pos++] = ','; 3568 buffer[buffer_pos++] = ',';
3578 buffer_pos = itoa(GetNodeId(entry->dominator()), buffer, buffer_pos); 3569 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
3579 buffer[buffer_pos++] = ','; 3570 buffer[buffer_pos++] = ',';
3580 buffer_pos = itoa(children.length(), buffer, buffer_pos); 3571 buffer_pos = itoa(children.length(), buffer, buffer_pos);
3581 buffer[buffer_pos++] = '\0'; 3572 buffer[buffer_pos++] = '\0';
3582 writer_->AddString(buffer.start()); 3573 writer_->AddString(buffer.start());
3583 for (int i = 0; i < children.length(); ++i) { 3574 for (int i = 0; i < children.length(); ++i) {
3584 SerializeEdge(&children[i]); 3575 SerializeEdge(&children[i]);
3585 if (writer_->aborted()) return; 3576 if (writer_->aborted()) return;
3586 } 3577 }
3587 } 3578 }
3588 3579
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3638 "," JSON_S("weak")) 3629 "," JSON_S("weak"))
3639 "," JSON_S("string_or_number") 3630 "," JSON_S("string_or_number")
3640 "," JSON_S("node")))))); 3631 "," JSON_S("node"))))));
3641 #undef JSON_S 3632 #undef JSON_S
3642 #undef JSON_O 3633 #undef JSON_O
3643 #undef JSON_A 3634 #undef JSON_A
3644 3635
3645 const int node_fields_count = 7; 3636 const int node_fields_count = 7;
3646 // type,name,id,self_size,retained_size,dominator,children_count. 3637 // type,name,id,self_size,retained_size,dominator,children_count.
3647 const int edge_fields_count = 3; // type,name|index,to_node. 3638 const int edge_fields_count = 3; // type,name|index,to_node.
3648 List<HashMap::Entry*> sorted_nodes; 3639
3649 SortHashMap(&nodes_, &sorted_nodes); 3640 List<HeapEntry*>& nodes = *(snapshot_->entries());
3650 // Rewrite node ids, so they refer to actual array positions. 3641 // Root must be the first.
3651 if (sorted_nodes.length() > 1) { 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) {
3652 // Nodes start from array index 1. 3646 // Nodes start from array index 1.
3653 int prev_value = 1; 3647 int index = 1;
3654 sorted_nodes[0]->value = reinterpret_cast<void*>(prev_value); 3648 for (int i = 0; i < nodes.length(); ++i) {
3655 for (int i = 1; i < sorted_nodes.length(); ++i) { 3649 HeapEntry* node = nodes[i];
3656 HeapEntry* prev_heap_entry = 3650 node->set_entry_index(index);
3657 reinterpret_cast<HeapEntry*>(sorted_nodes[i-1]->key); 3651 index += node_fields_count +
3658 prev_value += node_fields_count + 3652 node->children().length() * edge_fields_count;
3659 prev_heap_entry->children().length() * edge_fields_count;
3660 sorted_nodes[i]->value = reinterpret_cast<void*>(prev_value);
3661 } 3653 }
3662 } 3654 }
3663 for (int i = 0; i < sorted_nodes.length(); ++i) { 3655
3664 SerializeNode(reinterpret_cast<HeapEntry*>(sorted_nodes[i]->key)); 3656 for (int i = 0; i < nodes.length(); ++i) {
3657 SerializeNode(nodes[i]);
3665 if (writer_->aborted()) return; 3658 if (writer_->aborted()) return;
3666 } 3659 }
3667 } 3660 }
3668 3661
3669 3662
3670 void HeapSnapshotJSONSerializer::SerializeSnapshot() { 3663 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3671 writer_->AddString("\"title\":\""); 3664 writer_->AddString("\"title\":\"");
3672 writer_->AddString(snapshot_->title()); 3665 writer_->AddString(snapshot_->title());
3673 writer_->AddString("\""); 3666 writer_->AddString("\"");
3674 writer_->AddString(",\"uid\":"); 3667 writer_->AddString(",\"uid\":");
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3763 3756
3764 3757
3765 void HeapSnapshotJSONSerializer::SortHashMap( 3758 void HeapSnapshotJSONSerializer::SortHashMap(
3766 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3759 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3767 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3760 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3768 sorted_entries->Add(p); 3761 sorted_entries->Add(p);
3769 sorted_entries->Sort(SortUsingEntryValue); 3762 sorted_entries->Sort(SortUsingEntryValue);
3770 } 3763 }
3771 3764
3772 } } // namespace v8::internal 3765 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698