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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 705 #endif // defined(DEBUG) | 707 #endif // defined(DEBUG) |
| 706 | 708 |
| 707 WeakProperty::Clear(cur_weak); | 709 WeakProperty::Clear(cur_weak); |
| 708 | 710 |
| 709 // Advance to next weak property in the queue. | 711 // Advance to next weak property in the queue. |
| 710 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | 712 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
| 711 } | 713 } |
| 712 } | 714 } |
| 713 } | 715 } |
| 714 | 716 |
| 717 void Scavenger::MakeAllTLABsIterable(Isolate* isolate) const { | |
| 718 MonitorLocker ml(isolate->threads_lock(), false); | |
| 719 Thread* current = heap_->isolate()->thread_registry()->active_list(); | |
| 720 while (current != NULL) { | |
| 721 if (current->HasActiveTLAB()) { | |
| 722 heap_->MakeTLABIterable(current); | |
| 723 } | |
| 724 current = current->next(); | |
| 725 } | |
| 726 if (!isolate->IsMutatorThreadScheduled()) { | |
| 727 Thread* mutator_thread = isolate->mutator_thread(); | |
| 728 heap_->MakeTLABIterable(mutator_thread); | |
|
rmacnak
2017/08/10 18:37:07
An isolate might not have a mutator_thread yet.
danunez
2017/08/10 20:36:46
Right. Adding a check for NULL mutator_thread.
| |
| 729 } | |
| 730 } | |
| 731 | |
| 715 void Scavenger::MakeNewSpaceIterable() const { | 732 void Scavenger::MakeNewSpaceIterable() const { |
| 716 ASSERT(heap_ != NULL); | 733 ASSERT(heap_ != NULL); |
| 717 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 734 if (!scavenging_) { |
| 718 if (mutator_thread != NULL && !scavenging_) { | 735 MakeAllTLABsIterable(heap_->isolate()); |
| 719 if (mutator_thread->HasActiveTLAB()) { | |
| 720 ASSERT(mutator_thread->top() <= top_); | |
| 721 heap_->FillRemainingTLAB(mutator_thread); | |
| 722 } | |
| 723 } | 736 } |
| 724 } | 737 } |
| 725 | 738 |
| 739 void Scavenger::AbandonAllTLABs(Isolate* isolate) { | |
| 740 MonitorLocker ml(isolate->threads_lock(), false); | |
| 741 Thread* current = isolate->thread_registry()->active_list(); | |
| 742 while (current != NULL) { | |
| 743 heap_->AbandonRemainingTLAB(current); | |
| 744 current = current->next(); | |
| 745 } | |
| 746 if (!isolate->IsMutatorThreadScheduled()) { | |
| 747 Thread* mutator_thread = isolate->mutator_thread(); | |
|
rmacnak
2017/08/10 18:37:06
An isolate might not have a mutator_thread yet.
danunez
2017/08/10 20:36:46
Done.
| |
| 748 heap_->AbandonRemainingTLAB(mutator_thread); | |
| 749 } | |
| 750 } | |
| 751 | |
| 726 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 752 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 727 ASSERT(Thread::Current()->IsAtSafepoint() || | 753 ASSERT(Thread::Current()->IsAtSafepoint() || |
| 728 (Thread::Current()->task_kind() == Thread::kMarkerTask)); | 754 (Thread::Current()->task_kind() == Thread::kMarkerTask)); |
| 729 MakeNewSpaceIterable(); | 755 MakeNewSpaceIterable(); |
| 730 uword cur = FirstObjectStart(); | 756 uword cur = FirstObjectStart(); |
| 731 while (cur < top_) { | 757 while (cur < top_) { |
| 732 RawObject* raw_obj = RawObject::FromAddr(cur); | 758 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 733 cur += raw_obj->VisitPointers(visitor); | 759 cur += raw_obj->VisitPointers(visitor); |
| 734 } | 760 } |
| 735 } | 761 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 scavenging_ = true; | 818 scavenging_ = true; |
| 793 | 819 |
| 794 failed_to_promote_ = false; | 820 failed_to_promote_ = false; |
| 795 | 821 |
| 796 PageSpace* page_space = heap_->old_space(); | 822 PageSpace* page_space = heap_->old_space(); |
| 797 NoSafepointScope no_safepoints; | 823 NoSafepointScope no_safepoints; |
| 798 | 824 |
| 799 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 825 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
| 800 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 826 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
| 801 | 827 |
| 802 Thread* mutator_thread = isolate->mutator_thread(); | 828 AbandonAllTLABs(isolate); |
| 803 if ((mutator_thread != NULL) && (mutator_thread->HasActiveTLAB())) { | |
| 804 heap_->AbandonRemainingTLAB(mutator_thread); | |
| 805 } | |
| 806 | 829 |
| 807 // TODO(koda): Make verification more compatible with concurrent sweep. | 830 // TODO(koda): Make verification more compatible with concurrent sweep. |
| 808 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 831 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
| 809 OS::PrintErr("Verifying before Scavenge..."); | 832 OS::PrintErr("Verifying before Scavenge..."); |
| 810 heap_->Verify(kForbidMarked); | 833 heap_->Verify(kForbidMarked); |
| 811 OS::PrintErr(" done.\n"); | 834 OS::PrintErr(" done.\n"); |
| 812 } | 835 } |
| 813 | 836 |
| 814 // Prepare for a scavenge. | 837 // Prepare for a scavenge. |
| 815 SpaceUsage usage_before = GetCurrentUsage(); | 838 SpaceUsage usage_before = GetCurrentUsage(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 915 // Forces the next scavenge to promote all the objects in the new space. | 938 // Forces the next scavenge to promote all the objects in the new space. |
| 916 survivor_end_ = top_; | 939 survivor_end_ = top_; |
| 917 | 940 |
| 918 Scavenge(); | 941 Scavenge(); |
| 919 | 942 |
| 920 // It is possible for objects to stay in the new space | 943 // It is possible for objects to stay in the new space |
| 921 // if the VM cannot create more pages for these objects. | 944 // if the VM cannot create more pages for these objects. |
| 922 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 945 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
| 923 } | 946 } |
| 924 | 947 |
| 948 int64_t Scavenger::FreeSpaceInWords(Isolate* isolate) const { | |
| 949 MonitorLocker ml(isolate->threads_lock(), false); | |
| 950 Thread* current = isolate->thread_registry()->active_list(); | |
|
rmacnak
2017/08/10 18:37:07
"active_list" What about an unscheduled mutator t
danunez
2017/08/10 20:36:46
Added a check for an unscheduled mutator thread.
| |
| 951 int64_t free_space = 0; | |
| 952 while (current != NULL) { | |
| 953 if (current->HasActiveTLAB()) { | |
| 954 free_space += current->end() - current->top(); | |
| 955 } | |
| 956 current = current->next(); | |
| 957 } | |
| 958 return free_space >> kWordSizeLog2; | |
| 959 } | |
| 960 | |
| 925 int64_t Scavenger::UsedInWords() const { | 961 int64_t Scavenger::UsedInWords() const { |
| 926 int64_t free_space_in_tlab = 0; | 962 int64_t free_space_in_tlab = FreeSpaceInWords(heap_->isolate()); |
| 927 if (heap_->isolate()->IsMutatorThreadScheduled()) { | |
| 928 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | |
| 929 if (mutator_thread->HasActiveTLAB()) { | |
| 930 free_space_in_tlab = | |
| 931 (mutator_thread->end() - mutator_thread->top()) >> kWordSizeLog2; | |
| 932 } | |
| 933 } | |
| 934 int64_t max_space_used = (top_ - FirstObjectStart()) >> kWordSizeLog2; | 963 int64_t max_space_used = (top_ - FirstObjectStart()) >> kWordSizeLog2; |
| 935 return max_space_used - free_space_in_tlab; | 964 return max_space_used - free_space_in_tlab; |
| 936 } | 965 } |
| 937 | 966 |
| 938 } // namespace dart | 967 } // namespace dart |
| OLD | NEW |