Chromium Code Reviews| 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 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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; |
| 1373 SetInternalReference(obj, entry, | 1374 SetInternalReference(obj, entry, |
| 1374 "name", shared->name(), | 1375 "name", shared->name(), |
| 1375 SharedFunctionInfo::kNameOffset); | 1376 SharedFunctionInfo::kNameOffset); |
| 1376 TagObject(shared->code(), "(code)"); | 1377 Object* empty_string = *heap_->isolate()->factory()->empty_string(); |
| 1378 StringsStorage* names = collection_->names(); | |
| 1379 Object* shared_name = shared->name(); | |
| 1380 shared_name = !shared_name->IsFailure() ? shared_name : shared->DebugName(); | |
|
yurys
2013/10/31 09:54:01
shared_name->IsFailure() will always be true here
loislo
2013/10/31 10:59:39
Done.
| |
| 1381 const char* name = NULL; | |
| 1382 if (shared_name != empty_string) { | |
| 1383 name = names->GetName(Name::cast(shared_name)); | |
| 1384 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); | |
| 1385 } else { | |
| 1386 TagObject(shared->code(), names->GetFormatted("(%s code)", | |
| 1387 Code::Kind2String(shared->code()->kind()))); | |
| 1388 } | |
| 1377 SetInternalReference(obj, entry, | 1389 SetInternalReference(obj, entry, |
| 1378 "code", shared->code(), | 1390 "code", shared->code(), |
| 1379 SharedFunctionInfo::kCodeOffset); | 1391 SharedFunctionInfo::kCodeOffset); |
| 1380 TagObject(shared->scope_info(), "(function scope info)"); | 1392 TagObject(shared->scope_info(), "(function scope info)"); |
| 1381 SetInternalReference(obj, entry, | 1393 SetInternalReference(obj, entry, |
| 1382 "scope_info", shared->scope_info(), | 1394 "scope_info", shared->scope_info(), |
| 1383 SharedFunctionInfo::kScopeInfoOffset); | 1395 SharedFunctionInfo::kScopeInfoOffset); |
| 1384 SetInternalReference(obj, entry, | 1396 SetInternalReference(obj, entry, |
| 1385 "instance_class_name", shared->instance_class_name(), | 1397 "instance_class_name", shared->instance_class_name(), |
| 1386 SharedFunctionInfo::kInstanceClassNameOffset); | 1398 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1387 SetInternalReference(obj, entry, | 1399 SetInternalReference(obj, entry, |
| 1388 "script", shared->script(), | 1400 "script", shared->script(), |
| 1389 SharedFunctionInfo::kScriptOffset); | 1401 SharedFunctionInfo::kScriptOffset); |
| 1390 TagObject(shared->construct_stub(), "(code)"); | 1402 const char* construct_stub_name = name ? |
| 1403 names->GetFormatted("(construct stub code for %s)", name) : | |
| 1404 "(construct stub code)"; | |
| 1405 TagObject(shared->construct_stub(), construct_stub_name); | |
| 1391 SetInternalReference(obj, entry, | 1406 SetInternalReference(obj, entry, |
| 1392 "construct_stub", shared->construct_stub(), | 1407 "construct_stub", shared->construct_stub(), |
| 1393 SharedFunctionInfo::kConstructStubOffset); | 1408 SharedFunctionInfo::kConstructStubOffset); |
| 1394 SetInternalReference(obj, entry, | 1409 SetInternalReference(obj, entry, |
| 1395 "function_data", shared->function_data(), | 1410 "function_data", shared->function_data(), |
| 1396 SharedFunctionInfo::kFunctionDataOffset); | 1411 SharedFunctionInfo::kFunctionDataOffset); |
| 1397 SetInternalReference(obj, entry, | 1412 SetInternalReference(obj, entry, |
| 1398 "debug_info", shared->debug_info(), | 1413 "debug_info", shared->debug_info(), |
| 1399 SharedFunctionInfo::kDebugInfoOffset); | 1414 SharedFunctionInfo::kDebugInfoOffset); |
| 1400 SetInternalReference(obj, entry, | 1415 SetInternalReference(obj, entry, |
| 1401 "inferred_name", shared->inferred_name(), | 1416 "inferred_name", shared->inferred_name(), |
| 1402 SharedFunctionInfo::kInferredNameOffset); | 1417 SharedFunctionInfo::kInferredNameOffset); |
| 1418 SetInternalReference(obj, entry, | |
| 1419 "optimized_code_map", shared->optimized_code_map(), | |
| 1420 SharedFunctionInfo::kOptimizedCodeMapOffset); | |
| 1403 SetWeakReference(obj, entry, | 1421 SetWeakReference(obj, entry, |
| 1404 1, shared->initial_map(), | 1422 1, shared->initial_map(), |
| 1405 SharedFunctionInfo::kInitialMapOffset); | 1423 SharedFunctionInfo::kInitialMapOffset); |
| 1406 } | 1424 } |
| 1407 | 1425 |
| 1408 | 1426 |
| 1409 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { | 1427 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { |
| 1410 HeapObject* obj = script; | 1428 HeapObject* obj = script; |
| 1411 SetInternalReference(obj, entry, | 1429 SetInternalReference(obj, entry, |
| 1412 "source", script->source(), | 1430 "source", script->source(), |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1442 SetInternalReference(code_cache, entry, | 1460 SetInternalReference(code_cache, entry, |
| 1443 "default_cache", code_cache->default_cache(), | 1461 "default_cache", code_cache->default_cache(), |
| 1444 CodeCache::kDefaultCacheOffset); | 1462 CodeCache::kDefaultCacheOffset); |
| 1445 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1463 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
| 1446 SetInternalReference(code_cache, entry, | 1464 SetInternalReference(code_cache, entry, |
| 1447 "type_cache", code_cache->normal_type_cache(), | 1465 "type_cache", code_cache->normal_type_cache(), |
| 1448 CodeCache::kNormalTypeCacheOffset); | 1466 CodeCache::kNormalTypeCacheOffset); |
| 1449 } | 1467 } |
| 1450 | 1468 |
| 1451 | 1469 |
| 1470 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { | |
| 1471 StringsStorage* names = collection_->names(); | |
| 1472 if (external_name) { | |
| 1473 TagObject(code, names->GetFormatted("(%s code)", external_name)); | |
| 1474 return; | |
| 1475 } | |
| 1476 switch (code->kind()) { | |
| 1477 case Code::STUB: { | |
| 1478 TagObject(code, names->GetFormatted("(%s code)", | |
| 1479 CodeStub::MajorName(static_cast<CodeStub::Major>(code->major_key()), | |
| 1480 true))); | |
| 1481 break; | |
| 1482 } | |
| 1483 default: { | |
| 1484 break; | |
| 1485 } | |
| 1486 } | |
| 1487 } | |
| 1488 | |
| 1489 | |
| 1452 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1490 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1491 TagCodeObject(code); | |
| 1453 TagObject(code->relocation_info(), "(code relocation info)"); | 1492 TagObject(code->relocation_info(), "(code relocation info)"); |
| 1454 SetInternalReference(code, entry, | 1493 SetInternalReference(code, entry, |
| 1455 "relocation_info", code->relocation_info(), | 1494 "relocation_info", code->relocation_info(), |
| 1456 Code::kRelocationInfoOffset); | 1495 Code::kRelocationInfoOffset); |
| 1457 SetInternalReference(code, entry, | 1496 SetInternalReference(code, entry, |
| 1458 "handler_table", code->handler_table(), | 1497 "handler_table", code->handler_table(), |
| 1459 Code::kHandlerTableOffset); | 1498 Code::kHandlerTableOffset); |
| 1460 TagObject(code->deoptimization_data(), "(code deopt data)"); | 1499 TagObject(code->deoptimization_data(), "(code deopt data)"); |
| 1461 SetInternalReference(code, entry, | 1500 SetInternalReference(code, entry, |
| 1462 "deoptimization_data", code->deoptimization_data(), | 1501 "deoptimization_data", code->deoptimization_data(), |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1688 class RootsReferencesExtractor : public ObjectVisitor { | 1727 class RootsReferencesExtractor : public ObjectVisitor { |
| 1689 private: | 1728 private: |
| 1690 struct IndexTag { | 1729 struct IndexTag { |
| 1691 IndexTag(int index, VisitorSynchronization::SyncTag tag) | 1730 IndexTag(int index, VisitorSynchronization::SyncTag tag) |
| 1692 : index(index), tag(tag) { } | 1731 : index(index), tag(tag) { } |
| 1693 int index; | 1732 int index; |
| 1694 VisitorSynchronization::SyncTag tag; | 1733 VisitorSynchronization::SyncTag tag; |
| 1695 }; | 1734 }; |
| 1696 | 1735 |
| 1697 public: | 1736 public: |
| 1698 RootsReferencesExtractor() | 1737 explicit RootsReferencesExtractor(Heap* heap) |
| 1699 : collecting_all_references_(false), | 1738 : collecting_all_references_(false), |
| 1700 previous_reference_count_(0) { | 1739 previous_reference_count_(0), |
| 1740 heap_(heap) { | |
| 1701 } | 1741 } |
| 1702 | 1742 |
| 1703 void VisitPointers(Object** start, Object** end) { | 1743 void VisitPointers(Object** start, Object** end) { |
| 1704 if (collecting_all_references_) { | 1744 if (collecting_all_references_) { |
| 1705 for (Object** p = start; p < end; p++) all_references_.Add(*p); | 1745 for (Object** p = start; p < end; p++) all_references_.Add(*p); |
| 1706 } else { | 1746 } else { |
| 1707 for (Object** p = start; p < end; p++) strong_references_.Add(*p); | 1747 for (Object** p = start; p < end; p++) strong_references_.Add(*p); |
| 1708 } | 1748 } |
| 1709 } | 1749 } |
| 1710 | 1750 |
| 1711 void SetCollectingAllReferences() { collecting_all_references_ = true; } | 1751 void SetCollectingAllReferences() { collecting_all_references_ = true; } |
| 1712 | 1752 |
| 1713 void FillReferences(V8HeapExplorer* explorer) { | 1753 void FillReferences(V8HeapExplorer* explorer) { |
| 1714 ASSERT(strong_references_.length() <= all_references_.length()); | 1754 ASSERT(strong_references_.length() <= all_references_.length()); |
| 1755 Builtins* builtins = heap_->isolate()->builtins(); | |
| 1715 for (int i = 0; i < reference_tags_.length(); ++i) { | 1756 for (int i = 0; i < reference_tags_.length(); ++i) { |
| 1716 explorer->SetGcRootsReference(reference_tags_[i].tag); | 1757 explorer->SetGcRootsReference(reference_tags_[i].tag); |
| 1717 } | 1758 } |
| 1718 int strong_index = 0, all_index = 0, tags_index = 0; | 1759 int strong_index = 0, all_index = 0, tags_index = 0, prev_tag_index = 0; |
| 1719 while (all_index < all_references_.length()) { | 1760 while (all_index < all_references_.length()) { |
| 1720 if (strong_index < strong_references_.length() && | 1761 if (strong_index < strong_references_.length() && |
| 1721 strong_references_[strong_index] == all_references_[all_index]) { | 1762 strong_references_[strong_index] == all_references_[all_index]) { |
| 1722 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1763 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 1723 false, | 1764 false, |
| 1724 all_references_[all_index++]); | 1765 all_references_[all_index]); |
| 1725 ++strong_index; | 1766 ++strong_index; |
| 1726 } else { | 1767 } else { |
| 1727 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1768 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 1728 true, | 1769 true, |
| 1729 all_references_[all_index++]); | 1770 all_references_[all_index]); |
| 1730 } | 1771 } |
| 1731 if (reference_tags_[tags_index].index == all_index) ++tags_index; | 1772 if (reference_tags_[tags_index].tag == VisitorSynchronization::kBuiltins |
| 1773 && all_references_[all_index]->IsCode()) { | |
| 1774 explorer->TagCodeObject(Code::cast(all_references_[all_index]), | |
| 1775 builtins->name(all_index - prev_tag_index)); | |
| 1776 } | |
| 1777 ++all_index; | |
| 1778 if (reference_tags_[tags_index].index == all_index) { | |
| 1779 prev_tag_index = all_index; | |
| 1780 ++tags_index; | |
| 1781 } | |
| 1732 } | 1782 } |
| 1733 } | 1783 } |
| 1734 | 1784 |
| 1735 void Synchronize(VisitorSynchronization::SyncTag tag) { | 1785 void Synchronize(VisitorSynchronization::SyncTag tag) { |
| 1736 if (collecting_all_references_ && | 1786 if (collecting_all_references_ && |
| 1737 previous_reference_count_ != all_references_.length()) { | 1787 previous_reference_count_ != all_references_.length()) { |
| 1738 previous_reference_count_ = all_references_.length(); | 1788 previous_reference_count_ = all_references_.length(); |
| 1739 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); | 1789 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); |
| 1740 } | 1790 } |
| 1741 } | 1791 } |
| 1742 | 1792 |
| 1743 private: | 1793 private: |
| 1744 bool collecting_all_references_; | 1794 bool collecting_all_references_; |
| 1745 List<Object*> strong_references_; | 1795 List<Object*> strong_references_; |
| 1746 List<Object*> all_references_; | 1796 List<Object*> all_references_; |
| 1747 int previous_reference_count_; | 1797 int previous_reference_count_; |
| 1748 List<IndexTag> reference_tags_; | 1798 List<IndexTag> reference_tags_; |
| 1799 Heap* heap_; | |
| 1749 }; | 1800 }; |
| 1750 | 1801 |
| 1751 | 1802 |
| 1752 bool V8HeapExplorer::IterateAndExtractReferences( | 1803 bool V8HeapExplorer::IterateAndExtractReferences( |
| 1753 SnapshotFillerInterface* filler) { | 1804 SnapshotFillerInterface* filler) { |
| 1754 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); | 1805 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
| 1755 | 1806 |
| 1756 filler_ = filler; | 1807 filler_ = filler; |
| 1757 bool interrupted = false; | 1808 bool interrupted = false; |
| 1758 | 1809 |
| 1759 // Heap iteration with filtering must be finished in any case. | 1810 // Heap iteration with filtering must be finished in any case. |
| 1760 for (HeapObject* obj = iterator.next(); | 1811 for (HeapObject* obj = iterator.next(); |
| 1761 obj != NULL; | 1812 obj != NULL; |
| 1762 obj = iterator.next(), progress_->ProgressStep()) { | 1813 obj = iterator.next(), progress_->ProgressStep()) { |
| 1763 if (!interrupted) { | 1814 if (!interrupted) { |
| 1764 ExtractReferences(obj); | 1815 ExtractReferences(obj); |
| 1765 if (!progress_->ProgressReport(false)) interrupted = true; | 1816 if (!progress_->ProgressReport(false)) interrupted = true; |
| 1766 } | 1817 } |
| 1767 } | 1818 } |
| 1768 if (interrupted) { | 1819 if (interrupted) { |
| 1769 filler_ = NULL; | 1820 filler_ = NULL; |
| 1770 return false; | 1821 return false; |
| 1771 } | 1822 } |
| 1772 | 1823 |
| 1773 SetRootGcRootsReference(); | 1824 SetRootGcRootsReference(); |
| 1774 RootsReferencesExtractor extractor; | 1825 RootsReferencesExtractor extractor(heap_); |
| 1775 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); | 1826 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 1776 extractor.SetCollectingAllReferences(); | 1827 extractor.SetCollectingAllReferences(); |
| 1777 heap_->IterateRoots(&extractor, VISIT_ALL); | 1828 heap_->IterateRoots(&extractor, VISIT_ALL); |
| 1778 extractor.FillReferences(this); | 1829 extractor.FillReferences(this); |
| 1779 filler_ = NULL; | 1830 filler_ = NULL; |
| 1780 return progress_->ProgressReport(true); | 1831 return progress_->ProgressReport(true); |
| 1781 } | 1832 } |
| 1782 | 1833 |
| 1783 | 1834 |
| 1784 bool V8HeapExplorer::IsEssentialObject(Object* object) { | 1835 bool V8HeapExplorer::IsEssentialObject(Object* object) { |
| (...skipping 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3026 writer_->AddString("\"<dummy>\""); | 3077 writer_->AddString("\"<dummy>\""); |
| 3027 for (int i = 1; i < sorted_strings.length(); ++i) { | 3078 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3028 writer_->AddCharacter(','); | 3079 writer_->AddCharacter(','); |
| 3029 SerializeString(sorted_strings[i]); | 3080 SerializeString(sorted_strings[i]); |
| 3030 if (writer_->aborted()) return; | 3081 if (writer_->aborted()) return; |
| 3031 } | 3082 } |
| 3032 } | 3083 } |
| 3033 | 3084 |
| 3034 | 3085 |
| 3035 } } // namespace v8::internal | 3086 } } // namespace v8::internal |
| OLD | NEW |