OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 case ODDBALL_TYPE: return "system / Oddball"; | 1805 case ODDBALL_TYPE: return "system / Oddball"; |
1806 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1806 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
1807 case NAME##_TYPE: return "system / "#Name; | 1807 case NAME##_TYPE: return "system / "#Name; |
1808 STRUCT_LIST(MAKE_STRUCT_CASE) | 1808 STRUCT_LIST(MAKE_STRUCT_CASE) |
1809 #undef MAKE_STRUCT_CASE | 1809 #undef MAKE_STRUCT_CASE |
1810 default: return "system"; | 1810 default: return "system"; |
1811 } | 1811 } |
1812 } | 1812 } |
1813 | 1813 |
1814 | 1814 |
1815 int V8HeapExplorer::EstimateObjectsCount() { | 1815 int V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { |
1816 HeapIterator iterator(HeapIterator::kFilterUnreachable); | |
1817 int objects_count = 0; | 1816 int objects_count = 0; |
1818 for (HeapObject* obj = iterator.next(); | 1817 for (HeapObject* obj = iterator->next(); |
1819 obj != NULL; | 1818 obj != NULL; |
1820 obj = iterator.next(), ++objects_count) {} | 1819 obj = iterator->next()) { |
| 1820 objects_count++; |
| 1821 } |
1821 return objects_count; | 1822 return objects_count; |
1822 } | 1823 } |
1823 | 1824 |
1824 | 1825 |
1825 class IndexedReferencesExtractor : public ObjectVisitor { | 1826 class IndexedReferencesExtractor : public ObjectVisitor { |
1826 public: | 1827 public: |
1827 IndexedReferencesExtractor(V8HeapExplorer* generator, | 1828 IndexedReferencesExtractor(V8HeapExplorer* generator, |
1828 HeapObject* parent_obj, | 1829 HeapObject* parent_obj, |
1829 HeapEntry* parent_entry) | 1830 HeapEntry* parent_entry) |
1830 : generator_(generator), | 1831 : generator_(generator), |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 "prototype", map->prototype(), Map::kPrototypeOffset); | 1939 "prototype", map->prototype(), Map::kPrototypeOffset); |
1939 SetInternalReference(obj, entry, | 1940 SetInternalReference(obj, entry, |
1940 "constructor", map->constructor(), | 1941 "constructor", map->constructor(), |
1941 Map::kConstructorOffset); | 1942 Map::kConstructorOffset); |
1942 if (!map->instance_descriptors()->IsEmpty()) { | 1943 if (!map->instance_descriptors()->IsEmpty()) { |
1943 TagObject(map->instance_descriptors(), "(map descriptors)"); | 1944 TagObject(map->instance_descriptors(), "(map descriptors)"); |
1944 SetInternalReference(obj, entry, | 1945 SetInternalReference(obj, entry, |
1945 "descriptors", map->instance_descriptors(), | 1946 "descriptors", map->instance_descriptors(), |
1946 Map::kInstanceDescriptorsOrBitField3Offset); | 1947 Map::kInstanceDescriptorsOrBitField3Offset); |
1947 } | 1948 } |
| 1949 if (map->prototype_transitions() != heap_->empty_fixed_array()) { |
| 1950 TagObject(map->prototype_transitions(), "(prototype transitions)"); |
| 1951 SetInternalReference(obj, |
| 1952 entry, |
| 1953 "prototype_transitions", |
| 1954 map->prototype_transitions(), |
| 1955 Map::kPrototypeTransitionsOffset); |
| 1956 } |
1948 SetInternalReference(obj, entry, | 1957 SetInternalReference(obj, entry, |
1949 "code_cache", map->code_cache(), | 1958 "code_cache", map->code_cache(), |
1950 Map::kCodeCacheOffset); | 1959 Map::kCodeCacheOffset); |
1951 } else if (obj->IsSharedFunctionInfo()) { | 1960 } else if (obj->IsSharedFunctionInfo()) { |
1952 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 1961 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
1953 SetInternalReference(obj, entry, | 1962 SetInternalReference(obj, entry, |
1954 "name", shared->name(), | 1963 "name", shared->name(), |
1955 SharedFunctionInfo::kNameOffset); | 1964 SharedFunctionInfo::kNameOffset); |
1956 SetInternalReference(obj, entry, | 1965 SetInternalReference(obj, entry, |
1957 "code", shared->unchecked_code(), | 1966 "code", shared->unchecked_code(), |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2168 void VisitPointers(Object** start, Object** end) { | 2177 void VisitPointers(Object** start, Object** end) { |
2169 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2178 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); |
2170 } | 2179 } |
2171 private: | 2180 private: |
2172 V8HeapExplorer* explorer_; | 2181 V8HeapExplorer* explorer_; |
2173 }; | 2182 }; |
2174 | 2183 |
2175 | 2184 |
2176 bool V8HeapExplorer::IterateAndExtractReferences( | 2185 bool V8HeapExplorer::IterateAndExtractReferences( |
2177 SnapshotFillerInterface* filler) { | 2186 SnapshotFillerInterface* filler) { |
| 2187 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 2188 |
2178 filler_ = filler; | 2189 filler_ = filler; |
2179 HeapIterator iterator(HeapIterator::kFilterUnreachable); | |
2180 bool interrupted = false; | 2190 bool interrupted = false; |
| 2191 |
2181 // Heap iteration with filtering must be finished in any case. | 2192 // Heap iteration with filtering must be finished in any case. |
2182 for (HeapObject* obj = iterator.next(); | 2193 for (HeapObject* obj = iterator.next(); |
2183 obj != NULL; | 2194 obj != NULL; |
2184 obj = iterator.next(), progress_->ProgressStep()) { | 2195 obj = iterator.next(), progress_->ProgressStep()) { |
2185 if (!interrupted) { | 2196 if (!interrupted) { |
2186 ExtractReferences(obj); | 2197 ExtractReferences(obj); |
2187 if (!progress_->ProgressReport(false)) interrupted = true; | 2198 if (!progress_->ProgressReport(false)) interrupted = true; |
2188 } | 2199 } |
2189 } | 2200 } |
2190 if (interrupted) { | 2201 if (interrupted) { |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2736 private: | 2747 private: |
2737 HeapSnapshot* snapshot_; | 2748 HeapSnapshot* snapshot_; |
2738 HeapSnapshotsCollection* collection_; | 2749 HeapSnapshotsCollection* collection_; |
2739 HeapEntriesMap* entries_; | 2750 HeapEntriesMap* entries_; |
2740 }; | 2751 }; |
2741 | 2752 |
2742 | 2753 |
2743 bool HeapSnapshotGenerator::GenerateSnapshot() { | 2754 bool HeapSnapshotGenerator::GenerateSnapshot() { |
2744 v8_heap_explorer_.TagGlobalObjects(); | 2755 v8_heap_explorer_.TagGlobalObjects(); |
2745 | 2756 |
| 2757 // TODO(1562) Profiler assumes that any object that is in the heap after |
| 2758 // full GC is reachable from the root when computing dominators. |
| 2759 // This is not true for weakly reachable objects. |
| 2760 // As a temporary solution we call GC twice. |
| 2761 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2762 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2763 |
| 2764 #ifdef DEBUG |
| 2765 Heap* debug_heap = Isolate::Current()->heap(); |
| 2766 ASSERT(!debug_heap->old_data_space()->was_swept_conservatively()); |
| 2767 ASSERT(!debug_heap->old_pointer_space()->was_swept_conservatively()); |
| 2768 ASSERT(!debug_heap->code_space()->was_swept_conservatively()); |
| 2769 ASSERT(!debug_heap->cell_space()->was_swept_conservatively()); |
| 2770 ASSERT(!debug_heap->map_space()->was_swept_conservatively()); |
| 2771 #endif |
| 2772 |
| 2773 // The following code uses heap iterators, so we want the heap to be |
| 2774 // stable. It should follow TagGlobalObjects as that can allocate. |
2746 AssertNoAllocation no_alloc; | 2775 AssertNoAllocation no_alloc; |
2747 | 2776 |
| 2777 #ifdef DEBUG |
| 2778 debug_heap->Verify(); |
| 2779 #endif |
| 2780 |
2748 SetProgressTotal(4); // 2 passes + dominators + sizes. | 2781 SetProgressTotal(4); // 2 passes + dominators + sizes. |
2749 | 2782 |
| 2783 #ifdef DEBUG |
| 2784 debug_heap->Verify(); |
| 2785 #endif |
| 2786 |
2750 // Pass 1. Iterate heap contents to count entries and references. | 2787 // Pass 1. Iterate heap contents to count entries and references. |
2751 if (!CountEntriesAndReferences()) return false; | 2788 if (!CountEntriesAndReferences()) return false; |
2752 | 2789 |
| 2790 #ifdef DEBUG |
| 2791 debug_heap->Verify(); |
| 2792 #endif |
| 2793 |
2753 // Allocate and fill entries in the snapshot, allocate references. | 2794 // Allocate and fill entries in the snapshot, allocate references. |
2754 snapshot_->AllocateEntries(entries_.entries_count(), | 2795 snapshot_->AllocateEntries(entries_.entries_count(), |
2755 entries_.total_children_count(), | 2796 entries_.total_children_count(), |
2756 entries_.total_retainers_count()); | 2797 entries_.total_retainers_count()); |
2757 entries_.AllocateEntries(); | 2798 entries_.AllocateEntries(); |
2758 | 2799 |
2759 // Pass 2. Fill references. | 2800 // Pass 2. Fill references. |
2760 if (!FillReferences()) return false; | 2801 if (!FillReferences()) return false; |
2761 | 2802 |
2762 if (!SetEntriesDominators()) return false; | 2803 if (!SetEntriesDominators()) return false; |
(...skipping 17 matching lines...) Expand all Loading... |
2780 return | 2821 return |
2781 control_->ReportProgressValue(progress_counter_, progress_total_) == | 2822 control_->ReportProgressValue(progress_counter_, progress_total_) == |
2782 v8::ActivityControl::kContinue; | 2823 v8::ActivityControl::kContinue; |
2783 } | 2824 } |
2784 return true; | 2825 return true; |
2785 } | 2826 } |
2786 | 2827 |
2787 | 2828 |
2788 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { | 2829 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
2789 if (control_ == NULL) return; | 2830 if (control_ == NULL) return; |
| 2831 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
2790 progress_total_ = ( | 2832 progress_total_ = ( |
2791 v8_heap_explorer_.EstimateObjectsCount() + | 2833 v8_heap_explorer_.EstimateObjectsCount(&iterator) + |
2792 dom_explorer_.EstimateObjectsCount()) * iterations_count; | 2834 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
2793 progress_counter_ = 0; | 2835 progress_counter_ = 0; |
2794 } | 2836 } |
2795 | 2837 |
2796 | 2838 |
2797 bool HeapSnapshotGenerator::CountEntriesAndReferences() { | 2839 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
2798 SnapshotCounter counter(&entries_); | 2840 SnapshotCounter counter(&entries_); |
2799 v8_heap_explorer_.AddRootEntries(&counter); | 2841 v8_heap_explorer_.AddRootEntries(&counter); |
2800 dom_explorer_.AddRootEntries(&counter); | 2842 dom_explorer_.AddRootEntries(&counter); |
2801 return | 2843 return |
(...skipping 29 matching lines...) Expand all Loading... |
2831 child->paint_reachable(); | 2873 child->paint_reachable(); |
2832 has_new_edges = true; | 2874 has_new_edges = true; |
2833 } | 2875 } |
2834 } | 2876 } |
2835 if (!has_new_edges) { | 2877 if (!has_new_edges) { |
2836 entry->set_ordered_index(current_entry); | 2878 entry->set_ordered_index(current_entry); |
2837 (*entries)[current_entry++] = entry; | 2879 (*entries)[current_entry++] = entry; |
2838 nodes_to_visit.RemoveLast(); | 2880 nodes_to_visit.RemoveLast(); |
2839 } | 2881 } |
2840 } | 2882 } |
2841 entries->Truncate(current_entry); | 2883 ASSERT_EQ(current_entry, entries->length()); |
2842 } | 2884 } |
2843 | 2885 |
2844 | 2886 |
2845 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { | 2887 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
2846 int finger1 = i1, finger2 = i2; | 2888 int finger1 = i1, finger2 = i2; |
2847 while (finger1 != finger2) { | 2889 while (finger1 != finger2) { |
2848 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); | 2890 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
2849 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); | 2891 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
2850 } | 2892 } |
2851 return finger1; | 2893 return finger1; |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3326 | 3368 |
3327 | 3369 |
3328 void HeapSnapshotJSONSerializer::SortHashMap( | 3370 void HeapSnapshotJSONSerializer::SortHashMap( |
3329 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3371 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3330 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3372 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3331 sorted_entries->Add(p); | 3373 sorted_entries->Add(p); |
3332 sorted_entries->Sort(SortUsingEntryValue); | 3374 sorted_entries->Sort(SortUsingEntryValue); |
3333 } | 3375 } |
3334 | 3376 |
3335 } } // namespace v8::internal | 3377 } } // namespace v8::internal |
OLD | NEW |