OLD | NEW |
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 1672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1683 } else if (object->IsScript()) { | 1683 } else if (object->IsScript()) { |
1684 Script* script = Script::cast(object); | 1684 Script* script = Script::cast(object); |
1685 return AddEntry(object, | 1685 return AddEntry(object, |
1686 HeapEntry::kCode, | 1686 HeapEntry::kCode, |
1687 script->name()->IsString() ? | 1687 script->name()->IsString() ? |
1688 collection_->names()->GetName( | 1688 collection_->names()->GetName( |
1689 String::cast(script->name())) | 1689 String::cast(script->name())) |
1690 : "", | 1690 : "", |
1691 children_count, | 1691 children_count, |
1692 retainers_count); | 1692 retainers_count); |
1693 } else if (object->IsFixedArray()) { | 1693 } else if (object->IsFixedArray() || object->IsByteArray()) { |
1694 return AddEntry(object, | 1694 return AddEntry(object, |
1695 HeapEntry::kArray, | 1695 HeapEntry::kArray, |
1696 "", | 1696 "", |
1697 children_count, | 1697 children_count, |
1698 retainers_count); | 1698 retainers_count); |
1699 } else if (object->IsHeapNumber()) { | 1699 } else if (object->IsHeapNumber()) { |
1700 return AddEntry(object, | 1700 return AddEntry(object, |
1701 HeapEntry::kHeapNumber, | 1701 HeapEntry::kHeapNumber, |
1702 "number", | 1702 "number", |
1703 children_count, | 1703 children_count, |
1704 retainers_count); | 1704 retainers_count); |
1705 } | 1705 } |
1706 return AddEntry(object, | 1706 return AddEntry(object, |
1707 HeapEntry::kHidden, | 1707 HeapEntry::kHidden, |
1708 "system", | 1708 GetSystemEntryName(object), |
1709 children_count, | 1709 children_count, |
1710 retainers_count); | 1710 retainers_count); |
1711 } | 1711 } |
1712 | 1712 |
1713 | 1713 |
1714 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 1714 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
1715 HeapEntry::Type type, | 1715 HeapEntry::Type type, |
1716 const char* name, | 1716 const char* name, |
1717 int children_count, | 1717 int children_count, |
1718 int retainers_count) { | 1718 int retainers_count) { |
1719 return snapshot_->AddEntry(type, | 1719 return snapshot_->AddEntry(type, |
1720 name, | 1720 name, |
1721 collection_->GetObjectId(object->address()), | 1721 collection_->GetObjectId(object->address()), |
1722 object->Size(), | 1722 object->Size(), |
1723 children_count, | 1723 children_count, |
1724 retainers_count); | 1724 retainers_count); |
1725 } | 1725 } |
1726 | 1726 |
1727 | 1727 |
1728 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { | 1728 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
1729 filler->AddEntry(kInternalRootObject, this); | 1729 filler->AddEntry(kInternalRootObject, this); |
1730 filler->AddEntry(kGcRootsObject, this); | 1730 filler->AddEntry(kGcRootsObject, this); |
1731 } | 1731 } |
1732 | 1732 |
1733 | 1733 |
| 1734 const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { |
| 1735 switch (object->map()->instance_type()) { |
| 1736 case MAP_TYPE: return "system / Map"; |
| 1737 case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell"; |
| 1738 case PROXY_TYPE: return "system / Proxy"; |
| 1739 case ODDBALL_TYPE: return "system / Oddball"; |
| 1740 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 1741 case NAME##_TYPE: return "system / "#Name; |
| 1742 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 1743 #undef MAKE_STRUCT_CASE |
| 1744 default: return "system"; |
| 1745 } |
| 1746 } |
| 1747 |
| 1748 |
1734 int V8HeapExplorer::EstimateObjectsCount() { | 1749 int V8HeapExplorer::EstimateObjectsCount() { |
1735 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 1750 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
1736 int objects_count = 0; | 1751 int objects_count = 0; |
1737 for (HeapObject* obj = iterator.next(); | 1752 for (HeapObject* obj = iterator.next(); |
1738 obj != NULL; | 1753 obj != NULL; |
1739 obj = iterator.next(), ++objects_count) {} | 1754 obj = iterator.next(), ++objects_count) {} |
1740 return objects_count; | 1755 return objects_count; |
1741 } | 1756 } |
1742 | 1757 |
1743 | 1758 |
1744 class IndexedReferencesExtractor : public ObjectVisitor { | 1759 class IndexedReferencesExtractor : public ObjectVisitor { |
1745 public: | 1760 public: |
1746 IndexedReferencesExtractor(V8HeapExplorer* generator, | 1761 IndexedReferencesExtractor(V8HeapExplorer* generator, |
1747 HeapObject* parent_obj, | 1762 HeapObject* parent_obj, |
1748 HeapEntry* parent_entry, | 1763 HeapEntry* parent_entry) |
1749 bool process_field_marks = false) | |
1750 : generator_(generator), | 1764 : generator_(generator), |
1751 parent_obj_(parent_obj), | 1765 parent_obj_(parent_obj), |
1752 parent_(parent_entry), | 1766 parent_(parent_entry), |
1753 process_field_marks_(process_field_marks), | |
1754 next_index_(1) { | 1767 next_index_(1) { |
1755 } | 1768 } |
1756 void VisitPointers(Object** start, Object** end) { | 1769 void VisitPointers(Object** start, Object** end) { |
1757 for (Object** p = start; p < end; p++) { | 1770 for (Object** p = start; p < end; p++) { |
1758 if (CheckVisitedAndUnmark(p)) continue; | 1771 if (CheckVisitedAndUnmark(p)) continue; |
1759 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); | 1772 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
1760 } | 1773 } |
1761 } | 1774 } |
1762 static void MarkVisitedField(HeapObject* obj, int offset) { | 1775 static void MarkVisitedField(HeapObject* obj, int offset) { |
1763 if (offset < 0) return; | 1776 if (offset < 0) return; |
1764 Address field = obj->address() + offset; | 1777 Address field = obj->address() + offset; |
1765 ASSERT(!Memory::Object_at(field)->IsFailure()); | 1778 ASSERT(!Memory::Object_at(field)->IsFailure()); |
1766 ASSERT(Memory::Object_at(field)->IsHeapObject()); | 1779 ASSERT(Memory::Object_at(field)->IsHeapObject()); |
1767 *field |= kFailureTag; | 1780 *field |= kFailureTag; |
1768 } | 1781 } |
1769 private: | 1782 private: |
1770 bool CheckVisitedAndUnmark(Object** field) { | 1783 bool CheckVisitedAndUnmark(Object** field) { |
1771 if (process_field_marks_ && (*field)->IsFailure()) { | 1784 if ((*field)->IsFailure()) { |
1772 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; | 1785 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; |
1773 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); | 1786 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); |
1774 ASSERT((*field)->IsHeapObject()); | 1787 ASSERT((*field)->IsHeapObject()); |
1775 return true; | 1788 return true; |
1776 } | 1789 } |
1777 return false; | 1790 return false; |
1778 } | 1791 } |
1779 V8HeapExplorer* generator_; | 1792 V8HeapExplorer* generator_; |
1780 HeapObject* parent_obj_; | 1793 HeapObject* parent_obj_; |
1781 HeapEntry* parent_; | 1794 HeapEntry* parent_; |
1782 bool process_field_marks_; | |
1783 int next_index_; | 1795 int next_index_; |
1784 }; | 1796 }; |
1785 | 1797 |
1786 | 1798 |
1787 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { | 1799 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { |
1788 HeapEntry* entry = GetEntry(obj); | 1800 HeapEntry* entry = GetEntry(obj); |
1789 if (entry == NULL) return; // No interest in this object. | 1801 if (entry == NULL) return; // No interest in this object. |
1790 | 1802 |
1791 if (obj->IsJSGlobalProxy()) { | 1803 if (obj->IsJSGlobalProxy()) { |
1792 // We need to reference JS global objects from snapshot's root. | 1804 // We need to reference JS global objects from snapshot's root. |
1793 // We use JSGlobalProxy because this is what embedder (e.g. browser) | 1805 // We use JSGlobalProxy because this is what embedder (e.g. browser) |
1794 // uses for the global object. | 1806 // uses for the global object. |
1795 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); | 1807 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); |
1796 SetRootShortcutReference(proxy->map()->prototype()); | 1808 SetRootShortcutReference(proxy->map()->prototype()); |
| 1809 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
1797 IndexedReferencesExtractor refs_extractor(this, obj, entry); | 1810 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
1798 obj->Iterate(&refs_extractor); | 1811 obj->Iterate(&refs_extractor); |
1799 } else if (obj->IsJSObject()) { | 1812 } else if (obj->IsJSObject()) { |
1800 JSObject* js_obj = JSObject::cast(obj); | 1813 JSObject* js_obj = JSObject::cast(obj); |
1801 ExtractClosureReferences(js_obj, entry); | 1814 ExtractClosureReferences(js_obj, entry); |
1802 ExtractPropertyReferences(js_obj, entry); | 1815 ExtractPropertyReferences(js_obj, entry); |
1803 ExtractElementReferences(js_obj, entry); | 1816 ExtractElementReferences(js_obj, entry); |
1804 ExtractInternalReferences(js_obj, entry); | 1817 ExtractInternalReferences(js_obj, entry); |
1805 SetPropertyReference( | 1818 SetPropertyReference( |
1806 obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype()); | 1819 obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype()); |
1807 if (obj->IsJSFunction()) { | 1820 if (obj->IsJSFunction()) { |
1808 JSFunction* js_fun = JSFunction::cast(js_obj); | 1821 JSFunction* js_fun = JSFunction::cast(js_obj); |
1809 SetInternalReference( | |
1810 js_fun, entry, | |
1811 "code", js_fun->shared(), | |
1812 JSFunction::kSharedFunctionInfoOffset); | |
1813 Object* proto_or_map = js_fun->prototype_or_initial_map(); | 1822 Object* proto_or_map = js_fun->prototype_or_initial_map(); |
1814 if (!proto_or_map->IsTheHole()) { | 1823 if (!proto_or_map->IsTheHole()) { |
1815 if (!proto_or_map->IsMap()) { | 1824 if (!proto_or_map->IsMap()) { |
1816 SetPropertyReference( | 1825 SetPropertyReference( |
1817 obj, entry, | 1826 obj, entry, |
1818 HEAP->prototype_symbol(), proto_or_map, | 1827 HEAP->prototype_symbol(), proto_or_map, |
1819 JSFunction::kPrototypeOrInitialMapOffset); | 1828 JSFunction::kPrototypeOrInitialMapOffset); |
1820 } else { | 1829 } else { |
1821 SetPropertyReference( | 1830 SetPropertyReference( |
1822 obj, entry, | 1831 obj, entry, |
1823 HEAP->prototype_symbol(), js_fun->prototype()); | 1832 HEAP->prototype_symbol(), js_fun->prototype()); |
1824 } | 1833 } |
1825 } | 1834 } |
| 1835 SetInternalReference(js_fun, entry, |
| 1836 "shared", js_fun->shared(), |
| 1837 JSFunction::kSharedFunctionInfoOffset); |
| 1838 SetInternalReference(js_fun, entry, |
| 1839 "context", js_fun->unchecked_context(), |
| 1840 JSFunction::kContextOffset); |
| 1841 SetInternalReference(js_fun, entry, |
| 1842 "literals", js_fun->literals(), |
| 1843 JSFunction::kLiteralsOffset); |
1826 } | 1844 } |
1827 IndexedReferencesExtractor refs_extractor(this, obj, entry, true); | 1845 SetInternalReference(obj, entry, |
| 1846 "properties", js_obj->properties(), |
| 1847 JSObject::kPropertiesOffset); |
| 1848 SetInternalReference(obj, entry, |
| 1849 "elements", js_obj->elements(), |
| 1850 JSObject::kElementsOffset); |
| 1851 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
| 1852 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
1828 obj->Iterate(&refs_extractor); | 1853 obj->Iterate(&refs_extractor); |
1829 } else if (obj->IsString()) { | 1854 } else if (obj->IsString()) { |
1830 if (obj->IsConsString()) { | 1855 if (obj->IsConsString()) { |
1831 ConsString* cs = ConsString::cast(obj); | 1856 ConsString* cs = ConsString::cast(obj); |
1832 SetInternalReference(obj, entry, 1, cs->first()); | 1857 SetInternalReference(obj, entry, 1, cs->first()); |
1833 SetInternalReference(obj, entry, 2, cs->second()); | 1858 SetInternalReference(obj, entry, 2, cs->second()); |
1834 } | 1859 } |
| 1860 } else if (obj->IsMap()) { |
| 1861 Map* map = Map::cast(obj); |
| 1862 SetInternalReference(obj, entry, |
| 1863 "prototype", map->prototype(), Map::kPrototypeOffset); |
| 1864 SetInternalReference(obj, entry, |
| 1865 "constructor", map->constructor(), |
| 1866 Map::kConstructorOffset); |
| 1867 SetInternalReference(obj, entry, |
| 1868 "descriptors", map->instance_descriptors(), |
| 1869 Map::kInstanceDescriptorsOffset); |
| 1870 SetInternalReference(obj, entry, |
| 1871 "code_cache", map->code_cache(), |
| 1872 Map::kCodeCacheOffset); |
| 1873 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
| 1874 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
| 1875 obj->Iterate(&refs_extractor); |
| 1876 } else if (obj->IsSharedFunctionInfo()) { |
| 1877 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
| 1878 SetInternalReference(obj, entry, |
| 1879 "name", shared->name(), |
| 1880 SharedFunctionInfo::kNameOffset); |
| 1881 SetInternalReference(obj, entry, |
| 1882 "code", shared->unchecked_code(), |
| 1883 SharedFunctionInfo::kCodeOffset); |
| 1884 SetInternalReference(obj, entry, |
| 1885 "instance_class_name", shared->instance_class_name(), |
| 1886 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1887 SetInternalReference(obj, entry, |
| 1888 "script", shared->script(), |
| 1889 SharedFunctionInfo::kScriptOffset); |
| 1890 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
| 1891 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
| 1892 obj->Iterate(&refs_extractor); |
1835 } else { | 1893 } else { |
| 1894 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
1836 IndexedReferencesExtractor refs_extractor(this, obj, entry); | 1895 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
1837 obj->Iterate(&refs_extractor); | 1896 obj->Iterate(&refs_extractor); |
1838 } | 1897 } |
1839 } | 1898 } |
1840 | 1899 |
1841 | 1900 |
1842 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, | 1901 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, |
1843 HeapEntry* entry) { | 1902 HeapEntry* entry) { |
1844 if (js_obj->IsJSFunction()) { | 1903 if (js_obj->IsJSFunction()) { |
1845 HandleScope hs; | 1904 HandleScope hs; |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2300 | 2359 |
2301 | 2360 |
2302 void NativeObjectsExplorer::SetWrapperNativeReferences( | 2361 void NativeObjectsExplorer::SetWrapperNativeReferences( |
2303 HeapObject* wrapper, v8::RetainedObjectInfo* info) { | 2362 HeapObject* wrapper, v8::RetainedObjectInfo* info) { |
2304 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); | 2363 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); |
2305 ASSERT(wrapper_entry != NULL); | 2364 ASSERT(wrapper_entry != NULL); |
2306 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this); | 2365 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this); |
2307 ASSERT(info_entry != NULL); | 2366 ASSERT(info_entry != NULL); |
2308 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 2367 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
2309 wrapper, wrapper_entry, | 2368 wrapper, wrapper_entry, |
2310 "Native", | 2369 "native", |
2311 info, info_entry); | 2370 info, info_entry); |
2312 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, | 2371 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, |
2313 info, info_entry, | 2372 info, info_entry, |
2314 wrapper, wrapper_entry); | 2373 wrapper, wrapper_entry); |
2315 } | 2374 } |
2316 | 2375 |
2317 | 2376 |
2318 void NativeObjectsExplorer::SetRootNativesRootReference() { | 2377 void NativeObjectsExplorer::SetRootNativesRootReference() { |
2319 filler_->SetIndexedAutoIndexReference( | 2378 filler_->SetIndexedAutoIndexReference( |
2320 HeapGraphEdge::kElement, | 2379 HeapGraphEdge::kElement, |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3027 | 3086 |
3028 | 3087 |
3029 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3088 String* GetConstructorNameForHeapProfile(JSObject* object) { |
3030 if (object->IsJSFunction()) return HEAP->closure_symbol(); | 3089 if (object->IsJSFunction()) return HEAP->closure_symbol(); |
3031 return object->constructor_name(); | 3090 return object->constructor_name(); |
3032 } | 3091 } |
3033 | 3092 |
3034 } } // namespace v8::internal | 3093 } } // namespace v8::internal |
3035 | 3094 |
3036 #endif // ENABLE_LOGGING_AND_PROFILING | 3095 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |