OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "heap-snapshot-generator-inl.h" | 30 #include "heap-snapshot-generator-inl.h" |
31 | 31 |
32 #include "allocation-tracker.h" | 32 #include "allocation-tracker.h" |
| 33 #include "code-stubs.h" |
33 #include "heap-profiler.h" | 34 #include "heap-profiler.h" |
34 #include "debug.h" | 35 #include "debug.h" |
35 #include "types.h" | 36 #include "types.h" |
36 | 37 |
37 namespace v8 { | 38 namespace v8 { |
38 namespace internal { | 39 namespace internal { |
39 | 40 |
40 | 41 |
41 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) | 42 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) |
42 : type_(type), | 43 : type_(type), |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 HeapObject* parent_obj, | 1104 HeapObject* parent_obj, |
1104 int parent) | 1105 int parent) |
1105 : generator_(generator), | 1106 : generator_(generator), |
1106 parent_obj_(parent_obj), | 1107 parent_obj_(parent_obj), |
1107 parent_(parent), | 1108 parent_(parent), |
1108 next_index_(0) { | 1109 next_index_(0) { |
1109 } | 1110 } |
1110 void VisitCodeEntry(Address entry_address) { | 1111 void VisitCodeEntry(Address entry_address) { |
1111 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); | 1112 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); |
1112 generator_->SetInternalReference(parent_obj_, parent_, "code", code); | 1113 generator_->SetInternalReference(parent_obj_, parent_, "code", code); |
1113 generator_->TagObject(code, "(code)"); | 1114 generator_->TagCodeObject(code); |
1114 } | 1115 } |
1115 void VisitPointers(Object** start, Object** end) { | 1116 void VisitPointers(Object** start, Object** end) { |
1116 for (Object** p = start; p < end; p++) { | 1117 for (Object** p = start; p < end; p++) { |
1117 if (CheckVisitedAndUnmark(p)) continue; | 1118 if (CheckVisitedAndUnmark(p)) continue; |
1118 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); | 1119 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
1119 } | 1120 } |
1120 } | 1121 } |
1121 static void MarkVisitedField(HeapObject* obj, int offset) { | 1122 static void MarkVisitedField(HeapObject* obj, int offset) { |
1122 if (offset < 0) return; | 1123 if (offset < 0) return; |
1123 Address field = obj->address() + offset; | 1124 Address field = obj->address() + offset; |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 TagObject(map->dependent_code(), "(dependent code)"); | 1364 TagObject(map->dependent_code(), "(dependent code)"); |
1364 SetInternalReference(map, entry, | 1365 SetInternalReference(map, entry, |
1365 "dependent_code", map->dependent_code(), | 1366 "dependent_code", map->dependent_code(), |
1366 Map::kDependentCodeOffset); | 1367 Map::kDependentCodeOffset); |
1367 } | 1368 } |
1368 | 1369 |
1369 | 1370 |
1370 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( | 1371 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( |
1371 int entry, SharedFunctionInfo* shared) { | 1372 int entry, SharedFunctionInfo* shared) { |
1372 HeapObject* obj = shared; | 1373 HeapObject* obj = shared; |
| 1374 StringsStorage* names = collection_->names(); |
| 1375 String* shared_name = shared->DebugName(); |
| 1376 const char* name = NULL; |
| 1377 if (shared_name != *heap_->isolate()->factory()->empty_string()) { |
| 1378 name = names->GetName(shared_name); |
| 1379 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); |
| 1380 } else { |
| 1381 TagObject(shared->code(), names->GetFormatted("(%s code)", |
| 1382 Code::Kind2String(shared->code()->kind()))); |
| 1383 } |
| 1384 |
1373 SetInternalReference(obj, entry, | 1385 SetInternalReference(obj, entry, |
1374 "name", shared->name(), | 1386 "name", shared->name(), |
1375 SharedFunctionInfo::kNameOffset); | 1387 SharedFunctionInfo::kNameOffset); |
1376 TagObject(shared->code(), "(code)"); | |
1377 SetInternalReference(obj, entry, | 1388 SetInternalReference(obj, entry, |
1378 "code", shared->code(), | 1389 "code", shared->code(), |
1379 SharedFunctionInfo::kCodeOffset); | 1390 SharedFunctionInfo::kCodeOffset); |
1380 TagObject(shared->scope_info(), "(function scope info)"); | 1391 TagObject(shared->scope_info(), "(function scope info)"); |
1381 SetInternalReference(obj, entry, | 1392 SetInternalReference(obj, entry, |
1382 "scope_info", shared->scope_info(), | 1393 "scope_info", shared->scope_info(), |
1383 SharedFunctionInfo::kScopeInfoOffset); | 1394 SharedFunctionInfo::kScopeInfoOffset); |
1384 SetInternalReference(obj, entry, | 1395 SetInternalReference(obj, entry, |
1385 "instance_class_name", shared->instance_class_name(), | 1396 "instance_class_name", shared->instance_class_name(), |
1386 SharedFunctionInfo::kInstanceClassNameOffset); | 1397 SharedFunctionInfo::kInstanceClassNameOffset); |
1387 SetInternalReference(obj, entry, | 1398 SetInternalReference(obj, entry, |
1388 "script", shared->script(), | 1399 "script", shared->script(), |
1389 SharedFunctionInfo::kScriptOffset); | 1400 SharedFunctionInfo::kScriptOffset); |
1390 TagObject(shared->construct_stub(), "(code)"); | 1401 const char* construct_stub_name = name ? |
| 1402 names->GetFormatted("(construct stub code for %s)", name) : |
| 1403 "(construct stub code)"; |
| 1404 TagObject(shared->construct_stub(), construct_stub_name); |
1391 SetInternalReference(obj, entry, | 1405 SetInternalReference(obj, entry, |
1392 "construct_stub", shared->construct_stub(), | 1406 "construct_stub", shared->construct_stub(), |
1393 SharedFunctionInfo::kConstructStubOffset); | 1407 SharedFunctionInfo::kConstructStubOffset); |
1394 SetInternalReference(obj, entry, | 1408 SetInternalReference(obj, entry, |
1395 "function_data", shared->function_data(), | 1409 "function_data", shared->function_data(), |
1396 SharedFunctionInfo::kFunctionDataOffset); | 1410 SharedFunctionInfo::kFunctionDataOffset); |
1397 SetInternalReference(obj, entry, | 1411 SetInternalReference(obj, entry, |
1398 "debug_info", shared->debug_info(), | 1412 "debug_info", shared->debug_info(), |
1399 SharedFunctionInfo::kDebugInfoOffset); | 1413 SharedFunctionInfo::kDebugInfoOffset); |
1400 SetInternalReference(obj, entry, | 1414 SetInternalReference(obj, entry, |
1401 "inferred_name", shared->inferred_name(), | 1415 "inferred_name", shared->inferred_name(), |
1402 SharedFunctionInfo::kInferredNameOffset); | 1416 SharedFunctionInfo::kInferredNameOffset); |
| 1417 SetInternalReference(obj, entry, |
| 1418 "optimized_code_map", shared->optimized_code_map(), |
| 1419 SharedFunctionInfo::kOptimizedCodeMapOffset); |
1403 SetWeakReference(obj, entry, | 1420 SetWeakReference(obj, entry, |
1404 1, shared->initial_map(), | 1421 1, shared->initial_map(), |
1405 SharedFunctionInfo::kInitialMapOffset); | 1422 SharedFunctionInfo::kInitialMapOffset); |
1406 } | 1423 } |
1407 | 1424 |
1408 | 1425 |
1409 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { | 1426 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { |
1410 HeapObject* obj = script; | 1427 HeapObject* obj = script; |
1411 SetInternalReference(obj, entry, | 1428 SetInternalReference(obj, entry, |
1412 "source", script->source(), | 1429 "source", script->source(), |
(...skipping 29 matching lines...) Expand all Loading... |
1442 SetInternalReference(code_cache, entry, | 1459 SetInternalReference(code_cache, entry, |
1443 "default_cache", code_cache->default_cache(), | 1460 "default_cache", code_cache->default_cache(), |
1444 CodeCache::kDefaultCacheOffset); | 1461 CodeCache::kDefaultCacheOffset); |
1445 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1462 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
1446 SetInternalReference(code_cache, entry, | 1463 SetInternalReference(code_cache, entry, |
1447 "type_cache", code_cache->normal_type_cache(), | 1464 "type_cache", code_cache->normal_type_cache(), |
1448 CodeCache::kNormalTypeCacheOffset); | 1465 CodeCache::kNormalTypeCacheOffset); |
1449 } | 1466 } |
1450 | 1467 |
1451 | 1468 |
| 1469 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { |
| 1470 TagObject(code, collection_->names()->GetFormatted("(%s code)", |
| 1471 external_name)); |
| 1472 } |
| 1473 |
| 1474 |
| 1475 void V8HeapExplorer::TagCodeObject(Code* code) { |
| 1476 if (code->kind() == Code::STUB) { |
| 1477 TagObject(code, collection_->names()->GetFormatted( |
| 1478 "(%s code)", CodeStub::MajorName( |
| 1479 static_cast<CodeStub::Major>(code->major_key()), true))); |
| 1480 } |
| 1481 } |
| 1482 |
| 1483 |
1452 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1484 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1485 TagCodeObject(code); |
1453 TagObject(code->relocation_info(), "(code relocation info)"); | 1486 TagObject(code->relocation_info(), "(code relocation info)"); |
1454 SetInternalReference(code, entry, | 1487 SetInternalReference(code, entry, |
1455 "relocation_info", code->relocation_info(), | 1488 "relocation_info", code->relocation_info(), |
1456 Code::kRelocationInfoOffset); | 1489 Code::kRelocationInfoOffset); |
1457 SetInternalReference(code, entry, | 1490 SetInternalReference(code, entry, |
1458 "handler_table", code->handler_table(), | 1491 "handler_table", code->handler_table(), |
1459 Code::kHandlerTableOffset); | 1492 Code::kHandlerTableOffset); |
1460 TagObject(code->deoptimization_data(), "(code deopt data)"); | 1493 TagObject(code->deoptimization_data(), "(code deopt data)"); |
1461 SetInternalReference(code, entry, | 1494 SetInternalReference(code, entry, |
1462 "deoptimization_data", code->deoptimization_data(), | 1495 "deoptimization_data", code->deoptimization_data(), |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1688 class RootsReferencesExtractor : public ObjectVisitor { | 1721 class RootsReferencesExtractor : public ObjectVisitor { |
1689 private: | 1722 private: |
1690 struct IndexTag { | 1723 struct IndexTag { |
1691 IndexTag(int index, VisitorSynchronization::SyncTag tag) | 1724 IndexTag(int index, VisitorSynchronization::SyncTag tag) |
1692 : index(index), tag(tag) { } | 1725 : index(index), tag(tag) { } |
1693 int index; | 1726 int index; |
1694 VisitorSynchronization::SyncTag tag; | 1727 VisitorSynchronization::SyncTag tag; |
1695 }; | 1728 }; |
1696 | 1729 |
1697 public: | 1730 public: |
1698 RootsReferencesExtractor() | 1731 explicit RootsReferencesExtractor(Heap* heap) |
1699 : collecting_all_references_(false), | 1732 : collecting_all_references_(false), |
1700 previous_reference_count_(0) { | 1733 previous_reference_count_(0), |
| 1734 heap_(heap) { |
1701 } | 1735 } |
1702 | 1736 |
1703 void VisitPointers(Object** start, Object** end) { | 1737 void VisitPointers(Object** start, Object** end) { |
1704 if (collecting_all_references_) { | 1738 if (collecting_all_references_) { |
1705 for (Object** p = start; p < end; p++) all_references_.Add(*p); | 1739 for (Object** p = start; p < end; p++) all_references_.Add(*p); |
1706 } else { | 1740 } else { |
1707 for (Object** p = start; p < end; p++) strong_references_.Add(*p); | 1741 for (Object** p = start; p < end; p++) strong_references_.Add(*p); |
1708 } | 1742 } |
1709 } | 1743 } |
1710 | 1744 |
1711 void SetCollectingAllReferences() { collecting_all_references_ = true; } | 1745 void SetCollectingAllReferences() { collecting_all_references_ = true; } |
1712 | 1746 |
1713 void FillReferences(V8HeapExplorer* explorer) { | 1747 void FillReferences(V8HeapExplorer* explorer) { |
1714 ASSERT(strong_references_.length() <= all_references_.length()); | 1748 ASSERT(strong_references_.length() <= all_references_.length()); |
| 1749 Builtins* builtins = heap_->isolate()->builtins(); |
1715 for (int i = 0; i < reference_tags_.length(); ++i) { | 1750 for (int i = 0; i < reference_tags_.length(); ++i) { |
1716 explorer->SetGcRootsReference(reference_tags_[i].tag); | 1751 explorer->SetGcRootsReference(reference_tags_[i].tag); |
1717 } | 1752 } |
1718 int strong_index = 0, all_index = 0, tags_index = 0; | 1753 int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0; |
1719 while (all_index < all_references_.length()) { | 1754 while (all_index < all_references_.length()) { |
1720 if (strong_index < strong_references_.length() && | 1755 if (strong_index < strong_references_.length() && |
1721 strong_references_[strong_index] == all_references_[all_index]) { | 1756 strong_references_[strong_index] == all_references_[all_index]) { |
1722 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1757 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
1723 false, | 1758 false, |
1724 all_references_[all_index++]); | 1759 all_references_[all_index]); |
1725 ++strong_index; | 1760 ++strong_index; |
1726 } else { | 1761 } else { |
1727 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1762 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
1728 true, | 1763 true, |
1729 all_references_[all_index++]); | 1764 all_references_[all_index]); |
1730 } | 1765 } |
| 1766 if (reference_tags_[tags_index].tag == |
| 1767 VisitorSynchronization::kBuiltins) { |
| 1768 ASSERT(all_references_[all_index]->IsCode()); |
| 1769 explorer->TagCodeObject(Code::cast(all_references_[all_index]), |
| 1770 builtins->name(builtin_index++)); |
| 1771 } |
| 1772 ++all_index; |
1731 if (reference_tags_[tags_index].index == all_index) ++tags_index; | 1773 if (reference_tags_[tags_index].index == all_index) ++tags_index; |
1732 } | 1774 } |
1733 } | 1775 } |
1734 | 1776 |
1735 void Synchronize(VisitorSynchronization::SyncTag tag) { | 1777 void Synchronize(VisitorSynchronization::SyncTag tag) { |
1736 if (collecting_all_references_ && | 1778 if (collecting_all_references_ && |
1737 previous_reference_count_ != all_references_.length()) { | 1779 previous_reference_count_ != all_references_.length()) { |
1738 previous_reference_count_ = all_references_.length(); | 1780 previous_reference_count_ = all_references_.length(); |
1739 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); | 1781 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); |
1740 } | 1782 } |
1741 } | 1783 } |
1742 | 1784 |
1743 private: | 1785 private: |
1744 bool collecting_all_references_; | 1786 bool collecting_all_references_; |
1745 List<Object*> strong_references_; | 1787 List<Object*> strong_references_; |
1746 List<Object*> all_references_; | 1788 List<Object*> all_references_; |
1747 int previous_reference_count_; | 1789 int previous_reference_count_; |
1748 List<IndexTag> reference_tags_; | 1790 List<IndexTag> reference_tags_; |
| 1791 Heap* heap_; |
1749 }; | 1792 }; |
1750 | 1793 |
1751 | 1794 |
1752 bool V8HeapExplorer::IterateAndExtractReferences( | 1795 bool V8HeapExplorer::IterateAndExtractReferences( |
1753 SnapshotFillerInterface* filler) { | 1796 SnapshotFillerInterface* filler) { |
1754 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); | 1797 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
1755 | 1798 |
1756 filler_ = filler; | 1799 filler_ = filler; |
1757 bool interrupted = false; | 1800 bool interrupted = false; |
1758 | 1801 |
1759 // Heap iteration with filtering must be finished in any case. | 1802 // Heap iteration with filtering must be finished in any case. |
1760 for (HeapObject* obj = iterator.next(); | 1803 for (HeapObject* obj = iterator.next(); |
1761 obj != NULL; | 1804 obj != NULL; |
1762 obj = iterator.next(), progress_->ProgressStep()) { | 1805 obj = iterator.next(), progress_->ProgressStep()) { |
1763 if (!interrupted) { | 1806 if (!interrupted) { |
1764 ExtractReferences(obj); | 1807 ExtractReferences(obj); |
1765 if (!progress_->ProgressReport(false)) interrupted = true; | 1808 if (!progress_->ProgressReport(false)) interrupted = true; |
1766 } | 1809 } |
1767 } | 1810 } |
1768 if (interrupted) { | 1811 if (interrupted) { |
1769 filler_ = NULL; | 1812 filler_ = NULL; |
1770 return false; | 1813 return false; |
1771 } | 1814 } |
1772 | 1815 |
1773 SetRootGcRootsReference(); | 1816 SetRootGcRootsReference(); |
1774 RootsReferencesExtractor extractor; | 1817 RootsReferencesExtractor extractor(heap_); |
1775 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); | 1818 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
1776 extractor.SetCollectingAllReferences(); | 1819 extractor.SetCollectingAllReferences(); |
1777 heap_->IterateRoots(&extractor, VISIT_ALL); | 1820 heap_->IterateRoots(&extractor, VISIT_ALL); |
1778 extractor.FillReferences(this); | 1821 extractor.FillReferences(this); |
1779 filler_ = NULL; | 1822 filler_ = NULL; |
1780 return progress_->ProgressReport(true); | 1823 return progress_->ProgressReport(true); |
1781 } | 1824 } |
1782 | 1825 |
1783 | 1826 |
1784 bool V8HeapExplorer::IsEssentialObject(Object* object) { | 1827 bool V8HeapExplorer::IsEssentialObject(Object* object) { |
(...skipping 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3026 writer_->AddString("\"<dummy>\""); | 3069 writer_->AddString("\"<dummy>\""); |
3027 for (int i = 1; i < sorted_strings.length(); ++i) { | 3070 for (int i = 1; i < sorted_strings.length(); ++i) { |
3028 writer_->AddCharacter(','); | 3071 writer_->AddCharacter(','); |
3029 SerializeString(sorted_strings[i]); | 3072 SerializeString(sorted_strings[i]); |
3030 if (writer_->aborted()) return; | 3073 if (writer_->aborted()) return; |
3031 } | 3074 } |
3032 } | 3075 } |
3033 | 3076 |
3034 | 3077 |
3035 } } // namespace v8::internal | 3078 } } // namespace v8::internal |
OLD | NEW |