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

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

Issue 10105026: Version 3.10.3 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
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') | src/profile-generator-inl.h » ('j') | 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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 index_ = index; 950 index_ = index;
951 to_ = to; 951 to_ = to;
952 } 952 }
953 953
954 954
955 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { 955 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
956 Init(child_index, kElement, index, to); 956 Init(child_index, kElement, index, to);
957 } 957 }
958 958
959 959
960 HeapEntry* HeapGraphEdge::From() {
961 return reinterpret_cast<HeapEntry*>(this - child_index_) - 1;
962 }
963
964
965 void HeapEntry::Init(HeapSnapshot* snapshot, 960 void HeapEntry::Init(HeapSnapshot* snapshot,
966 Type type, 961 Type type,
967 const char* name, 962 const char* name,
968 SnapshotObjectId id, 963 SnapshotObjectId id,
969 int self_size, 964 int self_size,
970 int children_count, 965 int children_count,
971 int retainers_count) { 966 int retainers_count) {
972 snapshot_ = snapshot; 967 snapshot_ = snapshot;
973 type_ = type; 968 type_ = type;
974 painted_ = false; 969 painted_ = false;
970 reachable_from_window_ = false;
975 name_ = name; 971 name_ = name;
976 self_size_ = self_size; 972 self_size_ = self_size;
977 retained_size_ = 0; 973 retained_size_ = 0;
978 entry_index_ = -1; 974 entry_index_ = -1;
979 children_count_ = children_count; 975 children_count_ = children_count;
980 retainers_count_ = retainers_count; 976 retainers_count_ = retainers_count;
981 dominator_ = NULL; 977 dominator_ = NULL;
982 id_ = id; 978 id_ = id;
983 } 979 }
984 980
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 const char* title, 1123 const char* title,
1128 unsigned uid) 1124 unsigned uid)
1129 : collection_(collection), 1125 : collection_(collection),
1130 type_(type), 1126 type_(type),
1131 title_(title), 1127 title_(title),
1132 uid_(uid), 1128 uid_(uid),
1133 root_entry_(NULL), 1129 root_entry_(NULL),
1134 gc_roots_entry_(NULL), 1130 gc_roots_entry_(NULL),
1135 natives_root_entry_(NULL), 1131 natives_root_entry_(NULL),
1136 raw_entries_(NULL), 1132 raw_entries_(NULL),
1133 number_of_edges_(0),
1137 max_snapshot_js_object_id_(0) { 1134 max_snapshot_js_object_id_(0) {
1138 STATIC_CHECK( 1135 STATIC_CHECK(
1139 sizeof(HeapGraphEdge) == 1136 sizeof(HeapGraphEdge) ==
1140 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1137 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1141 STATIC_CHECK( 1138 STATIC_CHECK(
1142 sizeof(HeapEntry) == 1139 sizeof(HeapEntry) ==
1143 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1140 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1144 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1141 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1145 gc_subroot_entries_[i] = NULL; 1142 gc_subroot_entries_[i] = NULL;
1146 } 1143 }
(...skipping 13 matching lines...) Expand all
1160 1157
1161 void HeapSnapshot::RememberLastJSObjectId() { 1158 void HeapSnapshot::RememberLastJSObjectId() {
1162 max_snapshot_js_object_id_ = collection_->last_assigned_id(); 1159 max_snapshot_js_object_id_ = collection_->last_assigned_id();
1163 } 1160 }
1164 1161
1165 1162
1166 void HeapSnapshot::AllocateEntries(int entries_count, 1163 void HeapSnapshot::AllocateEntries(int entries_count,
1167 int children_count, 1164 int children_count,
1168 int retainers_count) { 1165 int retainers_count) {
1169 ASSERT(raw_entries_ == NULL); 1166 ASSERT(raw_entries_ == NULL);
1167 number_of_edges_ = children_count;
1170 raw_entries_size_ = 1168 raw_entries_size_ =
1171 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1169 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1172 raw_entries_ = NewArray<char>(raw_entries_size_); 1170 raw_entries_ = NewArray<char>(raw_entries_size_);
1173 } 1171 }
1174 1172
1175 1173
1176 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1174 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1177 (*entry_ptr)->clear_paint(); 1175 (*entry_ptr)->clear_paint();
1178 } 1176 }
1179 1177
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 1303 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1;
1306 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 1304 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId =
1307 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 1305 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep;
1308 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 1306 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId =
1309 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 1307 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep;
1310 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 1308 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId =
1311 HeapObjectsMap::kGcRootsFirstSubrootId + 1309 HeapObjectsMap::kGcRootsFirstSubrootId +
1312 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; 1310 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep;
1313 1311
1314 HeapObjectsMap::HeapObjectsMap() 1312 HeapObjectsMap::HeapObjectsMap()
1315 : initial_fill_mode_(true), 1313 : next_id_(kFirstAvailableObjectId),
1316 next_id_(kFirstAvailableObjectId), 1314 entries_map_(AddressesMatch) {
1317 entries_map_(AddressesMatch),
1318 entries_(new List<EntryInfo>()) {
1319 // This dummy element solves a problem with entries_map_. 1315 // This dummy element solves a problem with entries_map_.
1320 // When we do lookup in HashMap we see no difference between two cases: 1316 // When we do lookup in HashMap we see no difference between two cases:
1321 // it has an entry with NULL as the value or it has created 1317 // it has an entry with NULL as the value or it has created
1322 // a new entry on the fly with NULL as the default value. 1318 // a new entry on the fly with NULL as the default value.
1323 // With such dummy element we have a guaranty that all entries_map_ entries 1319 // With such dummy element we have a guaranty that all entries_map_ entries
1324 // will have the value field grater than 0. 1320 // will have the value field grater than 0.
1325 // This fact is using in MoveObject method. 1321 // This fact is using in MoveObject method.
1326 entries_->Add(EntryInfo(0, NULL)); 1322 entries_.Add(EntryInfo(0, NULL, 0));
1327 }
1328
1329
1330 HeapObjectsMap::~HeapObjectsMap() {
1331 delete entries_;
1332 } 1323 }
1333 1324
1334 1325
1335 void HeapObjectsMap::SnapshotGenerationFinished() { 1326 void HeapObjectsMap::SnapshotGenerationFinished() {
1336 initial_fill_mode_ = false;
1337 RemoveDeadEntries(); 1327 RemoveDeadEntries();
1338 } 1328 }
1339 1329
1340 1330
1341 SnapshotObjectId HeapObjectsMap::FindObject(Address addr) {
1342 if (!initial_fill_mode_) {
1343 SnapshotObjectId existing = FindEntry(addr);
1344 if (existing != 0) return existing;
1345 }
1346 SnapshotObjectId id = next_id_;
1347 next_id_ += kObjectIdStep;
1348 AddEntry(addr, id);
1349 // Here and in other places the length of entries_ list has to be
1350 // the same or greater than the length of entries_map_. But entries_ list
1351 // has a dummy element at index 0.
1352 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1353 return id;
1354 }
1355
1356
1357 void HeapObjectsMap::MoveObject(Address from, Address to) { 1331 void HeapObjectsMap::MoveObject(Address from, Address to) {
1358 ASSERT(to != NULL); 1332 ASSERT(to != NULL);
1359 ASSERT(from != NULL); 1333 ASSERT(from != NULL);
1360 if (from == to) return; 1334 if (from == to) return;
1361 void* from_value = entries_map_.Remove(from, AddressHash(from)); 1335 void* from_value = entries_map_.Remove(from, AddressHash(from));
1362 if (from_value == NULL) return; 1336 if (from_value == NULL) return;
1363 int from_entry_info_index = 1337 int from_entry_info_index =
1364 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); 1338 static_cast<int>(reinterpret_cast<intptr_t>(from_value));
1365 entries_->at(from_entry_info_index).addr = to; 1339 entries_.at(from_entry_info_index).addr = to;
1366 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); 1340 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true);
1367 if (to_entry->value != NULL) { 1341 if (to_entry->value != NULL) {
1368 int to_entry_info_index = 1342 int to_entry_info_index =
1369 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); 1343 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value));
1370 // Without this operation we will have two EntryInfo's with the same 1344 // Without this operation we will have two EntryInfo's with the same
1371 // value in addr field. It is bad because later at RemoveDeadEntries 1345 // value in addr field. It is bad because later at RemoveDeadEntries
1372 // one of this entry will be removed with the corresponding entries_map_ 1346 // one of this entry will be removed with the corresponding entries_map_
1373 // entry. 1347 // entry.
1374 entries_->at(to_entry_info_index).addr = NULL; 1348 entries_.at(to_entry_info_index).addr = NULL;
1375 } 1349 }
1376 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); 1350 to_entry->value = reinterpret_cast<void*>(from_entry_info_index);
1377 } 1351 }
1378 1352
1379 1353
1380 void HeapObjectsMap::AddEntry(Address addr, SnapshotObjectId id) { 1354 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
1381 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); 1355 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false);
1382 ASSERT(entry->value == NULL); 1356 if (entry == NULL) return 0;
1383 ASSERT(entries_->length() > 0 && 1357 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1384 entries_->at(0).id == 0 && 1358 EntryInfo& entry_info = entries_.at(entry_index);
1385 entries_->at(0).addr == NULL); 1359 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
1386 ASSERT(entries_->at(entries_->length() - 1).id < id); 1360 return entry_info.id;
1387 entry->value = reinterpret_cast<void*>(entries_->length());
1388 entries_->Add(EntryInfo(id, addr));
1389 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1390 } 1361 }
1391 1362
1392 1363
1393 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { 1364 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr,
1394 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); 1365 unsigned int size) {
1395 if (entry != NULL) { 1366 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
1396 int entry_index =
1397 static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1398 EntryInfo& entry_info = entries_->at(entry_index);
1399 entry_info.accessed = true;
1400 ASSERT(static_cast<uint32_t>(entries_->length()) >
1401 entries_map_.occupancy());
1402 return entry_info.id;
1403 } else {
1404 return 0;
1405 }
1406 }
1407
1408
1409 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr) {
1410 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1411 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); 1367 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
1412 if (entry->value != NULL) { 1368 if (entry->value != NULL) {
1413 int entry_index = 1369 int entry_index =
1414 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 1370 static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1415 EntryInfo& entry_info = entries_->at(entry_index); 1371 EntryInfo& entry_info = entries_.at(entry_index);
1416 entry_info.accessed = true; 1372 entry_info.accessed = true;
1373 entry_info.size = size;
1417 return entry_info.id; 1374 return entry_info.id;
1418 } 1375 }
1419 entry->value = reinterpret_cast<void*>(entries_->length()); 1376 entry->value = reinterpret_cast<void*>(entries_.length());
1420 SnapshotObjectId id = next_id_; 1377 SnapshotObjectId id = next_id_;
1421 next_id_ += kObjectIdStep; 1378 next_id_ += kObjectIdStep;
1422 entries_->Add(EntryInfo(id, addr)); 1379 entries_.Add(EntryInfo(id, addr, size));
1423 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); 1380 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
1424 return id; 1381 return id;
1425 } 1382 }
1426 1383
1427 1384
1428 void HeapObjectsMap::StopHeapObjectsTracking() { 1385 void HeapObjectsMap::StopHeapObjectsTracking() {
1429 time_intervals_.Clear(); 1386 time_intervals_.Clear();
1430 } 1387 }
1431 1388
1432 void HeapObjectsMap::UpdateHeapObjectsMap() { 1389 void HeapObjectsMap::UpdateHeapObjectsMap() {
1433 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, 1390 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1434 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); 1391 "HeapSnapshotsCollection::UpdateHeapObjectsMap");
1435 HeapIterator iterator(HeapIterator::kFilterUnreachable); 1392 HeapIterator iterator;
1436 for (HeapObject* obj = iterator.next(); 1393 for (HeapObject* obj = iterator.next();
1437 obj != NULL; 1394 obj != NULL;
1438 obj = iterator.next()) { 1395 obj = iterator.next()) {
1439 FindOrAddEntry(obj->address()); 1396 FindOrAddEntry(obj->address(), obj->Size());
1440 } 1397 }
1441 initial_fill_mode_ = false;
1442 RemoveDeadEntries(); 1398 RemoveDeadEntries();
1443 } 1399 }
1444 1400
1445 1401
1446 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { 1402 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) {
1447 UpdateHeapObjectsMap(); 1403 UpdateHeapObjectsMap();
1448 time_intervals_.Add(TimeInterval(next_id_)); 1404 time_intervals_.Add(TimeInterval(next_id_));
1449 int prefered_chunk_size = stream->GetChunkSize(); 1405 int prefered_chunk_size = stream->GetChunkSize();
1450 List<uint32_t> stats_buffer; 1406 List<uint32_t> stats_buffer;
1451 ASSERT(!entries_->is_empty()); 1407 ASSERT(!entries_.is_empty());
1452 EntryInfo* entry_info = &entries_->first(); 1408 EntryInfo* entry_info = &entries_.first();
1453 EntryInfo* end_entry_info = &entries_->last() + 1; 1409 EntryInfo* end_entry_info = &entries_.last() + 1;
1454 for (int time_interval_index = 0; 1410 for (int time_interval_index = 0;
1455 time_interval_index < time_intervals_.length(); 1411 time_interval_index < time_intervals_.length();
1456 ++time_interval_index) { 1412 ++time_interval_index) {
1457 TimeInterval& time_interval = time_intervals_[time_interval_index]; 1413 TimeInterval& time_interval = time_intervals_[time_interval_index];
1458 SnapshotObjectId time_interval_id = time_interval.id; 1414 SnapshotObjectId time_interval_id = time_interval.id;
1459 uint32_t entries_count = 0; 1415 uint32_t entries_size = 0;
1416 EntryInfo* start_entry_info = entry_info;
1460 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { 1417 while (entry_info < end_entry_info && entry_info->id < time_interval_id) {
1461 ++entries_count; 1418 entries_size += entry_info->size;
1462 ++entry_info; 1419 ++entry_info;
1463 } 1420 }
1464 if (time_interval.count != entries_count) { 1421 uint32_t entries_count =
1422 static_cast<uint32_t>(entry_info - start_entry_info);
1423 if (time_interval.count != entries_count ||
1424 time_interval.size != entries_size) {
1465 stats_buffer.Add(time_interval_index); 1425 stats_buffer.Add(time_interval_index);
1466 stats_buffer.Add(time_interval.count = entries_count); 1426 stats_buffer.Add(time_interval.count = entries_count);
1427 stats_buffer.Add(time_interval.size = entries_size);
1467 if (stats_buffer.length() >= prefered_chunk_size) { 1428 if (stats_buffer.length() >= prefered_chunk_size) {
1468 OutputStream::WriteResult result = stream->WriteUint32Chunk( 1429 OutputStream::WriteResult result = stream->WriteUint32Chunk(
1469 &stats_buffer.first(), stats_buffer.length()); 1430 &stats_buffer.first(), stats_buffer.length());
1470 if (result == OutputStream::kAbort) return; 1431 if (result == OutputStream::kAbort) return;
1471 stats_buffer.Clear(); 1432 stats_buffer.Clear();
1472 } 1433 }
1473 } 1434 }
1474 } 1435 }
1475 ASSERT(entry_info == end_entry_info); 1436 ASSERT(entry_info == end_entry_info);
1476 if (!stats_buffer.is_empty()) { 1437 if (!stats_buffer.is_empty()) {
1477 OutputStream::WriteResult result = 1438 OutputStream::WriteResult result =
1478 stream->WriteUint32Chunk(&stats_buffer.first(), stats_buffer.length()); 1439 stream->WriteUint32Chunk(&stats_buffer.first(), stats_buffer.length());
1479 if (result == OutputStream::kAbort) return; 1440 if (result == OutputStream::kAbort) return;
1480 } 1441 }
1481 stream->EndOfStream(); 1442 stream->EndOfStream();
1482 } 1443 }
1483 1444
1484 1445
1485 void HeapObjectsMap::RemoveDeadEntries() { 1446 void HeapObjectsMap::RemoveDeadEntries() {
1486 ASSERT(entries_->length() > 0 && 1447 ASSERT(entries_.length() > 0 &&
1487 entries_->at(0).id == 0 && 1448 entries_.at(0).id == 0 &&
1488 entries_->at(0).addr == NULL); 1449 entries_.at(0).addr == NULL);
1489 int first_free_entry = 1; 1450 int first_free_entry = 1;
1490 for (int i = 1; i < entries_->length(); ++i) { 1451 for (int i = 1; i < entries_.length(); ++i) {
1491 EntryInfo& entry_info = entries_->at(i); 1452 EntryInfo& entry_info = entries_.at(i);
1492 if (entry_info.accessed) { 1453 if (entry_info.accessed) {
1493 if (first_free_entry != i) { 1454 if (first_free_entry != i) {
1494 entries_->at(first_free_entry) = entry_info; 1455 entries_.at(first_free_entry) = entry_info;
1495 } 1456 }
1496 entries_->at(first_free_entry).accessed = false; 1457 entries_.at(first_free_entry).accessed = false;
1497 HashMap::Entry* entry = entries_map_.Lookup( 1458 HashMap::Entry* entry = entries_map_.Lookup(
1498 entry_info.addr, AddressHash(entry_info.addr), false); 1459 entry_info.addr, AddressHash(entry_info.addr), false);
1499 ASSERT(entry); 1460 ASSERT(entry);
1500 entry->value = reinterpret_cast<void*>(first_free_entry); 1461 entry->value = reinterpret_cast<void*>(first_free_entry);
1501 ++first_free_entry; 1462 ++first_free_entry;
1502 } else { 1463 } else {
1503 if (entry_info.addr) { 1464 if (entry_info.addr) {
1504 entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr)); 1465 entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr));
1505 } 1466 }
1506 } 1467 }
1507 } 1468 }
1508 entries_->Rewind(first_free_entry); 1469 entries_.Rewind(first_free_entry);
1509 ASSERT(static_cast<uint32_t>(entries_->length()) - 1 == 1470 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 ==
1510 entries_map_.occupancy()); 1471 entries_map_.occupancy());
1511 } 1472 }
1512 1473
1513 1474
1514 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { 1475 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
1515 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); 1476 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash());
1516 const char* label = info->GetLabel(); 1477 const char* label = info->GetLabel();
1517 id ^= HashSequentialString(label, 1478 id ^= HashSequentialString(label,
1518 static_cast<int>(strlen(label)), 1479 static_cast<int>(strlen(label)),
1519 HEAP->HashSeed()); 1480 HEAP->HashSeed());
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 // First perform a full GC in order to avoid dead objects. 1548 // First perform a full GC in order to avoid dead objects.
1588 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, 1549 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1589 "HeapSnapshotsCollection::FindHeapObjectById"); 1550 "HeapSnapshotsCollection::FindHeapObjectById");
1590 AssertNoAllocation no_allocation; 1551 AssertNoAllocation no_allocation;
1591 HeapObject* object = NULL; 1552 HeapObject* object = NULL;
1592 HeapIterator iterator(HeapIterator::kFilterUnreachable); 1553 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1593 // Make sure that object with the given id is still reachable. 1554 // Make sure that object with the given id is still reachable.
1594 for (HeapObject* obj = iterator.next(); 1555 for (HeapObject* obj = iterator.next();
1595 obj != NULL; 1556 obj != NULL;
1596 obj = iterator.next()) { 1557 obj = iterator.next()) {
1597 if (ids_.FindObject(obj->address()) == id) { 1558 if (ids_.FindEntry(obj->address()) == id) {
1598 ASSERT(object == NULL); 1559 ASSERT(object == NULL);
1599 object = obj; 1560 object = obj;
1600 // Can't break -- kFilterUnreachable requires full heap traversal. 1561 // Can't break -- kFilterUnreachable requires full heap traversal.
1601 } 1562 }
1602 } 1563 }
1603 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); 1564 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
1604 } 1565 }
1605 1566
1606 1567
1607 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder = 1568 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder =
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 children_count, 1849 children_count,
1889 retainers_count); 1850 retainers_count);
1890 } 1851 }
1891 1852
1892 1853
1893 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 1854 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1894 HeapEntry::Type type, 1855 HeapEntry::Type type,
1895 const char* name, 1856 const char* name,
1896 int children_count, 1857 int children_count,
1897 int retainers_count) { 1858 int retainers_count) {
1859 int object_size = object->Size();
1860 SnapshotObjectId object_id =
1861 collection_->GetObjectId(object->address(), object_size);
1898 return snapshot_->AddEntry(type, 1862 return snapshot_->AddEntry(type,
1899 name, 1863 name,
1900 collection_->GetObjectId(object->address()), 1864 object_id,
1901 object->Size(), 1865 object_size,
1902 children_count, 1866 children_count,
1903 retainers_count); 1867 retainers_count);
1904 } 1868 }
1905 1869
1906 1870
1907 class GcSubrootsEnumerator : public ObjectVisitor { 1871 class GcSubrootsEnumerator : public ObjectVisitor {
1908 public: 1872 public:
1909 GcSubrootsEnumerator( 1873 GcSubrootsEnumerator(
1910 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) 1874 SnapshotFillerInterface* filler, V8HeapExplorer* explorer)
1911 : filler_(filler), 1875 : filler_(filler),
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { 1973 void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
2010 HeapEntry* entry = GetEntry(obj); 1974 HeapEntry* entry = GetEntry(obj);
2011 if (entry == NULL) return; // No interest in this object. 1975 if (entry == NULL) return; // No interest in this object.
2012 1976
2013 bool extract_indexed_refs = true; 1977 bool extract_indexed_refs = true;
2014 if (obj->IsJSGlobalProxy()) { 1978 if (obj->IsJSGlobalProxy()) {
2015 // We need to reference JS global objects from snapshot's root. 1979 // We need to reference JS global objects from snapshot's root.
2016 // We use JSGlobalProxy because this is what embedder (e.g. browser) 1980 // We use JSGlobalProxy because this is what embedder (e.g. browser)
2017 // uses for the global object. 1981 // uses for the global object.
2018 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); 1982 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
2019 SetRootShortcutReference(proxy->map()->prototype()); 1983 SetWindowReference(proxy->map()->prototype());
2020 } else if (obj->IsJSObject()) { 1984 } else if (obj->IsJSObject()) {
2021 JSObject* js_obj = JSObject::cast(obj); 1985 JSObject* js_obj = JSObject::cast(obj);
2022 ExtractClosureReferences(js_obj, entry); 1986 ExtractClosureReferences(js_obj, entry);
2023 ExtractPropertyReferences(js_obj, entry); 1987 ExtractPropertyReferences(js_obj, entry);
2024 ExtractElementReferences(js_obj, entry); 1988 ExtractElementReferences(js_obj, entry);
2025 ExtractInternalReferences(js_obj, entry); 1989 ExtractInternalReferences(js_obj, entry);
2026 SetPropertyReference( 1990 SetPropertyReference(
2027 obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype()); 1991 obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype());
2028 if (obj->IsJSFunction()) { 1992 if (obj->IsJSFunction()) {
2029 JSFunction* js_fun = JSFunction::cast(js_obj); 1993 JSFunction* js_fun = JSFunction::cast(js_obj);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 obj->Iterate(&refs_extractor); 2144 obj->Iterate(&refs_extractor);
2181 } 2145 }
2182 } 2146 }
2183 2147
2184 2148
2185 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, 2149 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
2186 HeapEntry* entry) { 2150 HeapEntry* entry) {
2187 if (!js_obj->IsJSFunction()) return; 2151 if (!js_obj->IsJSFunction()) return;
2188 2152
2189 JSFunction* func = JSFunction::cast(js_obj); 2153 JSFunction* func = JSFunction::cast(js_obj);
2190 Context* context = func->context(); 2154 Context* context = func->context()->declaration_context();
2191 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); 2155 ScopeInfo* scope_info = context->closure()->shared()->scope_info();
2192 2156
2193 if (func->shared()->bound()) { 2157 if (func->shared()->bound()) {
2194 FixedArray* bindings = func->function_bindings(); 2158 FixedArray* bindings = func->function_bindings();
2195 SetNativeBindReference(js_obj, entry, "bound_this", 2159 SetNativeBindReference(js_obj, entry, "bound_this",
2196 bindings->get(JSFunction::kBoundThisIndex)); 2160 bindings->get(JSFunction::kBoundThisIndex));
2197 SetNativeBindReference(js_obj, entry, "bound_function", 2161 SetNativeBindReference(js_obj, entry, "bound_function",
2198 bindings->get(JSFunction::kBoundFunctionIndex)); 2162 bindings->get(JSFunction::kBoundFunctionIndex));
2199 for (int i = JSFunction::kBoundArgumentsStartIndex; 2163 for (int i = JSFunction::kBoundArgumentsStartIndex;
2200 i < bindings->length(); i++) { 2164 i < bindings->length(); i++) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2277 break; 2241 break;
2278 } 2242 }
2279 } 2243 }
2280 } else { 2244 } else {
2281 StringDictionary* dictionary = js_obj->property_dictionary(); 2245 StringDictionary* dictionary = js_obj->property_dictionary();
2282 int length = dictionary->Capacity(); 2246 int length = dictionary->Capacity();
2283 for (int i = 0; i < length; ++i) { 2247 for (int i = 0; i < length; ++i) {
2284 Object* k = dictionary->KeyAt(i); 2248 Object* k = dictionary->KeyAt(i);
2285 if (dictionary->IsKey(k)) { 2249 if (dictionary->IsKey(k)) {
2286 Object* target = dictionary->ValueAt(i); 2250 Object* target = dictionary->ValueAt(i);
2287 SetPropertyReference(
2288 js_obj, entry, String::cast(k), target);
2289 // We assume that global objects can only have slow properties. 2251 // We assume that global objects can only have slow properties.
2290 if (target->IsJSGlobalPropertyCell()) { 2252 Object* value = target->IsJSGlobalPropertyCell()
2291 SetPropertyShortcutReference(js_obj, 2253 ? JSGlobalPropertyCell::cast(target)->value()
2292 entry, 2254 : target;
2293 String::cast(k), 2255 if (String::cast(k)->length() > 0) {
2294 JSGlobalPropertyCell::cast( 2256 SetPropertyReference(js_obj, entry, String::cast(k), value);
2295 target)->value()); 2257 } else {
2258 TagObject(value, "(hidden properties)");
2259 SetInternalReference(js_obj, entry, "hidden_properties", value);
2296 } 2260 }
2297 } 2261 }
2298 } 2262 }
2299 } 2263 }
2300 } 2264 }
2301 2265
2302 2266
2303 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, 2267 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2304 HeapEntry* entry) { 2268 HeapEntry* entry) {
2305 if (js_obj->HasFastElements()) { 2269 if (js_obj->HasFastElements()) {
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 2618
2655 2619
2656 void V8HeapExplorer::SetRootGcRootsReference() { 2620 void V8HeapExplorer::SetRootGcRootsReference() {
2657 filler_->SetIndexedAutoIndexReference( 2621 filler_->SetIndexedAutoIndexReference(
2658 HeapGraphEdge::kElement, 2622 HeapGraphEdge::kElement,
2659 kInternalRootObject, snapshot_->root(), 2623 kInternalRootObject, snapshot_->root(),
2660 kGcRootsObject, snapshot_->gc_roots()); 2624 kGcRootsObject, snapshot_->gc_roots());
2661 } 2625 }
2662 2626
2663 2627
2664 void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) { 2628 void V8HeapExplorer::SetWindowReference(Object* child_obj) {
2665 HeapEntry* child_entry = GetEntry(child_obj); 2629 HeapEntry* child_entry = GetEntry(child_obj);
2666 ASSERT(child_entry != NULL); 2630 ASSERT(child_entry != NULL);
2667 filler_->SetNamedAutoIndexReference( 2631 filler_->SetNamedAutoIndexReference(
2668 HeapGraphEdge::kShortcut, 2632 HeapGraphEdge::kShortcut,
2669 kInternalRootObject, snapshot_->root(), 2633 kInternalRootObject, snapshot_->root(),
2670 child_obj, child_entry); 2634 child_obj, child_entry);
2671 } 2635 }
2672 2636
2673 2637
2674 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) { 2638 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2736 isolate->factory()->NewStringFromAscii(CStrVector("document")); 2700 isolate->factory()->NewStringFromAscii(CStrVector("document"));
2737 Handle<String> url_string = 2701 Handle<String> url_string =
2738 isolate->factory()->NewStringFromAscii(CStrVector("URL")); 2702 isolate->factory()->NewStringFromAscii(CStrVector("URL"));
2739 const char** urls = NewArray<const char*>(enumerator.count()); 2703 const char** urls = NewArray<const char*>(enumerator.count());
2740 for (int i = 0, l = enumerator.count(); i < l; ++i) { 2704 for (int i = 0, l = enumerator.count(); i < l; ++i) {
2741 urls[i] = NULL; 2705 urls[i] = NULL;
2742 HandleScope scope; 2706 HandleScope scope;
2743 Handle<JSGlobalObject> global_obj = enumerator.at(i); 2707 Handle<JSGlobalObject> global_obj = enumerator.at(i);
2744 Object* obj_document; 2708 Object* obj_document;
2745 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) && 2709 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) &&
2746 obj_document->IsJSObject()) { 2710 obj_document->IsJSObject()) {
2747 JSObject* document = JSObject::cast(obj_document); 2711 JSObject* document = JSObject::cast(obj_document);
2748 Object* obj_url; 2712 Object* obj_url;
2749 if (document->GetProperty(*url_string)->ToObject(&obj_url) && 2713 if (document->GetProperty(*url_string)->ToObject(&obj_url) &&
2750 obj_url->IsString()) { 2714 obj_url->IsString()) {
2751 urls[i] = collection_->names()->GetName(String::cast(obj_url)); 2715 urls[i] = collection_->names()->GetName(String::cast(obj_url));
2752 } 2716 }
2753 } 2717 }
2754 } 2718 }
2755 2719
2756 AssertNoAllocation no_allocation; 2720 AssertNoAllocation no_allocation;
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
3290 // in turn may relocate objects in property maps thus changing the heap 3254 // in turn may relocate objects in property maps thus changing the heap
3291 // layout and affecting retainer counts. This is not acceptable because 3255 // layout and affecting retainer counts. This is not acceptable because
3292 // number of retainers must not change between count and fill passes. 3256 // number of retainers must not change between count and fill passes.
3293 // To avoid this there's a separate postpass that set object names. 3257 // To avoid this there's a separate postpass that set object names.
3294 return v8_heap_explorer_.IterateAndExtractReferences(&filler) 3258 return v8_heap_explorer_.IterateAndExtractReferences(&filler)
3295 && dom_explorer_.IterateAndExtractReferences(&filler) 3259 && dom_explorer_.IterateAndExtractReferences(&filler)
3296 && v8_heap_explorer_.IterateAndSetObjectNames(&filler); 3260 && v8_heap_explorer_.IterateAndSetObjectNames(&filler);
3297 } 3261 }
3298 3262
3299 3263
3300 void HeapSnapshotGenerator::FillReversePostorderIndexes( 3264 bool HeapSnapshotGenerator::IsWindowReference(const HeapGraphEdge& edge) {
3265 ASSERT(edge.from() == snapshot_->root());
3266 return edge.type() == HeapGraphEdge::kShortcut;
3267 }
3268
3269
3270 void HeapSnapshotGenerator::MarkWindowReachableObjects() {
3271 List<HeapEntry*> worklist;
3272
3273 Vector<HeapGraphEdge> children = snapshot_->root()->children();
3274 for (int i = 0; i < children.length(); ++i) {
3275 if (IsWindowReference(children[i])) {
3276 worklist.Add(children[i].to());
3277 }
3278 }
3279
3280 while (!worklist.is_empty()) {
3281 HeapEntry* entry = worklist.RemoveLast();
3282 if (entry->reachable_from_window()) continue;
3283 entry->set_reachable_from_window();
3284 Vector<HeapGraphEdge> children = entry->children();
3285 for (int i = 0; i < children.length(); ++i) {
3286 HeapEntry* child = children[i].to();
3287 if (!child->reachable_from_window()) {
3288 worklist.Add(child);
3289 }
3290 }
3291 }
3292 }
3293
3294
3295 static bool IsRetainingEdge(HeapGraphEdge* edge) {
3296 if (edge->type() == HeapGraphEdge::kShortcut) return false;
3297 // The edge is not retaining if it goes from system domain
3298 // (i.e. an object not reachable from window) to the user domain
3299 // (i.e. a reachable object).
3300 return edge->from()->reachable_from_window()
3301 || !edge->to()->reachable_from_window();
3302 }
3303
3304
3305 void HeapSnapshotGenerator::FillPostorderIndexes(
3301 Vector<HeapEntry*>* entries) { 3306 Vector<HeapEntry*>* entries) {
3302 snapshot_->ClearPaint(); 3307 snapshot_->ClearPaint();
3303 int current_entry = 0; 3308 int current_entry = 0;
3304 List<HeapEntry*> nodes_to_visit; 3309 List<HeapEntry*> nodes_to_visit;
3305 nodes_to_visit.Add(snapshot_->root()); 3310 HeapEntry* root = snapshot_->root();
3311 nodes_to_visit.Add(root);
3306 snapshot_->root()->paint(); 3312 snapshot_->root()->paint();
3307 while (!nodes_to_visit.is_empty()) { 3313 while (!nodes_to_visit.is_empty()) {
3308 HeapEntry* entry = nodes_to_visit.last(); 3314 HeapEntry* entry = nodes_to_visit.last();
3309 Vector<HeapGraphEdge> children = entry->children(); 3315 Vector<HeapGraphEdge> children = entry->children();
3310 bool has_new_edges = false; 3316 bool has_new_edges = false;
3311 for (int i = 0; i < children.length(); ++i) { 3317 for (int i = 0; i < children.length(); ++i) {
3312 if (children[i].type() == HeapGraphEdge::kShortcut) continue; 3318 if (entry != root && !IsRetainingEdge(&children[i])) continue;
3313 HeapEntry* child = children[i].to(); 3319 HeapEntry* child = children[i].to();
3314 if (!child->painted()) { 3320 if (!child->painted()) {
3315 nodes_to_visit.Add(child); 3321 nodes_to_visit.Add(child);
3316 child->paint(); 3322 child->paint();
3317 has_new_edges = true; 3323 has_new_edges = true;
3318 } 3324 }
3319 } 3325 }
3320 if (!has_new_edges) { 3326 if (!has_new_edges) {
3321 entry->set_ordered_index(current_entry); 3327 entry->set_ordered_index(current_entry);
3322 (*entries)[current_entry++] = entry; 3328 (*entries)[current_entry++] = entry;
(...skipping 14 matching lines...) Expand all
3337 } 3343 }
3338 3344
3339 3345
3340 // The algorithm is based on the article: 3346 // The algorithm is based on the article:
3341 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" 3347 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
3342 // Softw. Pract. Exper. 4 (2001), pp. 1-10. 3348 // Softw. Pract. Exper. 4 (2001), pp. 1-10.
3343 bool HeapSnapshotGenerator::BuildDominatorTree( 3349 bool HeapSnapshotGenerator::BuildDominatorTree(
3344 const Vector<HeapEntry*>& entries, 3350 const Vector<HeapEntry*>& entries,
3345 Vector<int>* dominators) { 3351 Vector<int>* dominators) {
3346 if (entries.length() == 0) return true; 3352 if (entries.length() == 0) return true;
3353 HeapEntry* root = snapshot_->root();
3347 const int entries_length = entries.length(), root_index = entries_length - 1; 3354 const int entries_length = entries.length(), root_index = entries_length - 1;
3348 static const int kNoDominator = -1; 3355 static const int kNoDominator = -1;
3349 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; 3356 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
3350 (*dominators)[root_index] = root_index; 3357 (*dominators)[root_index] = root_index;
3351 3358
3352 // The affected array is used to mark entries which dominators 3359 // The affected array is used to mark entries which dominators
3353 // have to be racalculated because of changes in their retainers. 3360 // have to be racalculated because of changes in their retainers.
3354 ScopedVector<bool> affected(entries_length); 3361 ScopedVector<bool> affected(entries_length);
3355 for (int i = 0; i < affected.length(); ++i) affected[i] = false; 3362 for (int i = 0; i < affected.length(); ++i) affected[i] = false;
3356 // Mark the root direct children as affected. 3363 // Mark the root direct children as affected.
3357 Vector<HeapGraphEdge> children = entries[root_index]->children(); 3364 Vector<HeapGraphEdge> children = entries[root_index]->children();
3358 for (int i = 0; i < children.length(); ++i) { 3365 for (int i = 0; i < children.length(); ++i) {
3359 affected[children[i].to()->ordered_index()] = true; 3366 affected[children[i].to()->ordered_index()] = true;
3360 } 3367 }
3361 3368
3362 bool changed = true; 3369 bool changed = true;
3363 while (changed) { 3370 while (changed) {
3364 changed = false; 3371 changed = false;
3365 if (!ProgressReport(true)) return false; 3372 if (!ProgressReport(true)) return false;
3366 for (int i = root_index - 1; i >= 0; --i) { 3373 for (int i = root_index - 1; i >= 0; --i) {
3367 if (!affected[i]) continue; 3374 if (!affected[i]) continue;
3368 affected[i] = false; 3375 affected[i] = false;
3369 // If dominator of the entry has already been set to root, 3376 // If dominator of the entry has already been set to root,
3370 // then it can't propagate any further. 3377 // then it can't propagate any further.
3371 if ((*dominators)[i] == root_index) continue; 3378 if ((*dominators)[i] == root_index) continue;
3372 int new_idom_index = kNoDominator; 3379 int new_idom_index = kNoDominator;
3373 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); 3380 Vector<HeapGraphEdge*> rets = entries[i]->retainers();
3374 for (int j = 0; j < rets.length(); ++j) { 3381 for (int j = 0; j < rets.length(); ++j) {
3375 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; 3382 if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
3376 int ret_index = rets[j]->From()->ordered_index(); 3383 int ret_index = rets[j]->from()->ordered_index();
3377 if (dominators->at(ret_index) != kNoDominator) { 3384 if (dominators->at(ret_index) != kNoDominator) {
3378 new_idom_index = new_idom_index == kNoDominator 3385 new_idom_index = new_idom_index == kNoDominator
3379 ? ret_index 3386 ? ret_index
3380 : Intersect(ret_index, new_idom_index, *dominators); 3387 : Intersect(ret_index, new_idom_index, *dominators);
3381 // If idom has already reached the root, it doesn't make sense 3388 // If idom has already reached the root, it doesn't make sense
3382 // to check other retainers. 3389 // to check other retainers.
3383 if (new_idom_index == root_index) break; 3390 if (new_idom_index == root_index) break;
3384 } 3391 }
3385 } 3392 }
3386 if (new_idom_index != kNoDominator 3393 if (new_idom_index != kNoDominator
3387 && dominators->at(i) != new_idom_index) { 3394 && dominators->at(i) != new_idom_index) {
3388 (*dominators)[i] = new_idom_index; 3395 (*dominators)[i] = new_idom_index;
3389 changed = true; 3396 changed = true;
3390 Vector<HeapGraphEdge> children = entries[i]->children(); 3397 Vector<HeapGraphEdge> children = entries[i]->children();
3391 for (int j = 0; j < children.length(); ++j) { 3398 for (int j = 0; j < children.length(); ++j) {
3392 affected[children[j].to()->ordered_index()] = true; 3399 affected[children[j].to()->ordered_index()] = true;
3393 } 3400 }
3394 } 3401 }
3395 } 3402 }
3396 } 3403 }
3397 return true; 3404 return true;
3398 } 3405 }
3399 3406
3400 3407
3401 bool HeapSnapshotGenerator::SetEntriesDominators() { 3408 bool HeapSnapshotGenerator::SetEntriesDominators() {
3402 // This array is used for maintaining reverse postorder of nodes. 3409 MarkWindowReachableObjects();
3410 // This array is used for maintaining postorder of nodes.
3403 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); 3411 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
3404 FillReversePostorderIndexes(&ordered_entries); 3412 FillPostorderIndexes(&ordered_entries);
3405 ScopedVector<int> dominators(ordered_entries.length()); 3413 ScopedVector<int> dominators(ordered_entries.length());
3406 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; 3414 if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
3407 for (int i = 0; i < ordered_entries.length(); ++i) { 3415 for (int i = 0; i < ordered_entries.length(); ++i) {
3408 ASSERT(dominators[i] >= 0); 3416 ASSERT(dominators[i] >= 0);
3409 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); 3417 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]);
3410 } 3418 }
3411 return true; 3419 return true;
3412 } 3420 }
3413 3421
3414 3422
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
3569 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB, 3577 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
3570 (snapshot_->raw_entries_size() + MB - 1) / MB); 3578 (snapshot_->raw_entries_size() + MB - 1) / MB);
3571 HeapEntry* message = result->AddEntry( 3579 HeapEntry* message = result->AddEntry(
3572 HeapEntry::kString, text, 0, 4, 0, 0); 3580 HeapEntry::kString, text, 0, 4, 0, 0);
3573 root->SetUnidirElementReference(0, 1, message); 3581 root->SetUnidirElementReference(0, 1, message);
3574 result->SetDominatorsToSelf(); 3582 result->SetDominatorsToSelf();
3575 return result; 3583 return result;
3576 } 3584 }
3577 3585
3578 3586
3587 void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
3588 const List<HeapEntry*>& nodes) {
3589 // type,name,id,self_size,retained_size,dominator,children_index.
3590 const int node_fields_count = 7;
3591 // Root must be the first.
3592 ASSERT(nodes.first() == snapshot_->root());
3593 // Rewrite node indexes, so they refer to actual array positions. Do this
3594 // only once.
3595 if (nodes[0]->entry_index() == -1) {
3596 int index = 0;
3597 for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
3598 nodes[i]->set_entry_index(index);
3599 }
3600 }
3601 }
3602
3603
3579 void HeapSnapshotJSONSerializer::SerializeImpl() { 3604 void HeapSnapshotJSONSerializer::SerializeImpl() {
3605 List<HeapEntry*>& nodes = *(snapshot_->entries());
3606 CalculateNodeIndexes(nodes);
3580 writer_->AddCharacter('{'); 3607 writer_->AddCharacter('{');
3581 writer_->AddString("\"snapshot\":{"); 3608 writer_->AddString("\"snapshot\":{");
3582 SerializeSnapshot(); 3609 SerializeSnapshot();
3583 if (writer_->aborted()) return; 3610 if (writer_->aborted()) return;
3584 writer_->AddString("},\n"); 3611 writer_->AddString("},\n");
3585 writer_->AddString("\"nodes\":["); 3612 writer_->AddString("\"nodes\":[");
3586 SerializeNodes(); 3613 SerializeNodes(nodes);
3614 if (writer_->aborted()) return;
3615 writer_->AddString("],\n");
3616 writer_->AddString("\"edges\":[");
3617 SerializeEdges(nodes);
3587 if (writer_->aborted()) return; 3618 if (writer_->aborted()) return;
3588 writer_->AddString("],\n"); 3619 writer_->AddString("],\n");
3589 writer_->AddString("\"strings\":["); 3620 writer_->AddString("\"strings\":[");
3590 SerializeStrings(); 3621 SerializeStrings();
3591 if (writer_->aborted()) return; 3622 if (writer_->aborted()) return;
3592 writer_->AddCharacter(']'); 3623 writer_->AddCharacter(']');
3593 writer_->AddCharacter('}'); 3624 writer_->AddCharacter('}');
3594 writer_->Finalize(); 3625 writer_->Finalize();
3595 } 3626 }
3596 3627
(...skipping 26 matching lines...) Expand all
3623 int result = buffer_pos; 3654 int result = buffer_pos;
3624 do { 3655 do {
3625 int last_digit = value % 10; 3656 int last_digit = value % 10;
3626 buffer[--buffer_pos] = '0' + last_digit; 3657 buffer[--buffer_pos] = '0' + last_digit;
3627 value /= 10; 3658 value /= 10;
3628 } while (value); 3659 } while (value);
3629 return result; 3660 return result;
3630 } 3661 }
3631 3662
3632 3663
3633 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { 3664 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
3665 bool first_edge) {
3634 // The buffer needs space for 3 ints, 3 commas and \0 3666 // The buffer needs space for 3 ints, 3 commas and \0
3635 static const int kBufferSize = 3667 static const int kBufferSize =
3636 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT 3668 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
3637 EmbeddedVector<char, kBufferSize> buffer; 3669 EmbeddedVector<char, kBufferSize> buffer;
3638 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 3670 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
3639 || edge->type() == HeapGraphEdge::kHidden 3671 || edge->type() == HeapGraphEdge::kHidden
3640 || edge->type() == HeapGraphEdge::kWeak 3672 || edge->type() == HeapGraphEdge::kWeak
3641 ? edge->index() : GetStringId(edge->name()); 3673 ? edge->index() : GetStringId(edge->name());
3642 int buffer_pos = 0; 3674 int buffer_pos = 0;
3643 buffer[buffer_pos++] = ','; 3675 if (!first_edge) {
3676 buffer[buffer_pos++] = ',';
3677 }
3644 buffer_pos = itoa(edge->type(), buffer, buffer_pos); 3678 buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3645 buffer[buffer_pos++] = ','; 3679 buffer[buffer_pos++] = ',';
3646 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); 3680 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3647 buffer[buffer_pos++] = ','; 3681 buffer[buffer_pos++] = ',';
3648 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); 3682 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
3649 buffer[buffer_pos++] = '\0'; 3683 buffer[buffer_pos++] = '\0';
3650 writer_->AddString(buffer.start()); 3684 writer_->AddString(buffer.start());
3651 } 3685 }
3652 3686
3653 3687
3654 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 3688 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
3689 bool first_edge = true;
3690 for (int i = 0; i < nodes.length(); ++i) {
3691 HeapEntry* entry = nodes[i];
3692 Vector<HeapGraphEdge> children = entry->children();
3693 for (int j = 0; j < children.length(); ++j) {
3694 SerializeEdge(&children[j], first_edge);
3695 first_edge = false;
3696 if (writer_->aborted()) return;
3697 }
3698 }
3699 }
3700
3701
3702 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
3703 int edges_index) {
3655 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 3704 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3656 static const int kBufferSize = 3705 static const int kBufferSize =
3657 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT 3706 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3658 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT 3707 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3659 + 7 + 1 + 1; 3708 + 7 + 1 + 1;
3660 EmbeddedVector<char, kBufferSize> buffer; 3709 EmbeddedVector<char, kBufferSize> buffer;
3661 Vector<HeapGraphEdge> children = entry->children();
3662 int buffer_pos = 0; 3710 int buffer_pos = 0;
3663 buffer[buffer_pos++] = '\n'; 3711 buffer[buffer_pos++] = '\n';
3664 buffer[buffer_pos++] = ','; 3712 if (entry->entry_index() != 0) {
3713 buffer[buffer_pos++] = ',';
3714 }
3665 buffer_pos = itoa(entry->type(), buffer, buffer_pos); 3715 buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3666 buffer[buffer_pos++] = ','; 3716 buffer[buffer_pos++] = ',';
3667 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); 3717 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3668 buffer[buffer_pos++] = ','; 3718 buffer[buffer_pos++] = ',';
3669 buffer_pos = itoa(entry->id(), buffer, buffer_pos); 3719 buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3670 buffer[buffer_pos++] = ','; 3720 buffer[buffer_pos++] = ',';
3671 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); 3721 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3672 buffer[buffer_pos++] = ','; 3722 buffer[buffer_pos++] = ',';
3673 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); 3723 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3674 buffer[buffer_pos++] = ','; 3724 buffer[buffer_pos++] = ',';
3675 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); 3725 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
3676 buffer[buffer_pos++] = ','; 3726 buffer[buffer_pos++] = ',';
3677 buffer_pos = itoa(children.length(), buffer, buffer_pos); 3727 buffer_pos = itoa(edges_index, buffer, buffer_pos);
3678 buffer[buffer_pos++] = '\0'; 3728 buffer[buffer_pos++] = '\0';
3679 writer_->AddString(buffer.start()); 3729 writer_->AddString(buffer.start());
3680 for (int i = 0; i < children.length(); ++i) { 3730 }
3681 SerializeEdge(&children[i]); 3731
3732
3733 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
3734 const int edge_fields_count = 3; // type,name|index,to_node.
3735 int edges_index = 0;
3736 for (int i = 0; i < nodes.length(); ++i) {
3737 HeapEntry* entry = nodes[i];
3738 SerializeNode(entry, edges_index);
3739 edges_index += entry->children().length() * edge_fields_count;
3682 if (writer_->aborted()) return; 3740 if (writer_->aborted()) return;
3683 } 3741 }
3684 } 3742 }
3685
3686
3687 void HeapSnapshotJSONSerializer::SerializeNodes() {
3688 // The first (zero) item of nodes array is an object describing node
3689 // serialization layout. We use a set of macros to improve
3690 // readability.
3691 #define JSON_A(s) "["s"]"
3692 #define JSON_O(s) "{"s"}"
3693 #define JSON_S(s) "\""s"\""
3694 writer_->AddString(JSON_O(
3695 JSON_S("fields") ":" JSON_A(
3696 JSON_S("type")
3697 "," JSON_S("name")
3698 "," JSON_S("id")
3699 "," JSON_S("self_size")
3700 "," JSON_S("retained_size")
3701 "," JSON_S("dominator")
3702 "," JSON_S("children_count")
3703 "," JSON_S("children"))
3704 "," JSON_S("types") ":" JSON_A(
3705 JSON_A(
3706 JSON_S("hidden")
3707 "," JSON_S("array")
3708 "," JSON_S("string")
3709 "," JSON_S("object")
3710 "," JSON_S("code")
3711 "," JSON_S("closure")
3712 "," JSON_S("regexp")
3713 "," JSON_S("number")
3714 "," JSON_S("native")
3715 "," JSON_S("synthetic"))
3716 "," JSON_S("string")
3717 "," JSON_S("number")
3718 "," JSON_S("number")
3719 "," JSON_S("number")
3720 "," JSON_S("number")
3721 "," JSON_S("number")
3722 "," JSON_O(
3723 JSON_S("fields") ":" JSON_A(
3724 JSON_S("type")
3725 "," JSON_S("name_or_index")
3726 "," JSON_S("to_node"))
3727 "," JSON_S("types") ":" JSON_A(
3728 JSON_A(
3729 JSON_S("context")
3730 "," JSON_S("element")
3731 "," JSON_S("property")
3732 "," JSON_S("internal")
3733 "," JSON_S("hidden")
3734 "," JSON_S("shortcut")
3735 "," JSON_S("weak"))
3736 "," JSON_S("string_or_number")
3737 "," JSON_S("node"))))));
3738 #undef JSON_S
3739 #undef JSON_O
3740 #undef JSON_A
3741
3742 const int node_fields_count = 7;
3743 // type,name,id,self_size,retained_size,dominator,children_count.
3744 const int edge_fields_count = 3; // type,name|index,to_node.
3745
3746 List<HeapEntry*>& nodes = *(snapshot_->entries());
3747 // Root must be the first.
3748 ASSERT(nodes.first() == snapshot_->root());
3749 // Rewrite node indexes, so they refer to actual array positions. Do this
3750 // only once.
3751 if (nodes[0]->entry_index() == -1) {
3752 // Nodes start from array index 1.
3753 int index = 1;
3754 for (int i = 0; i < nodes.length(); ++i) {
3755 HeapEntry* node = nodes[i];
3756 node->set_entry_index(index);
3757 index += node_fields_count +
3758 node->children().length() * edge_fields_count;
3759 }
3760 }
3761
3762 for (int i = 0; i < nodes.length(); ++i) {
3763 SerializeNode(nodes[i]);
3764 if (writer_->aborted()) return;
3765 }
3766 }
3767 3743
3768 3744
3769 void HeapSnapshotJSONSerializer::SerializeSnapshot() { 3745 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3770 writer_->AddString("\"title\":\""); 3746 writer_->AddString("\"title\":\"");
3771 writer_->AddString(snapshot_->title()); 3747 writer_->AddString(snapshot_->title());
3772 writer_->AddString("\""); 3748 writer_->AddString("\"");
3773 writer_->AddString(",\"uid\":"); 3749 writer_->AddString(",\"uid\":");
3774 writer_->AddNumber(snapshot_->uid()); 3750 writer_->AddNumber(snapshot_->uid());
3751 writer_->AddString(",\"meta\":");
3752 // The object describing node serialization layout.
3753 // We use a set of macros to improve readability.
3754 #define JSON_A(s) "["s"]"
3755 #define JSON_O(s) "{"s"}"
3756 #define JSON_S(s) "\""s"\""
3757 writer_->AddString(JSON_O(
3758 JSON_S("node_fields") ":" JSON_A(
3759 JSON_S("type") ","
3760 JSON_S("name") ","
3761 JSON_S("id") ","
3762 JSON_S("self_size") ","
3763 JSON_S("retained_size") ","
3764 JSON_S("dominator") ","
3765 JSON_S("edges_index")) ","
3766 JSON_S("node_types") ":" JSON_A(
3767 JSON_A(
3768 JSON_S("hidden") ","
3769 JSON_S("array") ","
3770 JSON_S("string") ","
3771 JSON_S("object") ","
3772 JSON_S("code") ","
3773 JSON_S("closure") ","
3774 JSON_S("regexp") ","
3775 JSON_S("number") ","
3776 JSON_S("native") ","
3777 JSON_S("synthetic")) ","
3778 JSON_S("string") ","
3779 JSON_S("number") ","
3780 JSON_S("number") ","
3781 JSON_S("number") ","
3782 JSON_S("number") ","
3783 JSON_S("number")) ","
3784 JSON_S("edge_fields") ":" JSON_A(
3785 JSON_S("type") ","
3786 JSON_S("name_or_index") ","
3787 JSON_S("to_node")) ","
3788 JSON_S("edge_types") ":" JSON_A(
3789 JSON_A(
3790 JSON_S("context") ","
3791 JSON_S("element") ","
3792 JSON_S("property") ","
3793 JSON_S("internal") ","
3794 JSON_S("hidden") ","
3795 JSON_S("shortcut") ","
3796 JSON_S("weak")) ","
3797 JSON_S("string_or_number") ","
3798 JSON_S("node"))));
3799 #undef JSON_S
3800 #undef JSON_O
3801 #undef JSON_A
3802 writer_->AddString(",\"node_count\":");
3803 writer_->AddNumber(snapshot_->entries()->length());
3804 writer_->AddString(",\"edge_count\":");
3805 writer_->AddNumber(snapshot_->number_of_edges());
3775 } 3806 }
3776 3807
3777 3808
3778 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 3809 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
3779 static const char hex_chars[] = "0123456789ABCDEF"; 3810 static const char hex_chars[] = "0123456789ABCDEF";
3780 w->AddString("\\u"); 3811 w->AddString("\\u");
3781 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); 3812 w->AddCharacter(hex_chars[(u >> 12) & 0xf]);
3782 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); 3813 w->AddCharacter(hex_chars[(u >> 8) & 0xf]);
3783 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); 3814 w->AddCharacter(hex_chars[(u >> 4) & 0xf]);
3784 w->AddCharacter(hex_chars[u & 0xf]); 3815 w->AddCharacter(hex_chars[u & 0xf]);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3862 3893
3863 3894
3864 void HeapSnapshotJSONSerializer::SortHashMap( 3895 void HeapSnapshotJSONSerializer::SortHashMap(
3865 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3896 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3866 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3897 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3867 sorted_entries->Add(p); 3898 sorted_entries->Add(p);
3868 sorted_entries->Sort(SortUsingEntryValue); 3899 sorted_entries->Sort(SortUsingEntryValue);
3869 } 3900 }
3870 3901
3871 } } // namespace v8::internal 3902 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698