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

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

Issue 2992753002: Prepares allocation for proper sync with mutator and bg threads. (Closed)
Patch Set: Splits FindTopOfSpace to two functions 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 {
719 ASSERT(heap_ != NULL); 721 Thread* current = heap_->isolate()->thread_registry()->active_list();
720 uword saved_top = top_; 722 while (current != NULL) {
721 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { 723 if (current->HasActiveTLAB()) {
722 Thread* mutator_thread = heap_->isolate()->mutator_thread(); 724 heap_->MakeTLABIterable(current);
723 saved_top = mutator_thread->heap()->new_space()->top();
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 } 725 }
726 current = current->next();
729 } 727 }
730 return saved_top;
731 } 728 }
732 729
733 void Scavenger::UnflushTLS(uword value) const { 730 void Scavenger::FlushTLS() const {
734 ASSERT(heap_ != NULL); 731 ASSERT(heap_ != NULL);
735 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { 732 if (!scavenging_) {
736 Thread* mutator_thread = heap_->isolate()->mutator_thread(); 733 MakeALLTLABsIterable(heap_->isolate());
737 mutator_thread->heap()->new_space()->set_top(value); 734 }
738 ASSERT(mutator_thread->top() <= mutator_thread->heap()->new_space()->top()); 735 }
736
737 void Scavenger::AbandonAllTLABs() {
738 Thread* current = heap_->isolate()->thread_registry()->active_list();
739 while (current != NULL) {
740 heap_->AbandonRemainingTLAB(current);
741 current = current->next();
739 } 742 }
740 } 743 }
741 744
742 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 745 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
743 uword saved_top = FlushTLS(); 746 FlushTLS();
744 uword cur = FirstObjectStart(); 747 uword cur = FirstObjectStart();
745 while (cur < top_) { 748 while (cur < top_) {
746 RawObject* raw_obj = RawObject::FromAddr(cur); 749 RawObject* raw_obj = RawObject::FromAddr(cur);
747 cur += raw_obj->VisitPointers(visitor); 750 cur += raw_obj->VisitPointers(visitor);
748 } 751 }
749 UnflushTLS(saved_top);
750 } 752 }
751 753
752 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { 754 void Scavenger::VisitObjects(ObjectVisitor* visitor) const {
753 uword saved_top = FlushTLS(); 755 FlushTLS();
754 uword cur = FirstObjectStart(); 756 uword cur = FirstObjectStart();
755 while (cur < top_) { 757 while (cur < top_) {
756 RawObject* raw_obj = RawObject::FromAddr(cur); 758 RawObject* raw_obj = RawObject::FromAddr(cur);
757 visitor->VisitObject(raw_obj); 759 visitor->VisitObject(raw_obj);
758 cur += raw_obj->Size(); 760 cur += raw_obj->Size();
759 } 761 }
760 UnflushTLS(saved_top);
761 } 762 }
762 763
763 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { 764 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const {
764 set->AddRegion(to_->start(), to_->end()); 765 set->AddRegion(to_->start(), to_->end());
765 } 766 }
766 767
767 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { 768 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const {
768 ASSERT(!scavenging_); 769 ASSERT(!scavenging_);
769 uword saved_top = FlushTLS(); 770 FlushTLS();
770 uword cur = FirstObjectStart(); 771 uword cur = FirstObjectStart();
771 if (visitor->VisitRange(cur, top_)) { 772 if (visitor->VisitRange(cur, top_)) {
772 while (cur < top_) { 773 while (cur < top_) {
773 RawObject* raw_obj = RawObject::FromAddr(cur); 774 RawObject* raw_obj = RawObject::FromAddr(cur);
774 uword next = cur + raw_obj->Size(); 775 uword next = cur + raw_obj->Size();
775 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { 776 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) {
776 UnflushTLS(saved_top);
777 return raw_obj; // Found object, return it. 777 return raw_obj; // Found object, return it.
778 } 778 }
779 cur = next; 779 cur = next;
780 } 780 }
781 ASSERT(cur == top_); 781 ASSERT(cur == top_);
782 } 782 }
783 UnflushTLS(saved_top);
784 return Object::null(); 783 return Object::null();
785 } 784 }
786 785
787 void Scavenger::Scavenge() { 786 void Scavenger::Scavenge() {
788 // TODO(cshapiro): Add a decision procedure for determining when the 787 // TODO(cshapiro): Add a decision procedure for determining when the
789 // the API callbacks should be invoked. 788 // the API callbacks should be invoked.
790 Scavenge(false); 789 Scavenge(false);
791 } 790 }
792 791
793 void Scavenger::Scavenge(bool invoke_api_callbacks) { 792 void Scavenger::Scavenge(bool invoke_api_callbacks) {
(...skipping 14 matching lines...) Expand all
808 scavenging_ = true; 807 scavenging_ = true;
809 808
810 failed_to_promote_ = false; 809 failed_to_promote_ = false;
811 810
812 PageSpace* page_space = heap_->old_space(); 811 PageSpace* page_space = heap_->old_space();
813 NoSafepointScope no_safepoints; 812 NoSafepointScope no_safepoints;
814 813
815 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); 814 int64_t post_safe_point = OS::GetCurrentMonotonicMicros();
816 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); 815 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point);
817 816
818 if (isolate->IsMutatorThreadScheduled()) { 817 // TODO(danunez): Abandon all threads' TLABs. Every thread should be stopped
rmacnak 2017/08/02 19:20:48 Why TODO? Looks implemented to me.
danunez 2017/08/02 19:36:08 It is implemented (minus some locking with thread_
819 Thread* mutator_thread = isolate->mutator_thread(); 818 // here anyway.
820 if (mutator_thread->HasActiveTLAB()) { 819 AbandonAllTLABs();
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 Thread* current = heap_->isolate()->thread_registry()->active_list();
949 uword furthest_addr = 0;
950 while (current != NULL) {
951 if (current->HasActiveTLAB() && current->top() > furthest_addr) {
952 furthest_addr = current->top();
953 }
954 current = current->next();
955 }
956 if (furthest_addr == 0) {
957 return top_;
958 }
959 return furthest_addr;
960 }
961
951 int64_t Scavenger::UsedInWords() const { 962 int64_t Scavenger::UsedInWords() const {
952 uword saved_top = FlushTLS(); 963 uword top_of_space = FindTopOfSpace(heap_->isolate());
rmacnak 2017/08/02 19:20:48 This will count of the unallocated space in all bu
danunez 2017/08/02 19:36:08 If each thread allocates at most one TLAB, then we
953 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; 964 int64_t used_in_words = (top_of_space - FirstObjectStart()) >> kWordSizeLog2;
954 UnflushTLS(saved_top);
955 return used_in_words; 965 return used_in_words;
956 } 966 }
957 967
958 } // namespace dart 968 } // 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