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* mutator_thread = isolate->mutator_thread(); |
417 thread->set_top(top_); | 410 ASSERT(!mutator_thread->HasActiveTLAB()); |
418 thread->set_end(end_); | |
419 } | 411 } |
420 | 412 |
421 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); | 413 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); |
422 if (stats_history_.Size() >= 2) { | 414 if (stats_history_.Size() >= 2) { |
423 // Previous scavenge is only given half as much weight. | 415 // Previous scavenge is only given half as much weight. |
424 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); | 416 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); |
425 avg_frac /= 1.0 + 0.5; // Normalize. | 417 avg_frac /= 1.0 + 0.5; // Normalize. |
426 } | 418 } |
427 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { | 419 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { |
428 // Remember the limit to which objects have been copied. | 420 // 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) | 707 #endif // defined(DEBUG) |
716 | 708 |
717 WeakProperty::Clear(cur_weak); | 709 WeakProperty::Clear(cur_weak); |
718 | 710 |
719 // Advance to next weak property in the queue. | 711 // Advance to next weak property in the queue. |
720 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | 712 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
721 } | 713 } |
722 } | 714 } |
723 } | 715 } |
724 | 716 |
725 void Scavenger::FlushTLS() const { | 717 uword Scavenger::FlushTLS() const { |
726 ASSERT(heap_ != NULL); | 718 ASSERT(heap_ != NULL); |
727 if (heap_->isolate()->IsMutatorThreadScheduled()) { | 719 uword saved_top = top_; |
720 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | |
728 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 721 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
729 mutator_thread->heap()->new_space()->set_top(mutator_thread->top()); | 722 saved_top = mutator_thread->heap()->new_space()->top(); |
723 if (mutator_thread->HasActiveTLAB()) { | |
724 ASSERT(mutator_thread->top() <= | |
725 mutator_thread->heap()->new_space()->top()); | |
726 heap_->FillRemainingTLAB(mutator_thread); | |
727 } | |
730 } | 728 } |
729 return saved_top; | |
730 } | |
731 | |
732 void Scavenger::UnflushTLS(uword value) const { | |
rmacnak
2017/08/04 23:02:15
This only contains asserts now. Remove to rename t
| |
733 ASSERT(heap_ != NULL); | |
734 #if defined(DEBUG) | |
735 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { | |
736 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | |
737 ASSERT(mutator_thread->top() <= mutator_thread->heap()->new_space()->top()); | |
738 } | |
739 #endif // defined(DEBUG) | |
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()) { | |
917 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | |
918 survivor_end_ = mutator_thread->top(); | |
919 } | |
920 | |
921 Scavenge(); | 936 Scavenge(); |
922 | 937 |
923 // It is possible for objects to stay in the new space | 938 // It is possible for objects to stay in the new space |
924 // if the VM cannot create more pages for these objects. | 939 // if the VM cannot create more pages for these objects. |
925 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 940 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
926 } | 941 } |
927 | 942 |
943 int64_t Scavenger::UsedInWords() const { | |
944 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; | |
945 return used_in_words; | |
946 } | |
947 | |
928 } // namespace dart | 948 } // namespace dart |
OLD | NEW |