| 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 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1779 case NAME##_TYPE: return "system / "#Name; | 1779 case NAME##_TYPE: return "system / "#Name; |
| 1780 STRUCT_LIST(MAKE_STRUCT_CASE) | 1780 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 1781 #undef MAKE_STRUCT_CASE | 1781 #undef MAKE_STRUCT_CASE |
| 1782 default: return "system"; | 1782 default: return "system"; |
| 1783 } | 1783 } |
| 1784 } | 1784 } |
| 1785 | 1785 |
| 1786 | 1786 |
| 1787 int V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { | 1787 int V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { |
| 1788 int objects_count = 0; | 1788 int objects_count = 0; |
| 1789 for (HeapObject* obj = iterator->Next(); | 1789 for (HeapObject* obj = iterator->next(); |
| 1790 obj != NULL; | 1790 obj != NULL; |
| 1791 obj = iterator->Next(), ++objects_count) {} | 1791 obj = iterator->next()) { |
| 1792 objects_count++; |
| 1793 } |
| 1792 return objects_count; | 1794 return objects_count; |
| 1793 } | 1795 } |
| 1794 | 1796 |
| 1795 | 1797 |
| 1796 class IndexedReferencesExtractor : public ObjectVisitor { | 1798 class IndexedReferencesExtractor : public ObjectVisitor { |
| 1797 public: | 1799 public: |
| 1798 IndexedReferencesExtractor(V8HeapExplorer* generator, | 1800 IndexedReferencesExtractor(V8HeapExplorer* generator, |
| 1799 HeapObject* parent_obj, | 1801 HeapObject* parent_obj, |
| 1800 HeapEntry* parent_entry) | 1802 HeapEntry* parent_entry) |
| 1801 : generator_(generator), | 1803 : generator_(generator), |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 } | 2123 } |
| 2122 void VisitPointers(Object** start, Object** end) { | 2124 void VisitPointers(Object** start, Object** end) { |
| 2123 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2125 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); |
| 2124 } | 2126 } |
| 2125 private: | 2127 private: |
| 2126 V8HeapExplorer* explorer_; | 2128 V8HeapExplorer* explorer_; |
| 2127 }; | 2129 }; |
| 2128 | 2130 |
| 2129 | 2131 |
| 2130 bool V8HeapExplorer::IterateAndExtractReferences( | 2132 bool V8HeapExplorer::IterateAndExtractReferences( |
| 2131 HeapIterator* iterator, | |
| 2132 SnapshotFillerInterface* filler) { | 2133 SnapshotFillerInterface* filler) { |
| 2134 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 2135 |
| 2133 filler_ = filler; | 2136 filler_ = filler; |
| 2134 bool interrupted = false; | 2137 bool interrupted = false; |
| 2135 | 2138 |
| 2136 // Heap iteration with filtering must be finished in any case. | 2139 // Heap iteration with filtering must be finished in any case. |
| 2137 for (HeapObject* obj = iterator->Next(); | 2140 for (HeapObject* obj = iterator.next(); |
| 2138 obj != NULL; | 2141 obj != NULL; |
| 2139 obj = iterator->Next(), progress_->ProgressStep()) { | 2142 obj = iterator.next(), progress_->ProgressStep()) { |
| 2140 if (!interrupted) { | 2143 if (!interrupted) { |
| 2141 ExtractReferences(obj); | 2144 ExtractReferences(obj); |
| 2142 if (!progress_->ProgressReport(false)) interrupted = true; | 2145 if (!progress_->ProgressReport(false)) interrupted = true; |
| 2143 } | 2146 } |
| 2144 } | 2147 } |
| 2145 if (interrupted) { | 2148 if (interrupted) { |
| 2146 filler_ = NULL; | 2149 filler_ = NULL; |
| 2147 return false; | 2150 return false; |
| 2148 } | 2151 } |
| 2149 SetRootGcRootsReference(); | 2152 SetRootGcRootsReference(); |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2698 bool HeapSnapshotGenerator::GenerateSnapshot() { | 2701 bool HeapSnapshotGenerator::GenerateSnapshot() { |
| 2699 v8_heap_explorer_.TagGlobalObjects(); | 2702 v8_heap_explorer_.TagGlobalObjects(); |
| 2700 | 2703 |
| 2701 // TODO(gc) Profiler assumes that any object that is in the heap after | 2704 // TODO(gc) Profiler assumes that any object that is in the heap after |
| 2702 // full GC is reachable from the root when computing dominators. | 2705 // full GC is reachable from the root when computing dominators. |
| 2703 // This is not true for weakly reachable objects. | 2706 // This is not true for weakly reachable objects. |
| 2704 // As a temporary solution we call GC twice. | 2707 // As a temporary solution we call GC twice. |
| 2705 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); | 2708 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2706 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); | 2709 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2707 | 2710 |
| 2708 // Iterator creation should follow TagGlobalObjects as it can allocate. | 2711 #ifdef DEBUG |
| 2709 HeapIterator set_progress_heap_iterator; | 2712 Heap* debug_heap = Isolate::Current()->heap(); |
| 2710 HeapIterator count_entries_heap_iterator; | 2713 ASSERT(!debug_heap->old_data_space()->was_swept_conservatively()); |
| 2711 HeapIterator fill_references_heap_iterator; | 2714 ASSERT(!debug_heap->old_pointer_space()->was_swept_conservatively()); |
| 2715 ASSERT(!debug_heap->code_space()->was_swept_conservatively()); |
| 2716 ASSERT(!debug_heap->cell_space()->was_swept_conservatively()); |
| 2717 ASSERT(!debug_heap->map_space()->was_swept_conservatively()); |
| 2718 #endif |
| 2712 | 2719 |
| 2720 // The following code uses heap iterators, so we want the heap to be |
| 2721 // stable. It should follow TagGlobalObjects as that can allocate. |
| 2713 AssertNoAllocation no_alloc; | 2722 AssertNoAllocation no_alloc; |
| 2714 | 2723 |
| 2715 SetProgressTotal(&set_progress_heap_iterator, | 2724 #ifdef DEBUG |
| 2716 4); // 2 passes + dominators + sizes. | 2725 debug_heap->Verify(); |
| 2726 #endif |
| 2727 |
| 2728 SetProgressTotal(4); // 2 passes + dominators + sizes. |
| 2729 |
| 2730 #ifdef DEBUG |
| 2731 debug_heap->Verify(); |
| 2732 #endif |
| 2717 | 2733 |
| 2718 // Pass 1. Iterate heap contents to count entries and references. | 2734 // Pass 1. Iterate heap contents to count entries and references. |
| 2719 if (!CountEntriesAndReferences(&count_entries_heap_iterator)) return false; | 2735 if (!CountEntriesAndReferences()) return false; |
| 2736 |
| 2737 #ifdef DEBUG |
| 2738 debug_heap->Verify(); |
| 2739 #endif |
| 2720 | 2740 |
| 2721 // Allocate and fill entries in the snapshot, allocate references. | 2741 // Allocate and fill entries in the snapshot, allocate references. |
| 2722 snapshot_->AllocateEntries(entries_.entries_count(), | 2742 snapshot_->AllocateEntries(entries_.entries_count(), |
| 2723 entries_.total_children_count(), | 2743 entries_.total_children_count(), |
| 2724 entries_.total_retainers_count()); | 2744 entries_.total_retainers_count()); |
| 2725 entries_.AllocateEntries(); | 2745 entries_.AllocateEntries(); |
| 2726 | 2746 |
| 2727 // Pass 2. Fill references. | 2747 // Pass 2. Fill references. |
| 2728 if (!FillReferences(&fill_references_heap_iterator)) return false; | 2748 if (!FillReferences()) return false; |
| 2729 | 2749 |
| 2730 if (!SetEntriesDominators()) return false; | 2750 if (!SetEntriesDominators()) return false; |
| 2731 if (!ApproximateRetainedSizes()) return false; | 2751 if (!ApproximateRetainedSizes()) return false; |
| 2732 | 2752 |
| 2733 progress_counter_ = progress_total_; | 2753 progress_counter_ = progress_total_; |
| 2734 if (!ProgressReport(true)) return false; | 2754 if (!ProgressReport(true)) return false; |
| 2735 return true; | 2755 return true; |
| 2736 } | 2756 } |
| 2737 | 2757 |
| 2738 | 2758 |
| 2739 void HeapSnapshotGenerator::ProgressStep() { | 2759 void HeapSnapshotGenerator::ProgressStep() { |
| 2740 ++progress_counter_; | 2760 ++progress_counter_; |
| 2741 } | 2761 } |
| 2742 | 2762 |
| 2743 | 2763 |
| 2744 bool HeapSnapshotGenerator::ProgressReport(bool force) { | 2764 bool HeapSnapshotGenerator::ProgressReport(bool force) { |
| 2745 const int kProgressReportGranularity = 10000; | 2765 const int kProgressReportGranularity = 10000; |
| 2746 if (control_ != NULL | 2766 if (control_ != NULL |
| 2747 && (force || progress_counter_ % kProgressReportGranularity == 0)) { | 2767 && (force || progress_counter_ % kProgressReportGranularity == 0)) { |
| 2748 return | 2768 return |
| 2749 control_->ReportProgressValue(progress_counter_, progress_total_) == | 2769 control_->ReportProgressValue(progress_counter_, progress_total_) == |
| 2750 v8::ActivityControl::kContinue; | 2770 v8::ActivityControl::kContinue; |
| 2751 } | 2771 } |
| 2752 return true; | 2772 return true; |
| 2753 } | 2773 } |
| 2754 | 2774 |
| 2755 | 2775 |
| 2756 void HeapSnapshotGenerator::SetProgressTotal(HeapIterator* iterator, | 2776 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
| 2757 int iterations_count) { | |
| 2758 if (control_ == NULL) return; | 2777 if (control_ == NULL) return; |
| 2778 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 2759 progress_total_ = ( | 2779 progress_total_ = ( |
| 2760 v8_heap_explorer_.EstimateObjectsCount(iterator) + | 2780 v8_heap_explorer_.EstimateObjectsCount(&iterator) + |
| 2761 dom_explorer_.EstimateObjectsCount()) * iterations_count; | 2781 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
| 2762 progress_counter_ = 0; | 2782 progress_counter_ = 0; |
| 2763 } | 2783 } |
| 2764 | 2784 |
| 2765 | 2785 |
| 2766 bool HeapSnapshotGenerator::CountEntriesAndReferences(HeapIterator* iterator) { | 2786 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
| 2767 SnapshotCounter counter(&entries_); | 2787 SnapshotCounter counter(&entries_); |
| 2768 v8_heap_explorer_.AddRootEntries(&counter); | 2788 v8_heap_explorer_.AddRootEntries(&counter); |
| 2769 dom_explorer_.AddRootEntries(&counter); | 2789 dom_explorer_.AddRootEntries(&counter); |
| 2770 return | 2790 return |
| 2771 v8_heap_explorer_.IterateAndExtractReferences(iterator, &counter) && | 2791 v8_heap_explorer_.IterateAndExtractReferences(&counter) && |
| 2772 dom_explorer_.IterateAndExtractReferences(&counter); | 2792 dom_explorer_.IterateAndExtractReferences(&counter); |
| 2773 } | 2793 } |
| 2774 | 2794 |
| 2775 | 2795 |
| 2776 bool HeapSnapshotGenerator::FillReferences(HeapIterator* iterator) { | 2796 bool HeapSnapshotGenerator::FillReferences() { |
| 2777 SnapshotFiller filler(snapshot_, &entries_); | 2797 SnapshotFiller filler(snapshot_, &entries_); |
| 2778 return | 2798 return |
| 2779 v8_heap_explorer_.IterateAndExtractReferences(iterator, &filler) && | 2799 v8_heap_explorer_.IterateAndExtractReferences(&filler) && |
| 2780 dom_explorer_.IterateAndExtractReferences(&filler); | 2800 dom_explorer_.IterateAndExtractReferences(&filler); |
| 2781 } | 2801 } |
| 2782 | 2802 |
| 2783 | 2803 |
| 2784 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 2804 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
| 2785 Vector<HeapEntry*>* entries) { | 2805 Vector<HeapEntry*>* entries) { |
| 2786 snapshot_->ClearPaint(); | 2806 snapshot_->ClearPaint(); |
| 2787 int current_entry = 0; | 2807 int current_entry = 0; |
| 2788 List<HeapEntry*> nodes_to_visit; | 2808 List<HeapEntry*> nodes_to_visit; |
| 2789 nodes_to_visit.Add(snapshot_->root()); | 2809 nodes_to_visit.Add(snapshot_->root()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2800 child->paint_reachable(); | 2820 child->paint_reachable(); |
| 2801 has_new_edges = true; | 2821 has_new_edges = true; |
| 2802 } | 2822 } |
| 2803 } | 2823 } |
| 2804 if (!has_new_edges) { | 2824 if (!has_new_edges) { |
| 2805 entry->set_ordered_index(current_entry); | 2825 entry->set_ordered_index(current_entry); |
| 2806 (*entries)[current_entry++] = entry; | 2826 (*entries)[current_entry++] = entry; |
| 2807 nodes_to_visit.RemoveLast(); | 2827 nodes_to_visit.RemoveLast(); |
| 2808 } | 2828 } |
| 2809 } | 2829 } |
| 2810 entries->Truncate(current_entry); | 2830 ASSERT_EQ(current_entry, entries->length()); |
| 2811 } | 2831 } |
| 2812 | 2832 |
| 2813 | 2833 |
| 2814 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { | 2834 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
| 2815 int finger1 = i1, finger2 = i2; | 2835 int finger1 = i1, finger2 = i2; |
| 2816 while (finger1 != finger2) { | 2836 while (finger1 != finger2) { |
| 2817 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); | 2837 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
| 2818 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); | 2838 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
| 2819 } | 2839 } |
| 2820 return finger1; | 2840 return finger1; |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3272 sorted_entries->Sort(SortUsingEntryValue); | 3292 sorted_entries->Sort(SortUsingEntryValue); |
| 3273 } | 3293 } |
| 3274 | 3294 |
| 3275 | 3295 |
| 3276 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3296 String* GetConstructorNameForHeapProfile(JSObject* object) { |
| 3277 if (object->IsJSFunction()) return HEAP->closure_symbol(); | 3297 if (object->IsJSFunction()) return HEAP->closure_symbol(); |
| 3278 return object->constructor_name(); | 3298 return object->constructor_name(); |
| 3279 } | 3299 } |
| 3280 | 3300 |
| 3281 } } // namespace v8::internal | 3301 } } // namespace v8::internal |
| OLD | NEW |