Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: runtime/vm/scavenger.cc

Issue 2992753002: Prepares allocation for proper sync with mutator and bg threads. (Closed)
Patch Set: Adds thread locking to functions that iterate over threads Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/scavenger.h ('k') | runtime/vm/thread_registry.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/scavenger.h ('k') | runtime/vm/thread_registry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698