OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 // garbage. | 886 // garbage. |
887 // Note: as weak callbacks can execute arbitrary code, we cannot | 887 // Note: as weak callbacks can execute arbitrary code, we cannot |
888 // hope that eventually there will be no weak callbacks invocations. | 888 // hope that eventually there will be no weak callbacks invocations. |
889 // Therefore stop recollecting after several attempts. | 889 // Therefore stop recollecting after several attempts. |
890 if (isolate()->concurrent_recompilation_enabled()) { | 890 if (isolate()->concurrent_recompilation_enabled()) { |
891 // The optimizing compiler may be unnecessarily holding on to memory. | 891 // The optimizing compiler may be unnecessarily holding on to memory. |
892 DisallowHeapAllocation no_recursive_gc; | 892 DisallowHeapAllocation no_recursive_gc; |
893 isolate()->optimizing_compile_dispatcher()->Flush(); | 893 isolate()->optimizing_compile_dispatcher()->Flush(); |
894 } | 894 } |
895 isolate()->ClearSerializerData(); | 895 isolate()->ClearSerializerData(); |
896 set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask); | 896 set_current_gc_flags(kAbortIncrementalMarkingMask | |
| 897 kReduceMemoryFootprintMask); |
897 isolate_->compilation_cache()->Clear(); | 898 isolate_->compilation_cache()->Clear(); |
898 const int kMaxNumberOfAttempts = 7; | 899 const int kMaxNumberOfAttempts = 7; |
899 const int kMinNumberOfAttempts = 2; | 900 const int kMinNumberOfAttempts = 2; |
900 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { | 901 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
901 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, | 902 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, |
902 v8::kGCCallbackFlagCollectAllAvailableGarbage) && | 903 v8::kGCCallbackFlagCollectAllAvailableGarbage) && |
903 attempt + 1 >= kMinNumberOfAttempts) { | 904 attempt + 1 >= kMinNumberOfAttempts) { |
904 break; | 905 break; |
905 } | 906 } |
906 } | 907 } |
(...skipping 3131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4038 Struct* result = nullptr; | 4039 Struct* result = nullptr; |
4039 { | 4040 { |
4040 AllocationResult allocation = Allocate(map, OLD_SPACE); | 4041 AllocationResult allocation = Allocate(map, OLD_SPACE); |
4041 if (!allocation.To(&result)) return allocation; | 4042 if (!allocation.To(&result)) return allocation; |
4042 } | 4043 } |
4043 result->InitializeBody(size); | 4044 result->InitializeBody(size); |
4044 return result; | 4045 return result; |
4045 } | 4046 } |
4046 | 4047 |
4047 | 4048 |
4048 bool Heap::IsHeapIterable() { | |
4049 // TODO(hpayer): This function is not correct. Allocation folding in old | |
4050 // space breaks the iterability. | |
4051 return new_space_top_after_last_gc_ == new_space()->top(); | |
4052 } | |
4053 | |
4054 | |
4055 void Heap::MakeHeapIterable() { | 4049 void Heap::MakeHeapIterable() { |
4056 DCHECK(AllowHeapAllocation::IsAllowed()); | |
4057 if (!IsHeapIterable()) { | |
4058 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); | |
4059 } | |
4060 if (mark_compact_collector()->sweeping_in_progress()) { | 4050 if (mark_compact_collector()->sweeping_in_progress()) { |
4061 mark_compact_collector()->EnsureSweepingCompleted(); | 4051 mark_compact_collector()->EnsureSweepingCompleted(); |
4062 } | 4052 } |
4063 DCHECK(IsHeapIterable()); | |
4064 } | 4053 } |
4065 | 4054 |
4066 | 4055 |
4067 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { | 4056 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { |
4068 const double kMinMutatorUtilization = 0.0; | 4057 const double kMinMutatorUtilization = 0.0; |
4069 const double kConservativeGcSpeedInBytesPerMillisecond = 200000; | 4058 const double kConservativeGcSpeedInBytesPerMillisecond = 200000; |
4070 if (mutator_speed == 0) return kMinMutatorUtilization; | 4059 if (mutator_speed == 0) return kMinMutatorUtilization; |
4071 if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond; | 4060 if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond; |
4072 // Derivation: | 4061 // Derivation: |
4073 // mutator_utilization = mutator_time / (mutator_time + gc_time) | 4062 // mutator_utilization = mutator_time / (mutator_time + gc_time) |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4598 return false; | 4587 return false; |
4599 } | 4588 } |
4600 } | 4589 } |
4601 | 4590 |
4602 | 4591 |
4603 #ifdef VERIFY_HEAP | 4592 #ifdef VERIFY_HEAP |
4604 void Heap::Verify() { | 4593 void Heap::Verify() { |
4605 CHECK(HasBeenSetUp()); | 4594 CHECK(HasBeenSetUp()); |
4606 HandleScope scope(isolate()); | 4595 HandleScope scope(isolate()); |
4607 | 4596 |
4608 if (mark_compact_collector()->sweeping_in_progress()) { | 4597 MakeHeapIterable(); |
4609 // We have to wait here for the sweeper threads to have an iterable heap. | |
4610 mark_compact_collector()->EnsureSweepingCompleted(); | |
4611 } | |
4612 | 4598 |
4613 VerifyPointersVisitor visitor; | 4599 VerifyPointersVisitor visitor; |
4614 IterateRoots(&visitor, VISIT_ONLY_STRONG); | 4600 IterateRoots(&visitor, VISIT_ONLY_STRONG); |
4615 | 4601 |
4616 VerifySmisVisitor smis_visitor; | 4602 VerifySmisVisitor smis_visitor; |
4617 IterateSmiRoots(&smis_visitor); | 4603 IterateSmiRoots(&smis_visitor); |
4618 | 4604 |
4619 new_space_.Verify(); | 4605 new_space_.Verify(); |
4620 | 4606 |
4621 old_space_->Verify(&visitor); | 4607 old_space_->Verify(&visitor); |
(...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5795 case LO_SPACE: | 5781 case LO_SPACE: |
5796 iterator_ = new LargeObjectIterator(heap_->lo_space()); | 5782 iterator_ = new LargeObjectIterator(heap_->lo_space()); |
5797 break; | 5783 break; |
5798 } | 5784 } |
5799 | 5785 |
5800 // Return the newly allocated iterator; | 5786 // Return the newly allocated iterator; |
5801 DCHECK(iterator_ != NULL); | 5787 DCHECK(iterator_ != NULL); |
5802 return iterator_; | 5788 return iterator_; |
5803 } | 5789 } |
5804 | 5790 |
5805 | 5791 HeapIterator::HeapIterator(Heap* heap, HeapObjectsFiltering filtering) |
5806 class HeapObjectsFilter { | 5792 : heap_(heap), space_iterator_(nullptr), object_iterator_(nullptr) { |
5807 public: | |
5808 virtual ~HeapObjectsFilter() {} | |
5809 virtual bool SkipObject(HeapObject* object) = 0; | |
5810 }; | |
5811 | |
5812 | |
5813 class UnreachableObjectsFilter : public HeapObjectsFilter { | |
5814 public: | |
5815 explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) { | |
5816 MarkReachableObjects(); | |
5817 } | |
5818 | |
5819 ~UnreachableObjectsFilter() { | |
5820 heap_->mark_compact_collector()->ClearMarkbits(); | |
5821 } | |
5822 | |
5823 bool SkipObject(HeapObject* object) { | |
5824 if (object->IsFiller()) return true; | |
5825 MarkBit mark_bit = Marking::MarkBitFrom(object); | |
5826 return Marking::IsWhite(mark_bit); | |
5827 } | |
5828 | |
5829 private: | |
5830 class MarkingVisitor : public ObjectVisitor { | |
5831 public: | |
5832 MarkingVisitor() : marking_stack_(10) {} | |
5833 | |
5834 void VisitPointers(Object** start, Object** end) override { | |
5835 for (Object** p = start; p < end; p++) { | |
5836 if (!(*p)->IsHeapObject()) continue; | |
5837 HeapObject* obj = HeapObject::cast(*p); | |
5838 MarkBit mark_bit = Marking::MarkBitFrom(obj); | |
5839 if (Marking::IsWhite(mark_bit)) { | |
5840 Marking::WhiteToBlack(mark_bit); | |
5841 marking_stack_.Add(obj); | |
5842 } | |
5843 } | |
5844 } | |
5845 | |
5846 void TransitiveClosure() { | |
5847 while (!marking_stack_.is_empty()) { | |
5848 HeapObject* obj = marking_stack_.RemoveLast(); | |
5849 obj->Iterate(this); | |
5850 } | |
5851 } | |
5852 | |
5853 private: | |
5854 List<HeapObject*> marking_stack_; | |
5855 }; | |
5856 | |
5857 void MarkReachableObjects() { | |
5858 MarkingVisitor visitor; | |
5859 heap_->IterateRoots(&visitor, VISIT_ALL); | |
5860 visitor.TransitiveClosure(); | |
5861 } | |
5862 | |
5863 Heap* heap_; | |
5864 DisallowHeapAllocation no_allocation_; | |
5865 }; | |
5866 | |
5867 | |
5868 HeapIterator::HeapIterator(Heap* heap, | |
5869 HeapIterator::HeapObjectsFiltering filtering) | |
5870 : make_heap_iterable_helper_(heap), | |
5871 no_heap_allocation_(), | |
5872 heap_(heap), | |
5873 filtering_(filtering), | |
5874 filter_(nullptr), | |
5875 space_iterator_(nullptr), | |
5876 object_iterator_(nullptr) { | |
5877 heap_->heap_iterator_start(); | 5793 heap_->heap_iterator_start(); |
5878 // Start the iteration. | 5794 // Start the iteration. |
5879 space_iterator_ = new SpaceIterator(heap_); | 5795 space_iterator_ = new SpaceIterator(heap_); |
5880 switch (filtering_) { | 5796 switch (filtering) { |
5881 case kFilterUnreachable: | 5797 case HeapObjectsFiltering::kFilterUnreachable: |
5882 filter_ = new UnreachableObjectsFilter(heap_); | 5798 heap_->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask, |
| 5799 "filter unreachable objects"); |
5883 break; | 5800 break; |
5884 default: | 5801 default: |
5885 break; | 5802 break; |
5886 } | 5803 } |
| 5804 heap_->MakeHeapIterable(); |
| 5805 disallow_heap_allocation_ = new DisallowHeapAllocation(); |
5887 object_iterator_ = space_iterator_->next(); | 5806 object_iterator_ = space_iterator_->next(); |
5888 } | 5807 } |
5889 | 5808 |
5890 | 5809 |
5891 HeapIterator::~HeapIterator() { | 5810 HeapIterator::~HeapIterator() { |
5892 heap_->heap_iterator_end(); | 5811 heap_->heap_iterator_end(); |
5893 #ifdef DEBUG | |
5894 // Assert that in filtering mode we have iterated through all | |
5895 // objects. Otherwise, heap will be left in an inconsistent state. | |
5896 if (filtering_ != kNoFiltering) { | |
5897 DCHECK(object_iterator_ == nullptr); | |
5898 } | |
5899 #endif | |
5900 // Make sure the last iterator is deallocated. | 5812 // Make sure the last iterator is deallocated. |
5901 delete object_iterator_; | 5813 delete object_iterator_; |
5902 delete space_iterator_; | 5814 delete space_iterator_; |
5903 delete filter_; | 5815 delete disallow_heap_allocation_; |
5904 } | 5816 } |
5905 | 5817 |
5906 | 5818 |
5907 HeapObject* HeapIterator::next() { | 5819 HeapObject* HeapIterator::next() { |
5908 if (filter_ == nullptr) return NextObject(); | |
5909 | |
5910 HeapObject* obj = NextObject(); | |
5911 while ((obj != nullptr) && (filter_->SkipObject(obj))) obj = NextObject(); | |
5912 return obj; | |
5913 } | |
5914 | |
5915 | |
5916 HeapObject* HeapIterator::NextObject() { | |
5917 // No iterator means we are done. | 5820 // No iterator means we are done. |
5918 if (object_iterator_ == nullptr) return nullptr; | 5821 if (object_iterator_ == nullptr) return nullptr; |
5919 | 5822 |
5920 if (HeapObject* obj = object_iterator_->next_object()) { | 5823 if (HeapObject* obj = object_iterator_->next_object()) { |
5921 // If the current iterator has more objects we are fine. | 5824 // If the current iterator has more objects we are fine. |
5922 return obj; | 5825 return obj; |
5923 } else { | 5826 } else { |
5924 // Go though the spaces looking for one that has objects. | 5827 // Go though the spaces looking for one that has objects. |
5925 while (space_iterator_->has_next()) { | 5828 while (space_iterator_->has_next()) { |
5926 object_iterator_ = space_iterator_->next(); | 5829 object_iterator_ = space_iterator_->next(); |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6360 } | 6263 } |
6361 | 6264 |
6362 | 6265 |
6363 // static | 6266 // static |
6364 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6267 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6365 return StaticVisitorBase::GetVisitorId(map); | 6268 return StaticVisitorBase::GetVisitorId(map); |
6366 } | 6269 } |
6367 | 6270 |
6368 } // namespace internal | 6271 } // namespace internal |
6369 } // namespace v8 | 6272 } // namespace v8 |
OLD | NEW |