| 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 |