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 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 if (to_ == NULL) { | 387 if (to_ == NULL) { |
388 // TODO(koda): We could try to recover (collect old space, wait for another | 388 // TODO(koda): We could try to recover (collect old space, wait for another |
389 // isolate to finish scavenge, etc.). | 389 // isolate to finish scavenge, etc.). |
390 OUT_OF_MEMORY(); | 390 OUT_OF_MEMORY(); |
391 } | 391 } |
392 UpdateMaxHeapCapacity(); | 392 UpdateMaxHeapCapacity(); |
393 top_ = FirstObjectStart(); | 393 top_ = FirstObjectStart(); |
394 resolved_top_ = top_; | 394 resolved_top_ = top_; |
395 end_ = to_->end(); | 395 end_ = to_->end(); |
396 | 396 |
397 // Throw out the old information about the from space | |
398 if (isolate->IsMutatorThreadScheduled()) { | |
399 Thread* mutator_thread = isolate->mutator_thread(); | |
400 mutator_thread->set_top(top_); | |
401 mutator_thread->set_end(end_); | |
402 } | |
403 | |
404 return from; | 397 return from; |
405 } | 398 } |
406 | 399 |
407 void Scavenger::Epilogue(Isolate* isolate, | 400 void Scavenger::Epilogue(Isolate* isolate, |
408 SemiSpace* from, | 401 SemiSpace* from, |
409 bool invoke_api_callbacks) { | 402 bool invoke_api_callbacks) { |
410 // All objects in the to space have been copied from the from space at this | 403 // All objects in the to space have been copied from the from space at this |
411 // moment. | 404 // moment. |
412 | 405 |
413 // Ensure the mutator thread now has the up-to-date top_ and end_ of the | 406 // Ensure the mutator thread will fail the next allocation. This will force |
414 // semispace | 407 // mutator to allocate a new TLAB |
415 if (isolate->IsMutatorThreadScheduled()) { | 408 if (isolate->IsMutatorThreadScheduled()) { |
416 Thread* thread = isolate->mutator_thread(); | 409 Thread* thread = isolate->mutator_thread(); |
rmacnak
2017/08/03 20:31:40
We abandoned the TLAB at the beginning of the scav
danunez
2017/08/03 20:39:21
Yes. That is true. I will add an assertion and rem
| |
417 thread->set_top(top_); | 410 thread->set_top(0); |
418 thread->set_end(end_); | 411 thread->set_end(0); |
419 } | 412 } |
420 | 413 |
421 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); | 414 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); |
422 if (stats_history_.Size() >= 2) { | 415 if (stats_history_.Size() >= 2) { |
423 // Previous scavenge is only given half as much weight. | 416 // Previous scavenge is only given half as much weight. |
424 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); | 417 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); |
425 avg_frac /= 1.0 + 0.5; // Normalize. | 418 avg_frac /= 1.0 + 0.5; // Normalize. |
426 } | 419 } |
427 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { | 420 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { |
428 // Remember the limit to which objects have been copied. | 421 // Remember the limit to which objects have been copied. |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
715 #endif // defined(DEBUG) | 708 #endif // defined(DEBUG) |
716 | 709 |
717 WeakProperty::Clear(cur_weak); | 710 WeakProperty::Clear(cur_weak); |
718 | 711 |
719 // Advance to next weak property in the queue. | 712 // Advance to next weak property in the queue. |
720 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | 713 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
721 } | 714 } |
722 } | 715 } |
723 } | 716 } |
724 | 717 |
725 void Scavenger::FlushTLS() const { | 718 uword Scavenger::FlushTLS() const { |
726 ASSERT(heap_ != NULL); | 719 ASSERT(heap_ != NULL); |
727 if (heap_->isolate()->IsMutatorThreadScheduled()) { | 720 uword saved_top = top_; |
721 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | |
728 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 722 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
729 mutator_thread->heap()->new_space()->set_top(mutator_thread->top()); | 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 heap_->FillRemainingTLAB(mutator_thread); | |
728 } | |
729 } | |
730 return saved_top; | |
731 } | |
732 | |
733 void Scavenger::UnflushTLS(uword value) const { | |
734 ASSERT(heap_ != NULL); | |
735 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | |
736 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | |
737 mutator_thread->heap()->new_space()->set_top(value); | |
738 ASSERT(mutator_thread->top() <= mutator_thread->heap()->new_space()->top()); | |
730 } | 739 } |
731 } | 740 } |
732 | 741 |
733 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 742 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
734 FlushTLS(); | 743 uword saved_top = FlushTLS(); |
735 uword cur = FirstObjectStart(); | 744 uword cur = FirstObjectStart(); |
736 while (cur < top_) { | 745 while (cur < top_) { |
737 RawObject* raw_obj = RawObject::FromAddr(cur); | 746 RawObject* raw_obj = RawObject::FromAddr(cur); |
738 cur += raw_obj->VisitPointers(visitor); | 747 cur += raw_obj->VisitPointers(visitor); |
739 } | 748 } |
749 UnflushTLS(saved_top); | |
740 } | 750 } |
741 | 751 |
742 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 752 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
743 FlushTLS(); | 753 uword saved_top = FlushTLS(); |
744 uword cur = FirstObjectStart(); | 754 uword cur = FirstObjectStart(); |
745 while (cur < top_) { | 755 while (cur < top_) { |
746 RawObject* raw_obj = RawObject::FromAddr(cur); | 756 RawObject* raw_obj = RawObject::FromAddr(cur); |
747 visitor->VisitObject(raw_obj); | 757 visitor->VisitObject(raw_obj); |
748 cur += raw_obj->Size(); | 758 cur += raw_obj->Size(); |
749 } | 759 } |
760 UnflushTLS(saved_top); | |
750 } | 761 } |
751 | 762 |
752 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { | 763 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { |
753 set->AddRegion(to_->start(), to_->end()); | 764 set->AddRegion(to_->start(), to_->end()); |
754 } | 765 } |
755 | 766 |
756 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { | 767 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { |
757 ASSERT(!scavenging_); | 768 ASSERT(!scavenging_); |
758 FlushTLS(); | 769 uword saved_top = FlushTLS(); |
759 uword cur = FirstObjectStart(); | 770 uword cur = FirstObjectStart(); |
760 if (visitor->VisitRange(cur, top_)) { | 771 if (visitor->VisitRange(cur, top_)) { |
761 while (cur < top_) { | 772 while (cur < top_) { |
762 RawObject* raw_obj = RawObject::FromAddr(cur); | 773 RawObject* raw_obj = RawObject::FromAddr(cur); |
763 uword next = cur + raw_obj->Size(); | 774 uword next = cur + raw_obj->Size(); |
764 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { | 775 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { |
776 UnflushTLS(saved_top); | |
765 return raw_obj; // Found object, return it. | 777 return raw_obj; // Found object, return it. |
766 } | 778 } |
767 cur = next; | 779 cur = next; |
768 } | 780 } |
769 ASSERT(cur == top_); | 781 ASSERT(cur == top_); |
770 } | 782 } |
783 UnflushTLS(saved_top); | |
771 return Object::null(); | 784 return Object::null(); |
772 } | 785 } |
773 | 786 |
774 void Scavenger::Scavenge() { | 787 void Scavenger::Scavenge() { |
775 // TODO(cshapiro): Add a decision procedure for determining when the | 788 // TODO(cshapiro): Add a decision procedure for determining when the |
776 // the API callbacks should be invoked. | 789 // the API callbacks should be invoked. |
777 Scavenge(false); | 790 Scavenge(false); |
778 } | 791 } |
779 | 792 |
780 void Scavenger::Scavenge(bool invoke_api_callbacks) { | 793 void Scavenger::Scavenge(bool invoke_api_callbacks) { |
(...skipping 14 matching lines...) Expand all Loading... | |
795 scavenging_ = true; | 808 scavenging_ = true; |
796 | 809 |
797 failed_to_promote_ = false; | 810 failed_to_promote_ = false; |
798 | 811 |
799 PageSpace* page_space = heap_->old_space(); | 812 PageSpace* page_space = heap_->old_space(); |
800 NoSafepointScope no_safepoints; | 813 NoSafepointScope no_safepoints; |
801 | 814 |
802 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 815 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
803 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 816 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
804 | 817 |
818 if (isolate->IsMutatorThreadScheduled()) { | |
819 Thread* mutator_thread = isolate->mutator_thread(); | |
820 if (mutator_thread->HasActiveTLAB()) { | |
821 heap_->AbandonRemainingTLAB(mutator_thread); | |
822 } | |
823 } | |
824 | |
805 // TODO(koda): Make verification more compatible with concurrent sweep. | 825 // TODO(koda): Make verification more compatible with concurrent sweep. |
806 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 826 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
807 OS::PrintErr("Verifying before Scavenge..."); | 827 OS::PrintErr("Verifying before Scavenge..."); |
808 heap_->Verify(kForbidMarked); | 828 heap_->Verify(kForbidMarked); |
809 OS::PrintErr(" done.\n"); | 829 OS::PrintErr(" done.\n"); |
810 } | 830 } |
811 | 831 |
812 // Prepare for a scavenge. | 832 // Prepare for a scavenge. |
813 SpaceUsage usage_before = GetCurrentUsage(); | 833 SpaceUsage usage_before = GetCurrentUsage(); |
814 intptr_t promo_candidate_words = | 834 intptr_t promo_candidate_words = |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 // the scavenge. | 926 // the scavenge. |
907 // The former can introduce an object that we might fail to collect. | 927 // The former can introduce an object that we might fail to collect. |
908 // The latter means even if the scavenge promotes every object in the new | 928 // The latter means even if the scavenge promotes every object in the new |
909 // space, the new allocation means the space is not empty, | 929 // space, the new allocation means the space is not empty, |
910 // causing the assertion below to fail. | 930 // causing the assertion below to fail. |
911 SafepointOperationScope scope(Thread::Current()); | 931 SafepointOperationScope scope(Thread::Current()); |
912 | 932 |
913 // Forces the next scavenge to promote all the objects in the new space. | 933 // Forces the next scavenge to promote all the objects in the new space. |
914 survivor_end_ = top_; | 934 survivor_end_ = top_; |
915 | 935 |
916 if (heap_->isolate()->IsMutatorThreadScheduled()) { | 936 if (heap_->isolate()->IsMutatorThreadScheduled()) { |
rmacnak
2017/08/03 20:31:40
Isn't this redundant with the abdanon-tlab in Scav
danunez
2017/08/03 20:39:21
The call to abandon-tlab is redundant and will be
| |
917 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 937 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
918 survivor_end_ = mutator_thread->top(); | 938 if (mutator_thread->HasActiveTLAB()) { |
939 survivor_end_ = mutator_thread->top(); | |
940 heap_->AbandonRemainingTLAB(mutator_thread); | |
941 } | |
919 } | 942 } |
920 | 943 |
921 Scavenge(); | 944 Scavenge(); |
922 | 945 |
923 // It is possible for objects to stay in the new space | 946 // It is possible for objects to stay in the new space |
924 // if the VM cannot create more pages for these objects. | 947 // if the VM cannot create more pages for these objects. |
925 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 948 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
926 } | 949 } |
927 | 950 |
951 int64_t Scavenger::UsedInWords() const { | |
952 uword saved_top = FlushTLS(); | |
953 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; | |
954 UnflushTLS(saved_top); | |
955 return used_in_words; | |
956 } | |
957 | |
928 } // namespace dart | 958 } // namespace dart |
OLD | NEW |