Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/scavenger.h" | 5 #include "vm/scavenger.h" |
| 6 | 6 |
| 7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
| 8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 intptr_t max_semi_capacity_in_words, | 317 intptr_t max_semi_capacity_in_words, |
| 318 uword object_alignment) | 318 uword object_alignment) |
| 319 : heap_(heap), | 319 : heap_(heap), |
| 320 max_semi_capacity_in_words_(max_semi_capacity_in_words), | 320 max_semi_capacity_in_words_(max_semi_capacity_in_words), |
| 321 object_alignment_(object_alignment), | 321 object_alignment_(object_alignment), |
| 322 scavenging_(false), | 322 scavenging_(false), |
| 323 delayed_weak_properties_(NULL), | 323 delayed_weak_properties_(NULL), |
| 324 gc_time_micros_(0), | 324 gc_time_micros_(0), |
| 325 collections_(0), | 325 collections_(0), |
| 326 external_size_(0), | 326 external_size_(0), |
| 327 failed_to_promote_(false) { | 327 failed_to_promote_(false), |
| 328 space_lock_(new Mutex()) { | |
| 328 // Verify assumptions about the first word in objects which the scavenger is | 329 // Verify assumptions about the first word in objects which the scavenger is |
| 329 // going to use for forwarding pointers. | 330 // going to use for forwarding pointers. |
| 330 ASSERT(Object::tags_offset() == 0); | 331 ASSERT(Object::tags_offset() == 0); |
| 331 | 332 |
| 332 // Set initial size resulting in a total of three different levels. | 333 // Set initial size resulting in a total of three different levels. |
| 333 const intptr_t initial_semi_capacity_in_words = | 334 const intptr_t initial_semi_capacity_in_words = |
| 334 max_semi_capacity_in_words / | 335 max_semi_capacity_in_words / |
| 335 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); | 336 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); |
| 336 | 337 |
| 337 const intptr_t kVmNameSize = 128; | 338 const intptr_t kVmNameSize = 128; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 348 | 349 |
| 349 survivor_end_ = FirstObjectStart(); | 350 survivor_end_ = FirstObjectStart(); |
| 350 | 351 |
| 351 UpdateMaxHeapCapacity(); | 352 UpdateMaxHeapCapacity(); |
| 352 UpdateMaxHeapUsage(); | 353 UpdateMaxHeapUsage(); |
| 353 } | 354 } |
| 354 | 355 |
| 355 Scavenger::~Scavenger() { | 356 Scavenger::~Scavenger() { |
| 356 ASSERT(!scavenging_); | 357 ASSERT(!scavenging_); |
| 357 to_->Delete(); | 358 to_->Delete(); |
| 359 delete space_lock_; | |
| 358 } | 360 } |
| 359 | 361 |
| 360 intptr_t Scavenger::NewSizeInWords(intptr_t old_size_in_words) const { | 362 intptr_t Scavenger::NewSizeInWords(intptr_t old_size_in_words) const { |
| 361 if (stats_history_.Size() == 0) { | 363 if (stats_history_.Size() == 0) { |
| 362 return old_size_in_words; | 364 return old_size_in_words; |
| 363 } | 365 } |
| 364 double garbage = stats_history_.Get(0).GarbageFraction(); | 366 double garbage = stats_history_.Get(0).GarbageFraction(); |
| 365 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { | 367 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { |
| 366 return Utils::Minimum(max_semi_capacity_in_words_, | 368 return Utils::Minimum(max_semi_capacity_in_words_, |
| 367 old_size_in_words * FLAG_new_gen_growth_factor); | 369 old_size_in_words * FLAG_new_gen_growth_factor); |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 #endif // defined(DEBUG) | 710 #endif // defined(DEBUG) |
| 709 | 711 |
| 710 WeakProperty::Clear(cur_weak); | 712 WeakProperty::Clear(cur_weak); |
| 711 | 713 |
| 712 // Advance to next weak property in the queue. | 714 // Advance to next weak property in the queue. |
| 713 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | 715 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
| 714 } | 716 } |
| 715 } | 717 } |
| 716 } | 718 } |
| 717 | 719 |
| 718 uword Scavenger::FlushTLS() const { | 720 void Scavenger::MakeALLTLABsIterable(Isolate* isolate) const { |
|
rmacnak
2017/08/02 20:50:59
All (lowercase Ls)
| |
| 719 ASSERT(heap_ != NULL); | 721 MonitorLocker ml(isolate->threads_lock(), false); |
| 720 uword saved_top = top_; | 722 Thread* current = heap_->isolate()->thread_registry()->active_list(); |
| 721 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | 723 while (current != NULL) { |
| 722 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 724 if (current->HasActiveTLAB()) { |
| 723 saved_top = mutator_thread->heap()->new_space()->top(); | 725 heap_->MakeTLABIterable(current); |
| 724 if (mutator_thread->HasActiveTLAB()) { | |
| 725 ASSERT(mutator_thread->top() <= | |
| 726 mutator_thread->heap()->new_space()->top()); | |
| 727 mutator_thread->heap()->new_space()->set_top(mutator_thread->top()); | |
| 728 } | 726 } |
| 727 current = current->next(); | |
| 729 } | 728 } |
| 730 return saved_top; | |
| 731 } | 729 } |
| 732 | 730 |
| 733 void Scavenger::UnflushTLS(uword value) const { | 731 void Scavenger::FlushTLS() const { |
| 734 ASSERT(heap_ != NULL); | 732 ASSERT(heap_ != NULL); |
| 735 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | 733 if (!scavenging_) { |
| 736 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 734 MakeALLTLABsIterable(heap_->isolate()); |
| 737 mutator_thread->heap()->new_space()->set_top(value); | 735 } |
| 738 ASSERT(mutator_thread->top() <= mutator_thread->heap()->new_space()->top()); | 736 } |
| 737 | |
| 738 void Scavenger::AbandonAllTLABs(Isolate* isolate) { | |
| 739 MonitorLocker ml(isolate->threads_lock(), false); | |
| 740 Thread* current = isolate->thread_registry()->active_list(); | |
| 741 while (current != NULL) { | |
| 742 heap_->AbandonRemainingTLAB(current); | |
| 743 current = current->next(); | |
| 739 } | 744 } |
| 740 } | 745 } |
| 741 | 746 |
| 742 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 747 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 743 uword saved_top = FlushTLS(); | 748 FlushTLS(); |
| 744 uword cur = FirstObjectStart(); | 749 uword cur = FirstObjectStart(); |
| 745 while (cur < top_) { | 750 while (cur < top_) { |
| 746 RawObject* raw_obj = RawObject::FromAddr(cur); | 751 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 747 cur += raw_obj->VisitPointers(visitor); | 752 cur += raw_obj->VisitPointers(visitor); |
| 748 } | 753 } |
| 749 UnflushTLS(saved_top); | |
| 750 } | 754 } |
| 751 | 755 |
| 752 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 756 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
| 753 uword saved_top = FlushTLS(); | 757 FlushTLS(); |
| 754 uword cur = FirstObjectStart(); | 758 uword cur = FirstObjectStart(); |
| 755 while (cur < top_) { | 759 while (cur < top_) { |
| 756 RawObject* raw_obj = RawObject::FromAddr(cur); | 760 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 757 visitor->VisitObject(raw_obj); | 761 visitor->VisitObject(raw_obj); |
| 758 cur += raw_obj->Size(); | 762 cur += raw_obj->Size(); |
| 759 } | 763 } |
| 760 UnflushTLS(saved_top); | |
| 761 } | 764 } |
| 762 | 765 |
| 763 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { | 766 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { |
| 764 set->AddRegion(to_->start(), to_->end()); | 767 set->AddRegion(to_->start(), to_->end()); |
| 765 } | 768 } |
| 766 | 769 |
| 767 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { | 770 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { |
| 768 ASSERT(!scavenging_); | 771 ASSERT(!scavenging_); |
| 769 uword saved_top = FlushTLS(); | 772 FlushTLS(); |
| 770 uword cur = FirstObjectStart(); | 773 uword cur = FirstObjectStart(); |
| 771 if (visitor->VisitRange(cur, top_)) { | 774 if (visitor->VisitRange(cur, top_)) { |
| 772 while (cur < top_) { | 775 while (cur < top_) { |
| 773 RawObject* raw_obj = RawObject::FromAddr(cur); | 776 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 774 uword next = cur + raw_obj->Size(); | 777 uword next = cur + raw_obj->Size(); |
| 775 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { | 778 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { |
| 776 UnflushTLS(saved_top); | |
| 777 return raw_obj; // Found object, return it. | 779 return raw_obj; // Found object, return it. |
| 778 } | 780 } |
| 779 cur = next; | 781 cur = next; |
| 780 } | 782 } |
| 781 ASSERT(cur == top_); | 783 ASSERT(cur == top_); |
| 782 } | 784 } |
| 783 UnflushTLS(saved_top); | |
| 784 return Object::null(); | 785 return Object::null(); |
| 785 } | 786 } |
| 786 | 787 |
| 787 void Scavenger::Scavenge() { | 788 void Scavenger::Scavenge() { |
| 788 // TODO(cshapiro): Add a decision procedure for determining when the | 789 // TODO(cshapiro): Add a decision procedure for determining when the |
| 789 // the API callbacks should be invoked. | 790 // the API callbacks should be invoked. |
| 790 Scavenge(false); | 791 Scavenge(false); |
| 791 } | 792 } |
| 792 | 793 |
| 793 void Scavenger::Scavenge(bool invoke_api_callbacks) { | 794 void Scavenger::Scavenge(bool invoke_api_callbacks) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 808 scavenging_ = true; | 809 scavenging_ = true; |
| 809 | 810 |
| 810 failed_to_promote_ = false; | 811 failed_to_promote_ = false; |
| 811 | 812 |
| 812 PageSpace* page_space = heap_->old_space(); | 813 PageSpace* page_space = heap_->old_space(); |
| 813 NoSafepointScope no_safepoints; | 814 NoSafepointScope no_safepoints; |
| 814 | 815 |
| 815 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 816 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
| 816 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 817 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
| 817 | 818 |
| 818 if (isolate->IsMutatorThreadScheduled()) { | 819 AbandonAllTLABs(isolate); |
| 819 Thread* mutator_thread = isolate->mutator_thread(); | |
| 820 if (mutator_thread->HasActiveTLAB()) { | |
| 821 heap_->AbandonRemainingTLAB(mutator_thread); | |
| 822 } | |
| 823 } | |
| 824 | 820 |
| 825 // TODO(koda): Make verification more compatible with concurrent sweep. | 821 // TODO(koda): Make verification more compatible with concurrent sweep. |
| 826 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 822 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
| 827 OS::PrintErr("Verifying before Scavenge..."); | 823 OS::PrintErr("Verifying before Scavenge..."); |
| 828 heap_->Verify(kForbidMarked); | 824 heap_->Verify(kForbidMarked); |
| 829 OS::PrintErr(" done.\n"); | 825 OS::PrintErr(" done.\n"); |
| 830 } | 826 } |
| 831 | 827 |
| 832 // Prepare for a scavenge. | 828 // Prepare for a scavenge. |
| 833 SpaceUsage usage_before = GetCurrentUsage(); | 829 SpaceUsage usage_before = GetCurrentUsage(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 } | 937 } |
| 942 } | 938 } |
| 943 | 939 |
| 944 Scavenge(); | 940 Scavenge(); |
| 945 | 941 |
| 946 // It is possible for objects to stay in the new space | 942 // It is possible for objects to stay in the new space |
| 947 // if the VM cannot create more pages for these objects. | 943 // if the VM cannot create more pages for these objects. |
| 948 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 944 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
| 949 } | 945 } |
| 950 | 946 |
| 947 uword Scavenger::FindTopOfSpace(Isolate* isolate) const { | |
| 948 MonitorLocker ml(isolate->threads_lock(), false); | |
| 949 Thread* current = heap_->isolate()->thread_registry()->active_list(); | |
| 950 uword furthest_addr = 0; | |
| 951 while (current != NULL) { | |
| 952 if (current->HasActiveTLAB() && current->top() > furthest_addr) { | |
| 953 furthest_addr = current->top(); | |
| 954 } | |
| 955 current = current->next(); | |
| 956 } | |
| 957 if (furthest_addr == 0) { | |
| 958 return top_; | |
| 959 } | |
| 960 return furthest_addr; | |
| 961 } | |
| 962 | |
| 951 int64_t Scavenger::UsedInWords() const { | 963 int64_t Scavenger::UsedInWords() const { |
| 952 uword saved_top = FlushTLS(); | 964 uword top_of_space = FindTopOfSpace(heap_->isolate()); |
| 953 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; | 965 int64_t used_in_words = (top_of_space - FirstObjectStart()) >> kWordSizeLog2; |
| 954 UnflushTLS(saved_top); | |
| 955 return used_in_words; | 966 return used_in_words; |
| 956 } | 967 } |
| 957 | 968 |
| 958 } // namespace dart | 969 } // namespace dart |
| OLD | NEW |