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