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

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

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 tag_ = source.tag_; 151 tag_ = source.tag_;
152 name_prefix_ = source.name_prefix_; 152 name_prefix_ = source.name_prefix_;
153 name_ = source.name_; 153 name_ = source.name_;
154 resource_name_ = source.resource_name_; 154 resource_name_ = source.resource_name_;
155 line_number_ = source.line_number_; 155 line_number_ = source.line_number_;
156 } 156 }
157 157
158 158
159 uint32_t CodeEntry::GetCallUid() const { 159 uint32_t CodeEntry::GetCallUid() const {
160 uint32_t hash = ComputeIntegerHash(tag_); 160 uint32_t hash = ComputeIntegerHash(tag_);
161 hash ^= ComputeIntegerHash( 161 if (shared_id_ != 0) {
162 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_))); 162 hash ^= ComputeIntegerHash(
163 hash ^= ComputeIntegerHash( 163 static_cast<uint32_t>(shared_id_));
164 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_))); 164 } else {
165 hash ^= ComputeIntegerHash( 165 hash ^= ComputeIntegerHash(
166 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_))); 166 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)));
167 hash ^= ComputeIntegerHash(line_number_); 167 hash ^= ComputeIntegerHash(
168 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)));
169 hash ^= ComputeIntegerHash(
170 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)));
171 hash ^= ComputeIntegerHash(line_number_);
172 }
168 return hash; 173 return hash;
169 } 174 }
170 175
171 176
172 bool CodeEntry::IsSameAs(CodeEntry* entry) const { 177 bool CodeEntry::IsSameAs(CodeEntry* entry) const {
173 return this == entry 178 return this == entry
174 || (tag_ == entry->tag_ 179 || (tag_ == entry->tag_
175 && name_prefix_ == entry->name_prefix_ 180 && shared_id_ == entry->shared_id_
176 && name_ == entry->name_ 181 && (shared_id_ != 0
177 && resource_name_ == entry->resource_name_ 182 || (name_prefix_ == entry->name_prefix_
178 && line_number_ == entry->line_number_); 183 && name_ == entry->name_
184 && resource_name_ == entry->resource_name_
185 && line_number_ == entry->line_number_)));
179 } 186 }
180 187
181 188
182 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 189 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
183 HashMap::Entry* map_entry = 190 HashMap::Entry* map_entry =
184 children_.Lookup(entry, CodeEntryHash(entry), false); 191 children_.Lookup(entry, CodeEntryHash(entry), false);
185 return map_entry != NULL ? 192 return map_entry != NULL ?
186 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 193 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
187 } 194 }
188 195
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 460
454 461
455 void CpuProfile::Print() { 462 void CpuProfile::Print() {
456 OS::Print("[Top down]:\n"); 463 OS::Print("[Top down]:\n");
457 top_down_.Print(); 464 top_down_.Print();
458 OS::Print("[Bottom up]:\n"); 465 OS::Print("[Bottom up]:\n");
459 bottom_up_.Print(); 466 bottom_up_.Print();
460 } 467 }
461 468
462 469
470 CodeEntry* const CodeMap::kSfiCodeEntry = NULL;
463 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; 471 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
464 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue = 472 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
465 CodeMap::CodeEntryInfo(NULL, 0); 473 CodeMap::CodeEntryInfo(NULL, 0);
466 474
467 475
468 void CodeMap::AddAlias(Address start, CodeEntry* entry, Address code_start) {
469 CodeTree::Locator locator;
470 if (tree_.Find(code_start, &locator)) {
471 const CodeEntryInfo& code_info = locator.value();
472 if (tree_.Insert(start, &locator)) {
473 entry->CopyData(*code_info.entry);
474 locator.set_value(CodeEntryInfo(entry, code_info.size));
475 }
476 }
477 }
478
479
480 CodeEntry* CodeMap::FindEntry(Address addr) { 476 CodeEntry* CodeMap::FindEntry(Address addr) {
481 CodeTree::Locator locator; 477 CodeTree::Locator locator;
482 if (tree_.FindGreatestLessThan(addr, &locator)) { 478 if (tree_.FindGreatestLessThan(addr, &locator)) {
483 // locator.key() <= addr. Need to check that addr is within entry. 479 // locator.key() <= addr. Need to check that addr is within entry.
484 const CodeEntryInfo& entry = locator.value(); 480 const CodeEntryInfo& entry = locator.value();
485 if (addr < (locator.key() + entry.size)) 481 if (addr < (locator.key() + entry.size))
486 return entry.entry; 482 return entry.entry;
487 } 483 }
488 return NULL; 484 return NULL;
489 } 485 }
490 486
491 487
488 int CodeMap::GetSFITag(Address addr) {
489 CodeTree::Locator locator;
490 // For SFI entries, 'size' field is used to store their IDs.
491 if (tree_.Find(addr, &locator)) {
492 const CodeEntryInfo& entry = locator.value();
493 ASSERT(entry.entry == kSfiCodeEntry);
494 return entry.size;
495 } else {
496 tree_.Insert(addr, &locator);
497 int tag = next_sfi_tag_++;
498 locator.set_value(CodeEntryInfo(kSfiCodeEntry, tag));
499 return tag;
500 }
501 }
502
503
492 void CodeMap::CodeTreePrinter::Call( 504 void CodeMap::CodeTreePrinter::Call(
493 const Address& key, const CodeMap::CodeEntryInfo& value) { 505 const Address& key, const CodeMap::CodeEntryInfo& value) {
494 OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); 506 OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
495 } 507 }
496 508
497 509
498 void CodeMap::Print() { 510 void CodeMap::Print() {
499 CodeTreePrinter printer; 511 CodeTreePrinter printer;
500 tree_.ForEach(&printer); 512 tree_.ForEach(&printer);
501 } 513 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 "args_count: ", 722 "args_count: ",
711 GetName(args_count), 723 GetName(args_count),
712 "", 724 "",
713 v8::CpuProfileNode::kNoLineNumberInfo, 725 v8::CpuProfileNode::kNoLineNumberInfo,
714 TokenEnumerator::kInheritsSecurityToken); 726 TokenEnumerator::kInheritsSecurityToken);
715 code_entries_.Add(entry); 727 code_entries_.Add(entry);
716 return entry; 728 return entry;
717 } 729 }
718 730
719 731
720 CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
721 CodeEntry* entry = new CodeEntry(security_token_id);
722 code_entries_.Add(entry);
723 return entry;
724 }
725
726
727 void CpuProfilesCollection::AddPathToCurrentProfiles( 732 void CpuProfilesCollection::AddPathToCurrentProfiles(
728 const Vector<CodeEntry*>& path) { 733 const Vector<CodeEntry*>& path) {
729 // As starting / stopping profiles is rare relatively to this 734 // As starting / stopping profiles is rare relatively to this
730 // method, we don't bother minimizing the duration of lock holding, 735 // method, we don't bother minimizing the duration of lock holding,
731 // e.g. copying contents of the list to a local vector. 736 // e.g. copying contents of the list to a local vector.
732 current_profiles_semaphore_->Wait(); 737 current_profiles_semaphore_->Wait();
733 for (int i = 0; i < current_profiles_.length(); ++i) { 738 for (int i = 0; i < current_profiles_.length(); ++i) {
734 current_profiles_[i]->AddPath(path); 739 current_profiles_[i]->AddPath(path);
735 } 740 }
736 current_profiles_semaphore_->Signal(); 741 current_profiles_semaphore_->Signal();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 786 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
782 // Allocate space for stack frames + pc + function + vm-state. 787 // Allocate space for stack frames + pc + function + vm-state.
783 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); 788 ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
784 // As actual number of decoded code entries may vary, initialize 789 // As actual number of decoded code entries may vary, initialize
785 // entries vector with NULL values. 790 // entries vector with NULL values.
786 CodeEntry** entry = entries.start(); 791 CodeEntry** entry = entries.start();
787 memset(entry, 0, entries.length() * sizeof(*entry)); 792 memset(entry, 0, entries.length() * sizeof(*entry));
788 if (sample.pc != NULL) { 793 if (sample.pc != NULL) {
789 *entry++ = code_map_.FindEntry(sample.pc); 794 *entry++ = code_map_.FindEntry(sample.pc);
790 795
791 if (sample.function != NULL) { 796 if (sample.tos != NULL) {
792 *entry = code_map_.FindEntry(sample.function); 797 *entry = code_map_.FindEntry(sample.tos);
793 if (*entry != NULL && !(*entry)->is_js_function()) { 798 if (*entry != NULL && !(*entry)->is_js_function()) {
794 *entry = NULL; 799 *entry = NULL;
795 } else {
796 CodeEntry* pc_entry = *entries.start();
797 if (pc_entry == NULL) {
798 *entry = NULL;
799 } else if (pc_entry->is_js_function()) {
800 // Use function entry in favor of pc entry, as function
801 // entry has security token.
802 *entries.start() = NULL;
803 }
804 } 800 }
805 entry++; 801 entry++;
806 } 802 }
807 803
808 for (const Address *stack_pos = sample.stack, 804 for (const Address *stack_pos = sample.stack,
809 *stack_end = stack_pos + sample.frames_count; 805 *stack_end = stack_pos + sample.frames_count;
810 stack_pos != stack_end; 806 stack_pos != stack_end;
811 ++stack_pos) { 807 ++stack_pos) {
812 *entry++ = code_map_.FindEntry(*stack_pos); 808 *entry++ = code_map_.FindEntry(*stack_pos);
813 } 809 }
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 break; 1174 break;
1179 default: 1175 default:
1180 OS::Print("!!! unknown edge type: %d ", edge->type()); 1176 OS::Print("!!! unknown edge type: %d ", edge->type());
1181 } 1177 }
1182 edge->to()->Print(1, 0); 1178 edge->to()->Print(1, 0);
1183 } 1179 }
1184 OS::Print("\n"); 1180 OS::Print("\n");
1185 } 1181 }
1186 1182
1187 1183
1188 HeapObject *const HeapSnapshot::kInternalRootObject =
1189 reinterpret_cast<HeapObject*>(1);
1190 HeapObject *const HeapSnapshot::kGcRootsObject =
1191 reinterpret_cast<HeapObject*>(2);
1192
1193
1194 // It is very important to keep objects that form a heap snapshot 1184 // It is very important to keep objects that form a heap snapshot
1195 // as small as possible. 1185 // as small as possible.
1196 namespace { // Avoid littering the global namespace. 1186 namespace { // Avoid littering the global namespace.
1197 1187
1198 template <size_t ptr_size> struct SnapshotSizeConstants; 1188 template <size_t ptr_size> struct SnapshotSizeConstants;
1199 1189
1200 template <> struct SnapshotSizeConstants<4> { 1190 template <> struct SnapshotSizeConstants<4> {
1201 static const int kExpectedHeapGraphEdgeSize = 12; 1191 static const int kExpectedHeapGraphEdgeSize = 12;
1202 static const int kExpectedHeapEntrySize = 36; 1192 static const int kExpectedHeapEntrySize = 36;
1203 }; 1193 };
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 ASSERT(raw_entries_ == NULL); 1244 ASSERT(raw_entries_ == NULL);
1255 raw_entries_ = NewArray<char>( 1245 raw_entries_ = NewArray<char>(
1256 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); 1246 HeapEntry::EntriesSize(entries_count, children_count, retainers_count));
1257 #ifdef DEBUG 1247 #ifdef DEBUG
1258 raw_entries_size_ = 1248 raw_entries_size_ =
1259 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1249 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1260 #endif 1250 #endif
1261 } 1251 }
1262 1252
1263 1253
1264 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1265 int children_count,
1266 int retainers_count) {
1267 if (object == kInternalRootObject) {
1268 ASSERT(root_entry_ == NULL);
1269 ASSERT(retainers_count == 0);
1270 return (root_entry_ = AddEntry(HeapEntry::kObject,
1271 "",
1272 HeapObjectsMap::kInternalRootObjectId,
1273 0,
1274 children_count,
1275 retainers_count));
1276 } else if (object == kGcRootsObject) {
1277 ASSERT(gc_roots_entry_ == NULL);
1278 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1279 "(GC roots)",
1280 HeapObjectsMap::kGcRootsObjectId,
1281 0,
1282 children_count,
1283 retainers_count));
1284 } else if (object->IsJSFunction()) {
1285 JSFunction* func = JSFunction::cast(object);
1286 SharedFunctionInfo* shared = func->shared();
1287 return AddEntry(object,
1288 HeapEntry::kClosure,
1289 collection_->GetName(String::cast(shared->name())),
1290 children_count,
1291 retainers_count);
1292 } else if (object->IsJSRegExp()) {
1293 JSRegExp* re = JSRegExp::cast(object);
1294 return AddEntry(object,
1295 HeapEntry::kRegExp,
1296 collection_->GetName(re->Pattern()),
1297 children_count,
1298 retainers_count);
1299 } else if (object->IsJSObject()) {
1300 return AddEntry(object,
1301 HeapEntry::kObject,
1302 collection_->GetName(GetConstructorNameForHeapProfile(
1303 JSObject::cast(object))),
1304 children_count,
1305 retainers_count);
1306 } else if (object->IsString()) {
1307 return AddEntry(object,
1308 HeapEntry::kString,
1309 collection_->GetName(String::cast(object)),
1310 children_count,
1311 retainers_count);
1312 } else if (object->IsCode()) {
1313 return AddEntry(object,
1314 HeapEntry::kCode,
1315 "",
1316 children_count,
1317 retainers_count);
1318 } else if (object->IsSharedFunctionInfo()) {
1319 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1320 return AddEntry(object,
1321 HeapEntry::kCode,
1322 collection_->GetName(String::cast(shared->name())),
1323 children_count,
1324 retainers_count);
1325 } else if (object->IsScript()) {
1326 Script* script = Script::cast(object);
1327 return AddEntry(object,
1328 HeapEntry::kCode,
1329 script->name()->IsString() ?
1330 collection_->GetName(String::cast(script->name())) : "",
1331 children_count,
1332 retainers_count);
1333 } else if (object->IsFixedArray()) {
1334 return AddEntry(object,
1335 HeapEntry::kArray,
1336 "",
1337 children_count,
1338 retainers_count);
1339 } else if (object->IsHeapNumber()) {
1340 return AddEntry(object,
1341 HeapEntry::kHeapNumber,
1342 "number",
1343 children_count,
1344 retainers_count);
1345 }
1346 return AddEntry(object,
1347 HeapEntry::kHidden,
1348 "system",
1349 children_count,
1350 retainers_count);
1351 }
1352
1353
1354 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1254 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1355 (*entry_ptr)->clear_paint(); 1255 (*entry_ptr)->clear_paint();
1356 } 1256 }
1357 1257
1358 void HeapSnapshot::ClearPaint() { 1258 void HeapSnapshot::ClearPaint() {
1359 entries_.Iterate(HeapEntryClearPaint); 1259 entries_.Iterate(HeapEntryClearPaint);
1360 } 1260 }
1361 1261
1362 1262
1363 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, 1263 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1364 HeapEntry::Type type, 1264 ASSERT(root_entry_ == NULL);
1365 const char* name, 1265 return (root_entry_ = AddEntry(HeapEntry::kObject,
1366 int children_count, 1266 "",
1367 int retainers_count) { 1267 HeapObjectsMap::kInternalRootObjectId,
1368 return AddEntry(type, 1268 0,
1369 name, 1269 children_count,
1370 collection_->GetObjectId(object->address()), 1270 0));
1371 object->Size(), 1271 }
1372 children_count, 1272
1373 retainers_count); 1273
1274 HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
1275 int retainers_count) {
1276 ASSERT(gc_roots_entry_ == NULL);
1277 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1278 "(GC roots)",
1279 HeapObjectsMap::kGcRootsObjectId,
1280 0,
1281 children_count,
1282 retainers_count));
1374 } 1283 }
1375 1284
1376 1285
1377 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 1286 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1378 const char* name, 1287 const char* name,
1379 uint64_t id, 1288 uint64_t id,
1380 int size, 1289 int size,
1381 int children_count, 1290 int children_count,
1382 int retainers_count) { 1291 int retainers_count) {
1383 HeapEntry* entry = GetNextEntryToInit(); 1292 HeapEntry* entry = GetNextEntryToInit();
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 HeapSnapshot* snapshot1, 1525 HeapSnapshot* snapshot1,
1617 HeapSnapshot* snapshot2) { 1526 HeapSnapshot* snapshot2) {
1618 return comparator_.Compare(snapshot1, snapshot2); 1527 return comparator_.Compare(snapshot1, snapshot2);
1619 } 1528 }
1620 1529
1621 1530
1622 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = 1531 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
1623 reinterpret_cast<HeapEntry*>(1); 1532 reinterpret_cast<HeapEntry*>(1);
1624 1533
1625 HeapEntriesMap::HeapEntriesMap() 1534 HeapEntriesMap::HeapEntriesMap()
1626 : entries_(HeapObjectsMatch), 1535 : entries_(HeapThingsMatch),
1627 entries_count_(0), 1536 entries_count_(0),
1628 total_children_count_(0), 1537 total_children_count_(0),
1629 total_retainers_count_(0) { 1538 total_retainers_count_(0) {
1630 } 1539 }
1631 1540
1632 1541
1633 HeapEntriesMap::~HeapEntriesMap() { 1542 HeapEntriesMap::~HeapEntriesMap() {
1634 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { 1543 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
1635 delete reinterpret_cast<EntryInfo*>(p->value); 1544 delete reinterpret_cast<EntryInfo*>(p->value);
1636 } 1545 }
1637 } 1546 }
1638 1547
1639 1548
1640 HeapEntry* HeapEntriesMap::Map(HeapObject* object) { 1549 void HeapEntriesMap::AllocateEntries() {
1641 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); 1550 for (HashMap::Entry* p = entries_.Start();
1551 p != NULL;
1552 p = entries_.Next(p)) {
1553 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1554 entry_info->entry = entry_info->allocator->AllocateEntry(
1555 p->key,
1556 entry_info->children_count,
1557 entry_info->retainers_count);
1558 entry_info->children_count = 0;
1559 entry_info->retainers_count = 0;
1560 }
1561 }
1562
1563
1564 HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1565 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1642 if (cache_entry != NULL) { 1566 if (cache_entry != NULL) {
1643 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); 1567 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1644 return entry_info->entry; 1568 return entry_info->entry;
1645 } else { 1569 } else {
1646 return NULL; 1570 return NULL;
1647 } 1571 }
1648 } 1572 }
1649 1573
1650 1574
1651 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) { 1575 void HeapEntriesMap::Pair(
1652 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true); 1576 HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
1577 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1653 ASSERT(cache_entry->value == NULL); 1578 ASSERT(cache_entry->value == NULL);
1654 cache_entry->value = new EntryInfo(entry); 1579 cache_entry->value = new EntryInfo(entry, allocator);
1655 ++entries_count_; 1580 ++entries_count_;
1656 } 1581 }
1657 1582
1658 1583
1659 void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, 1584 void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
1660 int* prev_children_count, 1585 int* prev_children_count,
1661 int* prev_retainers_count) { 1586 int* prev_retainers_count) {
1662 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false); 1587 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
1663 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); 1588 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1664 ASSERT(from_cache_entry != NULL); 1589 ASSERT(from_cache_entry != NULL);
1665 ASSERT(to_cache_entry != NULL); 1590 ASSERT(to_cache_entry != NULL);
1666 EntryInfo* from_entry_info = 1591 EntryInfo* from_entry_info =
1667 reinterpret_cast<EntryInfo*>(from_cache_entry->value); 1592 reinterpret_cast<EntryInfo*>(from_cache_entry->value);
1668 EntryInfo* to_entry_info = 1593 EntryInfo* to_entry_info =
1669 reinterpret_cast<EntryInfo*>(to_cache_entry->value); 1594 reinterpret_cast<EntryInfo*>(to_cache_entry->value);
1670 if (prev_children_count) 1595 if (prev_children_count)
1671 *prev_children_count = from_entry_info->children_count; 1596 *prev_children_count = from_entry_info->children_count;
1672 if (prev_retainers_count) 1597 if (prev_retainers_count)
1673 *prev_retainers_count = to_entry_info->retainers_count; 1598 *prev_retainers_count = to_entry_info->retainers_count;
1674 ++from_entry_info->children_count; 1599 ++from_entry_info->children_count;
1675 ++to_entry_info->retainers_count; 1600 ++to_entry_info->retainers_count;
1676 ++total_children_count_; 1601 ++total_children_count_;
1677 ++total_retainers_count_; 1602 ++total_retainers_count_;
1678 } 1603 }
1679 1604
1680 1605
1681 HeapObjectsSet::HeapObjectsSet() 1606 HeapObjectsSet::HeapObjectsSet()
1682 : entries_(HeapEntriesMap::HeapObjectsMatch) { 1607 : entries_(HeapEntriesMap::HeapThingsMatch) {
1683 } 1608 }
1684 1609
1685 1610
1686 void HeapObjectsSet::Clear() { 1611 void HeapObjectsSet::Clear() {
1687 entries_.Clear(); 1612 entries_.Clear();
1688 } 1613 }
1689 1614
1690 1615
1691 bool HeapObjectsSet::Contains(Object* obj) { 1616 bool HeapObjectsSet::Contains(Object* obj) {
1692 if (!obj->IsHeapObject()) return false; 1617 if (!obj->IsHeapObject()) return false;
1693 HeapObject* object = HeapObject::cast(obj); 1618 HeapObject* object = HeapObject::cast(obj);
1694 HashMap::Entry* cache_entry = 1619 HashMap::Entry* cache_entry =
1695 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); 1620 entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1696 return cache_entry != NULL; 1621 return cache_entry != NULL;
1697 } 1622 }
1698 1623
1699 1624
1700 void HeapObjectsSet::Insert(Object* obj) { 1625 void HeapObjectsSet::Insert(Object* obj) {
1701 if (!obj->IsHeapObject()) return; 1626 if (!obj->IsHeapObject()) return;
1702 HeapObject* object = HeapObject::cast(obj); 1627 HeapObject* object = HeapObject::cast(obj);
1703 HashMap::Entry* cache_entry = 1628 HashMap::Entry* cache_entry =
1704 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); 1629 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1705 if (cache_entry->value == NULL) { 1630 if (cache_entry->value == NULL) {
1706 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; 1631 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
1707 } 1632 }
1708 } 1633 }
1709 1634
1710 1635
1711 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, 1636 HeapObject *const V8HeapExplorer::kInternalRootObject =
1712 v8::ActivityControl* control) 1637 reinterpret_cast<HeapObject*>(1);
1638 HeapObject *const V8HeapExplorer::kGcRootsObject =
1639 reinterpret_cast<HeapObject*>(2);
1640
1641
1642 V8HeapExplorer::V8HeapExplorer(
1643 HeapSnapshot* snapshot,
1644 SnapshottingProgressReportingInterface* progress)
1713 : snapshot_(snapshot), 1645 : snapshot_(snapshot),
1714 control_(control), 1646 collection_(snapshot_->collection()),
1715 collection_(snapshot->collection()), 1647 progress_(progress),
1716 filler_(NULL) { 1648 filler_(NULL) {
1717 } 1649 }
1718 1650
1719 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface {
1720 public:
1721 explicit SnapshotCounter(HeapEntriesMap* entries)
1722 : entries_(entries) { }
1723 HeapEntry* AddEntry(HeapObject* obj) {
1724 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder);
1725 return HeapEntriesMap::kHeapEntryPlaceholder;
1726 }
1727 void SetIndexedReference(HeapGraphEdge::Type,
1728 HeapObject* parent_obj,
1729 HeapEntry*,
1730 int,
1731 Object* child_obj,
1732 HeapEntry*) {
1733 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1734 }
1735 void SetNamedReference(HeapGraphEdge::Type,
1736 HeapObject* parent_obj,
1737 HeapEntry*,
1738 const char*,
1739 Object* child_obj,
1740 HeapEntry*) {
1741 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1742 }
1743 void SetRootShortcutReference(Object* child_obj, HeapEntry*) {
1744 entries_->CountReference(
1745 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
1746 }
1747 void SetRootGcRootsReference() {
1748 entries_->CountReference(
1749 HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject);
1750 }
1751 void SetStrongRootReference(Object* child_obj, HeapEntry*) {
1752 entries_->CountReference(
1753 HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj));
1754 }
1755 private:
1756 HeapEntriesMap* entries_;
1757 };
1758 1651
1759 1652 V8HeapExplorer::~V8HeapExplorer() {
1760 class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
1761 public:
1762 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
1763 : snapshot_(snapshot),
1764 collection_(snapshot->collection()),
1765 entries_(entries) { }
1766 HeapEntry* AddEntry(HeapObject* obj) {
1767 UNREACHABLE();
1768 return NULL;
1769 }
1770 void SetIndexedReference(HeapGraphEdge::Type type,
1771 HeapObject* parent_obj,
1772 HeapEntry* parent_entry,
1773 int index,
1774 Object* child_obj,
1775 HeapEntry* child_entry) {
1776 int child_index, retainer_index;
1777 entries_->CountReference(parent_obj,
1778 HeapObject::cast(child_obj),
1779 &child_index,
1780 &retainer_index);
1781 parent_entry->SetIndexedReference(
1782 type, child_index, index, child_entry, retainer_index);
1783 }
1784 void SetNamedReference(HeapGraphEdge::Type type,
1785 HeapObject* parent_obj,
1786 HeapEntry* parent_entry,
1787 const char* reference_name,
1788 Object* child_obj,
1789 HeapEntry* child_entry) {
1790 int child_index, retainer_index;
1791 entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
1792 &child_index, &retainer_index);
1793 parent_entry->SetNamedReference(type,
1794 child_index,
1795 reference_name,
1796 child_entry,
1797 retainer_index);
1798 }
1799 void SetRootGcRootsReference() {
1800 int child_index, retainer_index;
1801 entries_->CountReference(HeapSnapshot::kInternalRootObject,
1802 HeapSnapshot::kGcRootsObject,
1803 &child_index,
1804 &retainer_index);
1805 snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement,
1806 child_index,
1807 child_index + 1,
1808 snapshot_->gc_roots(),
1809 retainer_index);
1810 }
1811 void SetRootShortcutReference(Object* child_obj,
1812 HeapEntry* child_entry) {
1813 int child_index, retainer_index;
1814 entries_->CountReference(HeapSnapshot::kInternalRootObject,
1815 HeapObject::cast(child_obj),
1816 &child_index,
1817 &retainer_index);
1818 snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut,
1819 child_index,
1820 collection_->GetName(child_index + 1),
1821 child_entry,
1822 retainer_index);
1823 }
1824 void SetStrongRootReference(Object* child_obj,
1825 HeapEntry* child_entry) {
1826 int child_index, retainer_index;
1827 entries_->CountReference(HeapSnapshot::kGcRootsObject,
1828 HeapObject::cast(child_obj),
1829 &child_index,
1830 &retainer_index);
1831 snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement,
1832 child_index,
1833 child_index + 1,
1834 child_entry,
1835 retainer_index);
1836 }
1837 private:
1838 HeapSnapshot* snapshot_;
1839 HeapSnapshotsCollection* collection_;
1840 HeapEntriesMap* entries_;
1841 };
1842
1843 class SnapshotAllocator {
1844 public:
1845 explicit SnapshotAllocator(HeapSnapshot* snapshot)
1846 : snapshot_(snapshot) { }
1847 HeapEntry* GetEntry(
1848 HeapObject* obj, int children_count, int retainers_count) {
1849 HeapEntry* entry =
1850 snapshot_->AddEntry(obj, children_count, retainers_count);
1851 ASSERT(entry != NULL);
1852 return entry;
1853 }
1854 private:
1855 HeapSnapshot* snapshot_;
1856 };
1857
1858 class RootsReferencesExtractor : public ObjectVisitor {
1859 public:
1860 explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator)
1861 : generator_(generator) {
1862 }
1863 void VisitPointers(Object** start, Object** end) {
1864 for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p);
1865 }
1866 private:
1867 HeapSnapshotGenerator* generator_;
1868 };
1869
1870
1871 bool HeapSnapshotGenerator::GenerateSnapshot() {
1872 AssertNoAllocation no_alloc;
1873
1874 SetProgressTotal(4); // 2 passes + dominators + sizes.
1875
1876 // Pass 1. Iterate heap contents to count entries and references.
1877 if (!CountEntriesAndReferences()) return false;
1878
1879 // Allocate and fill entries in the snapshot, allocate references.
1880 snapshot_->AllocateEntries(entries_.entries_count(),
1881 entries_.total_children_count(),
1882 entries_.total_retainers_count());
1883 SnapshotAllocator allocator(snapshot_);
1884 entries_.UpdateEntries(&allocator);
1885
1886 // Pass 2. Fill references.
1887 if (!FillReferences()) return false;
1888
1889 if (!SetEntriesDominators()) return false;
1890 if (!ApproximateRetainedSizes()) return false;
1891
1892 progress_counter_ = progress_total_;
1893 if (!ReportProgress(true)) return false;
1894 return true;
1895 } 1653 }
1896 1654
1897 1655
1898 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { 1656 HeapEntry* V8HeapExplorer::AllocateEntry(
1899 if (!obj->IsHeapObject()) return NULL; 1657 HeapThing ptr, int children_count, int retainers_count) {
1900 HeapObject* object = HeapObject::cast(obj); 1658 return AddEntry(
1901 HeapEntry* entry = entries_.Map(object); 1659 reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
1902 // A new entry. 1660 }
1903 if (entry == NULL) entry = filler_->AddEntry(object); 1661
1904 return entry; 1662
1663 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1664 int children_count,
1665 int retainers_count) {
1666 if (object == kInternalRootObject) {
1667 ASSERT(retainers_count == 0);
1668 return snapshot_->AddRootEntry(children_count);
1669 } else if (object == kGcRootsObject) {
1670 return snapshot_->AddGcRootsEntry(children_count, retainers_count);
1671 } else if (object->IsJSFunction()) {
1672 JSFunction* func = JSFunction::cast(object);
1673 SharedFunctionInfo* shared = func->shared();
1674 return AddEntry(object,
1675 HeapEntry::kClosure,
1676 collection_->GetName(String::cast(shared->name())),
1677 children_count,
1678 retainers_count);
1679 } else if (object->IsJSRegExp()) {
1680 JSRegExp* re = JSRegExp::cast(object);
1681 return AddEntry(object,
1682 HeapEntry::kRegExp,
1683 collection_->GetName(re->Pattern()),
1684 children_count,
1685 retainers_count);
1686 } else if (object->IsJSObject()) {
1687 return AddEntry(object,
1688 HeapEntry::kObject,
1689 collection_->GetName(GetConstructorNameForHeapProfile(
1690 JSObject::cast(object))),
1691 children_count,
1692 retainers_count);
1693 } else if (object->IsString()) {
1694 return AddEntry(object,
1695 HeapEntry::kString,
1696 collection_->GetName(String::cast(object)),
1697 children_count,
1698 retainers_count);
1699 } else if (object->IsCode()) {
1700 return AddEntry(object,
1701 HeapEntry::kCode,
1702 "",
1703 children_count,
1704 retainers_count);
1705 } else if (object->IsSharedFunctionInfo()) {
1706 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1707 return AddEntry(object,
1708 HeapEntry::kCode,
1709 collection_->GetName(String::cast(shared->name())),
1710 children_count,
1711 retainers_count);
1712 } else if (object->IsScript()) {
1713 Script* script = Script::cast(object);
1714 return AddEntry(object,
1715 HeapEntry::kCode,
1716 script->name()->IsString() ?
1717 collection_->GetName(String::cast(script->name())) : "",
1718 children_count,
1719 retainers_count);
1720 } else if (object->IsFixedArray()) {
1721 return AddEntry(object,
1722 HeapEntry::kArray,
1723 "",
1724 children_count,
1725 retainers_count);
1726 } else if (object->IsHeapNumber()) {
1727 return AddEntry(object,
1728 HeapEntry::kHeapNumber,
1729 "number",
1730 children_count,
1731 retainers_count);
1732 }
1733 return AddEntry(object,
1734 HeapEntry::kHidden,
1735 "system",
1736 children_count,
1737 retainers_count);
1738 }
1739
1740
1741 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1742 HeapEntry::Type type,
1743 const char* name,
1744 int children_count,
1745 int retainers_count) {
1746 return snapshot_->AddEntry(type,
1747 name,
1748 collection_->GetObjectId(object->address()),
1749 object->Size(),
1750 children_count,
1751 retainers_count);
1752 }
1753
1754
1755 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
1756 filler->AddEntry(kInternalRootObject);
1757 filler->AddEntry(kGcRootsObject);
1758 }
1759
1760
1761 int V8HeapExplorer::EstimateObjectsCount() {
1762 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1763 int objects_count = 0;
1764 for (HeapObject* obj = iterator.next();
1765 obj != NULL;
1766 obj = iterator.next(), ++objects_count) {}
1767 return objects_count;
1905 } 1768 }
1906 1769
1907 1770
1908 class IndexedReferencesExtractor : public ObjectVisitor { 1771 class IndexedReferencesExtractor : public ObjectVisitor {
1909 public: 1772 public:
1910 IndexedReferencesExtractor(HeapSnapshotGenerator* generator, 1773 IndexedReferencesExtractor(V8HeapExplorer* generator,
1911 HeapObject* parent_obj, 1774 HeapObject* parent_obj,
1912 HeapEntry* parent_entry, 1775 HeapEntry* parent_entry,
1913 HeapObjectsSet* known_references = NULL) 1776 HeapObjectsSet* known_references = NULL)
1914 : generator_(generator), 1777 : generator_(generator),
1915 parent_obj_(parent_obj), 1778 parent_obj_(parent_obj),
1916 parent_(parent_entry), 1779 parent_(parent_entry),
1917 known_references_(known_references), 1780 known_references_(known_references),
1918 next_index_(1) { 1781 next_index_(1) {
1919 } 1782 }
1920 void VisitPointers(Object** start, Object** end) { 1783 void VisitPointers(Object** start, Object** end) {
1921 for (Object** p = start; p < end; p++) { 1784 for (Object** p = start; p < end; p++) {
1922 if (!known_references_ || !known_references_->Contains(*p)) { 1785 if (!known_references_ || !known_references_->Contains(*p)) {
1923 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); 1786 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
1924 } 1787 }
1925 } 1788 }
1926 } 1789 }
1927 private: 1790 private:
1928 HeapSnapshotGenerator* generator_; 1791 V8HeapExplorer* generator_;
1929 HeapObject* parent_obj_; 1792 HeapObject* parent_obj_;
1930 HeapEntry* parent_; 1793 HeapEntry* parent_;
1931 HeapObjectsSet* known_references_; 1794 HeapObjectsSet* known_references_;
1932 int next_index_; 1795 int next_index_;
1933 }; 1796 };
1934 1797
1935 1798
1936 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { 1799 void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1937 HeapEntry* entry = GetEntry(obj); 1800 HeapEntry* entry = GetEntry(obj);
1938 if (entry == NULL) return; // No interest in this object. 1801 if (entry == NULL) return; // No interest in this object.
1939 1802
1940 known_references_.Clear(); 1803 known_references_.Clear();
1941 if (obj->IsJSGlobalProxy()) { 1804 if (obj->IsJSGlobalProxy()) {
1942 // We need to reference JS global objects from snapshot's root. 1805 // We need to reference JS global objects from snapshot's root.
1943 // We use JSGlobalProxy because this is what embedder (e.g. browser) 1806 // We use JSGlobalProxy because this is what embedder (e.g. browser)
1944 // uses for the global object. 1807 // uses for the global object.
1945 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); 1808 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
1946 SetRootShortcutReference(proxy->map()->prototype()); 1809 SetRootShortcutReference(proxy->map()->prototype());
(...skipping 23 matching lines...) Expand all
1970 SetInternalReference(obj, entry, 1, cs->first()); 1833 SetInternalReference(obj, entry, 1, cs->first());
1971 SetInternalReference(obj, entry, 2, cs->second()); 1834 SetInternalReference(obj, entry, 2, cs->second());
1972 } 1835 }
1973 } else { 1836 } else {
1974 IndexedReferencesExtractor refs_extractor(this, obj, entry); 1837 IndexedReferencesExtractor refs_extractor(this, obj, entry);
1975 obj->Iterate(&refs_extractor); 1838 obj->Iterate(&refs_extractor);
1976 } 1839 }
1977 } 1840 }
1978 1841
1979 1842
1980 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, 1843 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
1981 HeapEntry* entry) { 1844 HeapEntry* entry) {
1982 if (js_obj->IsJSFunction()) { 1845 if (js_obj->IsJSFunction()) {
1983 HandleScope hs; 1846 HandleScope hs;
1984 JSFunction* func = JSFunction::cast(js_obj); 1847 JSFunction* func = JSFunction::cast(js_obj);
1985 Context* context = func->context(); 1848 Context* context = func->context();
1986 ZoneScope zscope(DELETE_ON_EXIT); 1849 ZoneScope zscope(DELETE_ON_EXIT);
1987 SerializedScopeInfo* serialized_scope_info = 1850 SerializedScopeInfo* serialized_scope_info =
1988 context->closure()->shared()->scope_info(); 1851 context->closure()->shared()->scope_info();
1989 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info); 1852 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
1990 int locals_number = zone_scope_info.NumberOfLocals(); 1853 int locals_number = zone_scope_info.NumberOfLocals();
1991 for (int i = 0; i < locals_number; ++i) { 1854 for (int i = 0; i < locals_number; ++i) {
1992 String* local_name = *zone_scope_info.LocalName(i); 1855 String* local_name = *zone_scope_info.LocalName(i);
1993 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL); 1856 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
1994 if (idx >= 0 && idx < context->length()) { 1857 if (idx >= 0 && idx < context->length()) {
1995 SetClosureReference(js_obj, entry, local_name, context->get(idx)); 1858 SetClosureReference(js_obj, entry, local_name, context->get(idx));
1996 } 1859 }
1997 } 1860 }
1998 SetInternalReference(js_obj, entry, "code", func->shared()); 1861 SetInternalReference(js_obj, entry, "code", func->shared());
1999 } 1862 }
2000 } 1863 }
2001 1864
2002 1865
2003 void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, 1866 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
2004 HeapEntry* entry) { 1867 HeapEntry* entry) {
2005 if (js_obj->HasFastProperties()) { 1868 if (js_obj->HasFastProperties()) {
2006 DescriptorArray* descs = js_obj->map()->instance_descriptors(); 1869 DescriptorArray* descs = js_obj->map()->instance_descriptors();
2007 for (int i = 0; i < descs->number_of_descriptors(); i++) { 1870 for (int i = 0; i < descs->number_of_descriptors(); i++) {
2008 switch (descs->GetType(i)) { 1871 switch (descs->GetType(i)) {
2009 case FIELD: { 1872 case FIELD: {
2010 int index = descs->GetFieldIndex(i); 1873 int index = descs->GetFieldIndex(i);
2011 SetPropertyReference( 1874 SetPropertyReference(
2012 js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); 1875 js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index));
2013 break; 1876 break;
2014 } 1877 }
(...skipping 20 matching lines...) Expand all
2035 String::cast(k), 1898 String::cast(k),
2036 JSGlobalPropertyCell::cast( 1899 JSGlobalPropertyCell::cast(
2037 target)->value()); 1900 target)->value());
2038 } 1901 }
2039 } 1902 }
2040 } 1903 }
2041 } 1904 }
2042 } 1905 }
2043 1906
2044 1907
2045 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, 1908 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2046 HeapEntry* entry) { 1909 HeapEntry* entry) {
2047 if (js_obj->HasFastElements()) { 1910 if (js_obj->HasFastElements()) {
2048 FixedArray* elements = FixedArray::cast(js_obj->elements()); 1911 FixedArray* elements = FixedArray::cast(js_obj->elements());
2049 int length = js_obj->IsJSArray() ? 1912 int length = js_obj->IsJSArray() ?
2050 Smi::cast(JSArray::cast(js_obj)->length())->value() : 1913 Smi::cast(JSArray::cast(js_obj)->length())->value() :
2051 elements->length(); 1914 elements->length();
2052 for (int i = 0; i < length; ++i) { 1915 for (int i = 0; i < length; ++i) {
2053 if (!elements->get(i)->IsTheHole()) { 1916 if (!elements->get(i)->IsTheHole()) {
2054 SetElementReference(js_obj, entry, i, elements->get(i)); 1917 SetElementReference(js_obj, entry, i, elements->get(i));
2055 } 1918 }
2056 } 1919 }
2057 } else if (js_obj->HasDictionaryElements()) { 1920 } else if (js_obj->HasDictionaryElements()) {
2058 NumberDictionary* dictionary = js_obj->element_dictionary(); 1921 NumberDictionary* dictionary = js_obj->element_dictionary();
2059 int length = dictionary->Capacity(); 1922 int length = dictionary->Capacity();
2060 for (int i = 0; i < length; ++i) { 1923 for (int i = 0; i < length; ++i) {
2061 Object* k = dictionary->KeyAt(i); 1924 Object* k = dictionary->KeyAt(i);
2062 if (dictionary->IsKey(k)) { 1925 if (dictionary->IsKey(k)) {
2063 ASSERT(k->IsNumber()); 1926 ASSERT(k->IsNumber());
2064 uint32_t index = static_cast<uint32_t>(k->Number()); 1927 uint32_t index = static_cast<uint32_t>(k->Number());
2065 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 1928 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
2066 } 1929 }
2067 } 1930 }
2068 } 1931 }
2069 } 1932 }
2070 1933
2071 1934
2072 void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj, 1935 void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
2073 HeapEntry* entry) { 1936 HeapEntry* entry) {
2074 int length = js_obj->GetInternalFieldCount(); 1937 int length = js_obj->GetInternalFieldCount();
2075 for (int i = 0; i < length; ++i) { 1938 for (int i = 0; i < length; ++i) {
2076 Object* o = js_obj->GetInternalField(i); 1939 Object* o = js_obj->GetInternalField(i);
2077 SetInternalReference(js_obj, entry, i, o); 1940 SetInternalReference(js_obj, entry, i, o);
2078 } 1941 }
2079 } 1942 }
2080 1943
2081 1944
2082 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, 1945 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
2083 HeapEntry* parent_entry, 1946 if (!obj->IsHeapObject()) return NULL;
2084 String* reference_name, 1947 return filler_->FindOrAddEntry(obj);
2085 Object* child_obj) { 1948 }
1949
1950
1951 class RootsReferencesExtractor : public ObjectVisitor {
1952 public:
1953 explicit RootsReferencesExtractor(V8HeapExplorer* explorer)
1954 : explorer_(explorer) {
1955 }
1956 void VisitPointers(Object** start, Object** end) {
1957 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p);
1958 }
1959 private:
1960 V8HeapExplorer* explorer_;
1961 };
1962
1963
1964 bool V8HeapExplorer::IterateAndExtractReferences(
1965 SnapshotFillerInterface* filler) {
1966 filler_ = filler;
1967 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1968 bool interrupted = false;
1969 // Heap iteration with filtering must be finished in any case.
1970 for (HeapObject* obj = iterator.next();
1971 obj != NULL;
1972 obj = iterator.next(), progress_->ProgressStep()) {
1973 if (!interrupted) {
1974 ExtractReferences(obj);
1975 if (!progress_->ProgressReport(false)) interrupted = true;
1976 }
1977 }
1978 if (interrupted) {
1979 filler_ = NULL;
1980 return false;
1981 }
1982 SetRootGcRootsReference();
1983 RootsReferencesExtractor extractor(this);
1984 HEAP->IterateRoots(&extractor, VISIT_ALL);
1985 filler_ = NULL;
1986 return progress_->ProgressReport(false);
1987 }
1988
1989
1990 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
1991 HeapEntry* parent_entry,
1992 String* reference_name,
1993 Object* child_obj) {
2086 HeapEntry* child_entry = GetEntry(child_obj); 1994 HeapEntry* child_entry = GetEntry(child_obj);
2087 if (child_entry != NULL) { 1995 if (child_entry != NULL) {
2088 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, 1996 filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2089 parent_obj, 1997 parent_obj,
2090 parent_entry, 1998 parent_entry,
2091 collection_->GetName(reference_name), 1999 collection_->GetName(reference_name),
2092 child_obj, 2000 child_obj,
2093 child_entry); 2001 child_entry);
2094 known_references_.Insert(child_obj); 2002 known_references_.Insert(child_obj);
2095 } 2003 }
2096 } 2004 }
2097 2005
2098 2006
2099 void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, 2007 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
2100 HeapEntry* parent_entry, 2008 HeapEntry* parent_entry,
2101 int index, 2009 int index,
2102 Object* child_obj) { 2010 Object* child_obj) {
2103 HeapEntry* child_entry = GetEntry(child_obj); 2011 HeapEntry* child_entry = GetEntry(child_obj);
2104 if (child_entry != NULL) { 2012 if (child_entry != NULL) {
2105 filler_->SetIndexedReference(HeapGraphEdge::kElement, 2013 filler_->SetIndexedReference(HeapGraphEdge::kElement,
2106 parent_obj, 2014 parent_obj,
2107 parent_entry, 2015 parent_entry,
2108 index, 2016 index,
2109 child_obj, 2017 child_obj,
2110 child_entry); 2018 child_entry);
2111 known_references_.Insert(child_obj); 2019 known_references_.Insert(child_obj);
2112 } 2020 }
2113 } 2021 }
2114 2022
2115 2023
2116 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, 2024 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2117 HeapEntry* parent_entry, 2025 HeapEntry* parent_entry,
2118 const char* reference_name, 2026 const char* reference_name,
2119 Object* child_obj) { 2027 Object* child_obj) {
2120 HeapEntry* child_entry = GetEntry(child_obj); 2028 HeapEntry* child_entry = GetEntry(child_obj);
2121 if (child_entry != NULL) { 2029 if (child_entry != NULL) {
2122 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2030 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2123 parent_obj, 2031 parent_obj,
2124 parent_entry, 2032 parent_entry,
2125 reference_name, 2033 reference_name,
2126 child_obj, 2034 child_obj,
2127 child_entry); 2035 child_entry);
2128 known_references_.Insert(child_obj); 2036 known_references_.Insert(child_obj);
2129 } 2037 }
2130 } 2038 }
2131 2039
2132 2040
2133 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, 2041 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2134 HeapEntry* parent_entry, 2042 HeapEntry* parent_entry,
2135 int index, 2043 int index,
2136 Object* child_obj) { 2044 Object* child_obj) {
2137 HeapEntry* child_entry = GetEntry(child_obj); 2045 HeapEntry* child_entry = GetEntry(child_obj);
2138 if (child_entry != NULL) { 2046 if (child_entry != NULL) {
2139 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2047 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2140 parent_obj, 2048 parent_obj,
2141 parent_entry, 2049 parent_entry,
2142 collection_->GetName(index), 2050 collection_->GetName(index),
2143 child_obj, 2051 child_obj,
2144 child_entry); 2052 child_entry);
2145 known_references_.Insert(child_obj); 2053 known_references_.Insert(child_obj);
2146 } 2054 }
2147 } 2055 }
2148 2056
2149 2057
2150 void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, 2058 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
2151 HeapEntry* parent_entry, 2059 HeapEntry* parent_entry,
2152 int index, 2060 int index,
2153 Object* child_obj) { 2061 Object* child_obj) {
2154 HeapEntry* child_entry = GetEntry(child_obj); 2062 HeapEntry* child_entry = GetEntry(child_obj);
2155 if (child_entry != NULL) { 2063 if (child_entry != NULL) {
2156 filler_->SetIndexedReference(HeapGraphEdge::kHidden, 2064 filler_->SetIndexedReference(HeapGraphEdge::kHidden,
2157 parent_obj, 2065 parent_obj,
2158 parent_entry, 2066 parent_entry,
2159 index, 2067 index,
2160 child_obj, 2068 child_obj,
2161 child_entry); 2069 child_entry);
2162 } 2070 }
2163 } 2071 }
2164 2072
2165 2073
2166 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, 2074 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2167 HeapEntry* parent_entry, 2075 HeapEntry* parent_entry,
2168 String* reference_name, 2076 String* reference_name,
2169 Object* child_obj) { 2077 Object* child_obj) {
2170 HeapEntry* child_entry = GetEntry(child_obj); 2078 HeapEntry* child_entry = GetEntry(child_obj);
2171 if (child_entry != NULL) { 2079 if (child_entry != NULL) {
2172 HeapGraphEdge::Type type = reference_name->length() > 0 ? 2080 HeapGraphEdge::Type type = reference_name->length() > 0 ?
2173 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; 2081 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
2174 filler_->SetNamedReference(type, 2082 filler_->SetNamedReference(type,
2175 parent_obj, 2083 parent_obj,
2176 parent_entry, 2084 parent_entry,
2177 collection_->GetName(reference_name), 2085 collection_->GetName(reference_name),
2178 child_obj, 2086 child_obj,
2179 child_entry); 2087 child_entry);
2180 known_references_.Insert(child_obj); 2088 known_references_.Insert(child_obj);
2181 } 2089 }
2182 } 2090 }
2183 2091
2184 2092
2185 void HeapSnapshotGenerator::SetPropertyShortcutReference( 2093 void V8HeapExplorer::SetPropertyShortcutReference(
2186 HeapObject* parent_obj, 2094 HeapObject* parent_obj,
2187 HeapEntry* parent_entry, 2095 HeapEntry* parent_entry,
2188 String* reference_name, 2096 String* reference_name,
2189 Object* child_obj) { 2097 Object* child_obj) {
2190 HeapEntry* child_entry = GetEntry(child_obj); 2098 HeapEntry* child_entry = GetEntry(child_obj);
2191 if (child_entry != NULL) { 2099 if (child_entry != NULL) {
2192 filler_->SetNamedReference(HeapGraphEdge::kShortcut, 2100 filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2193 parent_obj, 2101 parent_obj,
2194 parent_entry, 2102 parent_entry,
2195 collection_->GetName(reference_name), 2103 collection_->GetName(reference_name),
2196 child_obj, 2104 child_obj,
2197 child_entry); 2105 child_entry);
2198 } 2106 }
2199 } 2107 }
2200 2108
2201 2109
2202 void HeapSnapshotGenerator::SetRootGcRootsReference() { 2110 void V8HeapExplorer::SetRootGcRootsReference() {
2203 filler_->SetRootGcRootsReference(); 2111 filler_->SetIndexedAutoIndexReference(
2204 } 2112 HeapGraphEdge::kElement,
2205 2113 kInternalRootObject, snapshot_->root(),
2206 2114 kGcRootsObject, snapshot_->gc_roots());
2207 void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) { 2115 }
2116
2117
2118 void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) {
2208 HeapEntry* child_entry = GetEntry(child_obj); 2119 HeapEntry* child_entry = GetEntry(child_obj);
2209 ASSERT(child_entry != NULL); 2120 ASSERT(child_entry != NULL);
2210 filler_->SetRootShortcutReference(child_obj, child_entry); 2121 filler_->SetNamedAutoIndexReference(
2211 } 2122 HeapGraphEdge::kShortcut,
2212 2123 kInternalRootObject, snapshot_->root(),
2213 2124 child_obj, child_entry);
2214 void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { 2125 }
2126
2127
2128 void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
2215 HeapEntry* child_entry = GetEntry(child_obj); 2129 HeapEntry* child_entry = GetEntry(child_obj);
2216 if (child_entry != NULL) { 2130 if (child_entry != NULL) {
2217 filler_->SetStrongRootReference(child_obj, child_entry); 2131 filler_->SetIndexedAutoIndexReference(
2218 } 2132 HeapGraphEdge::kElement,
2133 kGcRootsObject, snapshot_->gc_roots(),
2134 child_obj, child_entry);
2135 }
2136 }
2137
2138
2139 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
2140 v8::ActivityControl* control)
2141 : snapshot_(snapshot),
2142 control_(control),
2143 v8_heap_explorer_(snapshot_, this) {
2144 }
2145
2146
2147 class SnapshotCounter : public SnapshotFillerInterface {
2148 public:
2149 SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries)
2150 : allocator_(allocator), entries_(entries) { }
2151 HeapEntry* AddEntry(HeapThing ptr) {
2152 entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
2153 return HeapEntriesMap::kHeapEntryPlaceholder;
2154 }
2155 HeapEntry* FindOrAddEntry(HeapThing ptr) {
2156 HeapEntry* entry = entries_->Map(ptr);
2157 return entry != NULL ? entry : AddEntry(ptr);
2158 }
2159 void SetIndexedReference(HeapGraphEdge::Type,
2160 HeapThing parent_ptr,
2161 HeapEntry*,
2162 int,
2163 HeapThing child_ptr,
2164 HeapEntry*) {
2165 entries_->CountReference(parent_ptr, child_ptr);
2166 }
2167 void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
2168 HeapThing parent_ptr,
2169 HeapEntry*,
2170 HeapThing child_ptr,
2171 HeapEntry*) {
2172 entries_->CountReference(parent_ptr, child_ptr);
2173 }
2174 void SetNamedReference(HeapGraphEdge::Type,
2175 HeapThing parent_ptr,
2176 HeapEntry*,
2177 const char*,
2178 HeapThing child_ptr,
2179 HeapEntry*) {
2180 entries_->CountReference(parent_ptr, child_ptr);
2181 }
2182 void SetNamedAutoIndexReference(HeapGraphEdge::Type,
2183 HeapThing parent_ptr,
2184 HeapEntry*,
2185 HeapThing child_ptr,
2186 HeapEntry*) {
2187 entries_->CountReference(parent_ptr, child_ptr);
2188 }
2189 private:
2190 HeapEntriesAllocator* allocator_;
2191 HeapEntriesMap* entries_;
2192 };
2193
2194
2195 class SnapshotFiller : public SnapshotFillerInterface {
2196 public:
2197 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
2198 : snapshot_(snapshot),
2199 collection_(snapshot->collection()),
2200 entries_(entries) { }
2201 HeapEntry* AddEntry(HeapThing ptr) {
2202 UNREACHABLE();
2203 return NULL;
2204 }
2205 HeapEntry* FindOrAddEntry(HeapThing ptr) {
2206 HeapEntry* entry = entries_->Map(ptr);
2207 return entry != NULL ? entry : AddEntry(ptr);
2208 }
2209 void SetIndexedReference(HeapGraphEdge::Type type,
2210 HeapThing parent_ptr,
2211 HeapEntry* parent_entry,
2212 int index,
2213 HeapThing child_ptr,
2214 HeapEntry* child_entry) {
2215 int child_index, retainer_index;
2216 entries_->CountReference(
2217 parent_ptr, child_ptr, &child_index, &retainer_index);
2218 parent_entry->SetIndexedReference(
2219 type, child_index, index, child_entry, retainer_index);
2220 }
2221 void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
2222 HeapThing parent_ptr,
2223 HeapEntry* parent_entry,
2224 HeapThing child_ptr,
2225 HeapEntry* child_entry) {
2226 int child_index, retainer_index;
2227 entries_->CountReference(
2228 parent_ptr, child_ptr, &child_index, &retainer_index);
2229 parent_entry->SetIndexedReference(
2230 type, child_index, child_index + 1, child_entry, retainer_index);
2231 }
2232 void SetNamedReference(HeapGraphEdge::Type type,
2233 HeapThing parent_ptr,
2234 HeapEntry* parent_entry,
2235 const char* reference_name,
2236 HeapThing child_ptr,
2237 HeapEntry* child_entry) {
2238 int child_index, retainer_index;
2239 entries_->CountReference(
2240 parent_ptr, child_ptr, &child_index, &retainer_index);
2241 parent_entry->SetNamedReference(
2242 type, child_index, reference_name, child_entry, retainer_index);
2243 }
2244 void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
2245 HeapThing parent_ptr,
2246 HeapEntry* parent_entry,
2247 HeapThing child_ptr,
2248 HeapEntry* child_entry) {
2249 int child_index, retainer_index;
2250 entries_->CountReference(
2251 parent_ptr, child_ptr, &child_index, &retainer_index);
2252 parent_entry->SetNamedReference(type,
2253 child_index,
2254 collection_->GetName(child_index + 1),
2255 child_entry,
2256 retainer_index);
2257 }
2258 private:
2259 HeapSnapshot* snapshot_;
2260 HeapSnapshotsCollection* collection_;
2261 HeapEntriesMap* entries_;
2262 };
2263
2264
2265 bool HeapSnapshotGenerator::GenerateSnapshot() {
2266 AssertNoAllocation no_alloc;
2267
2268 SetProgressTotal(4); // 2 passes + dominators + sizes.
2269
2270 // Pass 1. Iterate heap contents to count entries and references.
2271 if (!CountEntriesAndReferences()) return false;
2272
2273 // Allocate and fill entries in the snapshot, allocate references.
2274 snapshot_->AllocateEntries(entries_.entries_count(),
2275 entries_.total_children_count(),
2276 entries_.total_retainers_count());
2277 entries_.AllocateEntries();
2278
2279 // Pass 2. Fill references.
2280 if (!FillReferences()) return false;
2281
2282 if (!SetEntriesDominators()) return false;
2283 if (!ApproximateRetainedSizes()) return false;
2284
2285 progress_counter_ = progress_total_;
2286 if (!ProgressReport(true)) return false;
2287 return true;
2288 }
2289
2290
2291 void HeapSnapshotGenerator::ProgressStep() {
2292 ++progress_counter_;
2293 }
2294
2295
2296 bool HeapSnapshotGenerator::ProgressReport(bool force) {
2297 const int kProgressReportGranularity = 10000;
2298 if (control_ != NULL
2299 && (force || progress_counter_ % kProgressReportGranularity == 0)) {
2300 return
2301 control_->ReportProgressValue(progress_counter_, progress_total_) ==
2302 v8::ActivityControl::kContinue;
2303 }
2304 return true;
2219 } 2305 }
2220 2306
2221 2307
2222 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 2308 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
2223 if (control_ == NULL) return; 2309 if (control_ == NULL) return;
2224 2310 progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count;
2225 HeapIterator iterator(HeapIterator::kFilterUnreachable);
2226 int objects_count = 0;
2227 for (HeapObject* obj = iterator.next();
2228 obj != NULL;
2229 obj = iterator.next(), ++objects_count) {}
2230 progress_total_ = objects_count * iterations_count;
2231 progress_counter_ = 0; 2311 progress_counter_ = 0;
2232 } 2312 }
2233 2313
2234 2314
2235 bool HeapSnapshotGenerator::CountEntriesAndReferences() { 2315 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
2236 SnapshotCounter counter(&entries_); 2316 SnapshotCounter counter(&v8_heap_explorer_, &entries_);
2237 filler_ = &counter; 2317 v8_heap_explorer_.AddRootEntries(&counter);
2238 filler_->AddEntry(HeapSnapshot::kInternalRootObject); 2318 return v8_heap_explorer_.IterateAndExtractReferences(&counter);
2239 filler_->AddEntry(HeapSnapshot::kGcRootsObject);
2240 return IterateAndExtractReferences();
2241 } 2319 }
2242 2320
2243 2321
2244 bool HeapSnapshotGenerator::FillReferences() { 2322 bool HeapSnapshotGenerator::FillReferences() {
2245 SnapshotFiller filler(snapshot_, &entries_); 2323 SnapshotFiller filler(snapshot_, &entries_);
2246 filler_ = &filler; 2324 return v8_heap_explorer_.IterateAndExtractReferences(&filler);
2247 return IterateAndExtractReferences(); 2325 }
2248 } 2326
2249 2327
2250
2251 void HeapSnapshotGenerator::FillReversePostorderIndexes( 2328 void HeapSnapshotGenerator::FillReversePostorderIndexes(
2252 Vector<HeapEntry*>* entries) { 2329 Vector<HeapEntry*>* entries) {
2253 snapshot_->ClearPaint(); 2330 snapshot_->ClearPaint();
2254 int current_entry = 0; 2331 int current_entry = 0;
2255 List<HeapEntry*> nodes_to_visit; 2332 List<HeapEntry*> nodes_to_visit;
2256 nodes_to_visit.Add(snapshot_->root()); 2333 nodes_to_visit.Add(snapshot_->root());
2257 snapshot_->root()->paint_reachable(); 2334 snapshot_->root()->paint_reachable();
2258 while (!nodes_to_visit.is_empty()) { 2335 while (!nodes_to_visit.is_empty()) {
2259 HeapEntry* entry = nodes_to_visit.last(); 2336 HeapEntry* entry = nodes_to_visit.last();
2260 Vector<HeapGraphEdge> children = entry->children(); 2337 Vector<HeapGraphEdge> children = entry->children();
(...skipping 21 matching lines...) Expand all
2282 int finger1 = i1, finger2 = i2; 2359 int finger1 = i1, finger2 = i2;
2283 while (finger1 != finger2) { 2360 while (finger1 != finger2) {
2284 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); 2361 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index();
2285 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); 2362 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index();
2286 } 2363 }
2287 return finger1; 2364 return finger1;
2288 } 2365 }
2289 2366
2290 // The algorithm is based on the article: 2367 // The algorithm is based on the article:
2291 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" 2368 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
2292 // Softw. Pract. Exper. 4 (2001), pp. 110. 2369 // Softw. Pract. Exper. 4 (2001), pp. 1-10.
2293 bool HeapSnapshotGenerator::BuildDominatorTree( 2370 bool HeapSnapshotGenerator::BuildDominatorTree(
2294 const Vector<HeapEntry*>& entries, 2371 const Vector<HeapEntry*>& entries,
2295 Vector<HeapEntry*>* dominators) { 2372 Vector<HeapEntry*>* dominators) {
2296 if (entries.length() == 0) return true; 2373 if (entries.length() == 0) return true;
2297 const int entries_length = entries.length(), root_index = entries_length - 1; 2374 const int entries_length = entries.length(), root_index = entries_length - 1;
2298 for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; 2375 for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL;
2299 (*dominators)[root_index] = entries[root_index]; 2376 (*dominators)[root_index] = entries[root_index];
2300 int changed = 1; 2377 int changed = 1;
2301 const int base_progress_counter = progress_counter_; 2378 const int base_progress_counter = progress_counter_;
2302 while (changed != 0) { 2379 while (changed != 0) {
(...skipping 20 matching lines...) Expand all
2323 } 2400 }
2324 } 2401 }
2325 if (new_idom != NULL && dominators->at(i) != new_idom) { 2402 if (new_idom != NULL && dominators->at(i) != new_idom) {
2326 (*dominators)[i] = new_idom; 2403 (*dominators)[i] = new_idom;
2327 ++changed; 2404 ++changed;
2328 } 2405 }
2329 } 2406 }
2330 int remaining = entries_length - changed; 2407 int remaining = entries_length - changed;
2331 if (remaining < 0) remaining = 0; 2408 if (remaining < 0) remaining = 0;
2332 progress_counter_ = base_progress_counter + remaining; 2409 progress_counter_ = base_progress_counter + remaining;
2333 if (!ReportProgress(true)) return false; 2410 if (!ProgressReport(true)) return false;
2334 } 2411 }
2335 return true; 2412 return true;
2336 } 2413 }
2337 2414
2338 2415
2339 bool HeapSnapshotGenerator::SetEntriesDominators() { 2416 bool HeapSnapshotGenerator::SetEntriesDominators() {
2340 // This array is used for maintaining reverse postorder of nodes. 2417 // This array is used for maintaining reverse postorder of nodes.
2341 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); 2418 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
2342 FillReversePostorderIndexes(&ordered_entries); 2419 FillReversePostorderIndexes(&ordered_entries);
2343 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); 2420 ScopedVector<HeapEntry*> dominators(ordered_entries.length());
2344 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; 2421 if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
2345 for (int i = 0; i < ordered_entries.length(); ++i) { 2422 for (int i = 0; i < ordered_entries.length(); ++i) {
2346 ASSERT(dominators[i] != NULL); 2423 ASSERT(dominators[i] != NULL);
2347 ordered_entries[i]->set_dominator(dominators[i]); 2424 ordered_entries[i]->set_dominator(dominators[i]);
2348 } 2425 }
2349 return true; 2426 return true;
2350 } 2427 }
2351 2428
2352 2429
2353 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { 2430 bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
2354 // As for the dominators tree we only know parent nodes, not 2431 // As for the dominators tree we only know parent nodes, not
2355 // children, to sum up total sizes we "bubble" node's self size 2432 // children, to sum up total sizes we "bubble" node's self size
2356 // adding it to all of its parents. 2433 // adding it to all of its parents.
2357 for (int i = 0; i < snapshot_->entries()->length(); ++i) { 2434 for (int i = 0; i < snapshot_->entries()->length(); ++i) {
2358 HeapEntry* entry = snapshot_->entries()->at(i); 2435 HeapEntry* entry = snapshot_->entries()->at(i);
2359 entry->set_retained_size(entry->self_size()); 2436 entry->set_retained_size(entry->self_size());
2360 } 2437 }
2361 for (int i = 0; 2438 for (int i = 0;
2362 i < snapshot_->entries()->length(); 2439 i < snapshot_->entries()->length();
2363 ++i, IncProgressCounter()) { 2440 ++i, ProgressStep()) {
2364 HeapEntry* entry = snapshot_->entries()->at(i); 2441 HeapEntry* entry = snapshot_->entries()->at(i);
2365 int entry_size = entry->self_size(); 2442 int entry_size = entry->self_size();
2366 for (HeapEntry* dominator = entry->dominator(); 2443 for (HeapEntry* dominator = entry->dominator();
2367 dominator != entry; 2444 dominator != entry;
2368 entry = dominator, dominator = entry->dominator()) { 2445 entry = dominator, dominator = entry->dominator()) {
2369 dominator->add_retained_size(entry_size); 2446 dominator->add_retained_size(entry_size);
2370 } 2447 }
2371 if (!ReportProgress()) return false; 2448 if (!ProgressReport()) return false;
2372 } 2449 }
2373 return true; 2450 return true;
2374 } 2451 }
2375 2452
2376 2453
2377 bool HeapSnapshotGenerator::IterateAndExtractReferences() {
2378 HeapIterator iterator(HeapIterator::kFilterUnreachable);
2379 bool interrupted = false;
2380 // Heap iteration with filtering must be finished in any case.
2381 for (HeapObject* obj = iterator.next();
2382 obj != NULL;
2383 obj = iterator.next(), IncProgressCounter()) {
2384 if (!interrupted) {
2385 ExtractReferences(obj);
2386 if (!ReportProgress()) interrupted = true;
2387 }
2388 }
2389 if (interrupted) return false;
2390 SetRootGcRootsReference();
2391 RootsReferencesExtractor extractor(this);
2392 HEAP->IterateRoots(&extractor, VISIT_ALL);
2393 return ReportProgress();
2394 }
2395
2396
2397 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { 2454 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
2398 raw_additions_root_ = 2455 raw_additions_root_ =
2399 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); 2456 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
2400 additions_root()->Init( 2457 additions_root()->Init(
2401 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); 2458 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
2402 raw_deletions_root_ = 2459 raw_deletions_root_ =
2403 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); 2460 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
2404 deletions_root()->Init( 2461 deletions_root()->Init(
2405 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); 2462 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
2406 } 2463 }
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 2894
2838 2895
2839 String* GetConstructorNameForHeapProfile(JSObject* object) { 2896 String* GetConstructorNameForHeapProfile(JSObject* object) {
2840 if (object->IsJSFunction()) return HEAP->closure_symbol(); 2897 if (object->IsJSFunction()) return HEAP->closure_symbol();
2841 return object->constructor_name(); 2898 return object->constructor_name();
2842 } 2899 }
2843 2900
2844 } } // namespace v8::internal 2901 } } // namespace v8::internal
2845 2902
2846 #endif // ENABLE_LOGGING_AND_PROFILING 2903 #endif // ENABLE_LOGGING_AND_PROFILING
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