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 } |
| 728 } |
| 729 return saved_top; |
| 730 } |
| 731 |
| 732 void Scavenger::UnflushTLS(uword value) const { |
| 733 ASSERT(heap_ != NULL); |
| 734 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { |
| 735 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
| 736 mutator_thread->heap()->new_space()->set_top(value); |
| 737 ASSERT(mutator_thread->top() <= mutator_thread->heap()->new_space()->top()); |
730 } | 738 } |
731 } | 739 } |
732 | 740 |
733 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 741 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
734 FlushTLS(); | 742 uword saved_top = FlushTLS(); |
735 uword cur = FirstObjectStart(); | 743 uword cur = FirstObjectStart(); |
736 while (cur < top_) { | 744 while (cur < top_) { |
737 RawObject* raw_obj = RawObject::FromAddr(cur); | 745 RawObject* raw_obj = RawObject::FromAddr(cur); |
738 cur += raw_obj->VisitPointers(visitor); | 746 cur += raw_obj->VisitPointers(visitor); |
739 } | 747 } |
| 748 UnflushTLS(saved_top); |
740 } | 749 } |
741 | 750 |
742 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 751 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
743 FlushTLS(); | 752 uword saved_top = FlushTLS(); |
744 uword cur = FirstObjectStart(); | 753 uword cur = FirstObjectStart(); |
745 while (cur < top_) { | 754 while (cur < top_) { |
746 RawObject* raw_obj = RawObject::FromAddr(cur); | 755 RawObject* raw_obj = RawObject::FromAddr(cur); |
747 visitor->VisitObject(raw_obj); | 756 visitor->VisitObject(raw_obj); |
748 cur += raw_obj->Size(); | 757 cur += raw_obj->Size(); |
749 } | 758 } |
| 759 UnflushTLS(saved_top); |
750 } | 760 } |
751 | 761 |
752 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { | 762 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { |
753 set->AddRegion(to_->start(), to_->end()); | 763 set->AddRegion(to_->start(), to_->end()); |
754 } | 764 } |
755 | 765 |
756 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { | 766 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { |
757 ASSERT(!scavenging_); | 767 ASSERT(!scavenging_); |
758 FlushTLS(); | 768 uword saved_top = FlushTLS(); |
759 uword cur = FirstObjectStart(); | 769 uword cur = FirstObjectStart(); |
760 if (visitor->VisitRange(cur, top_)) { | 770 if (visitor->VisitRange(cur, top_)) { |
761 while (cur < top_) { | 771 while (cur < top_) { |
762 RawObject* raw_obj = RawObject::FromAddr(cur); | 772 RawObject* raw_obj = RawObject::FromAddr(cur); |
763 uword next = cur + raw_obj->Size(); | 773 uword next = cur + raw_obj->Size(); |
764 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { | 774 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { |
| 775 UnflushTLS(saved_top); |
765 return raw_obj; // Found object, return it. | 776 return raw_obj; // Found object, return it. |
766 } | 777 } |
767 cur = next; | 778 cur = next; |
768 } | 779 } |
769 ASSERT(cur == top_); | 780 ASSERT(cur == top_); |
770 } | 781 } |
| 782 UnflushTLS(saved_top); |
771 return Object::null(); | 783 return Object::null(); |
772 } | 784 } |
773 | 785 |
774 void Scavenger::Scavenge() { | 786 void Scavenger::Scavenge() { |
775 // TODO(cshapiro): Add a decision procedure for determining when the | 787 // TODO(cshapiro): Add a decision procedure for determining when the |
776 // the API callbacks should be invoked. | 788 // the API callbacks should be invoked. |
777 Scavenge(false); | 789 Scavenge(false); |
778 } | 790 } |
779 | 791 |
780 void Scavenger::Scavenge(bool invoke_api_callbacks) { | 792 void Scavenger::Scavenge(bool invoke_api_callbacks) { |
(...skipping 14 matching lines...) Expand all Loading... |
795 scavenging_ = true; | 807 scavenging_ = true; |
796 | 808 |
797 failed_to_promote_ = false; | 809 failed_to_promote_ = false; |
798 | 810 |
799 PageSpace* page_space = heap_->old_space(); | 811 PageSpace* page_space = heap_->old_space(); |
800 NoSafepointScope no_safepoints; | 812 NoSafepointScope no_safepoints; |
801 | 813 |
802 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 814 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
803 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 815 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
804 | 816 |
| 817 if (isolate->IsMutatorThreadScheduled()) { |
| 818 Thread* mutator_thread = isolate->mutator_thread(); |
| 819 if (mutator_thread->HasActiveTLAB()) { |
| 820 heap_->AbandonRemainingTLAB(mutator_thread); |
| 821 } |
| 822 } |
| 823 |
805 // TODO(koda): Make verification more compatible with concurrent sweep. | 824 // TODO(koda): Make verification more compatible with concurrent sweep. |
806 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 825 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
807 OS::PrintErr("Verifying before Scavenge..."); | 826 OS::PrintErr("Verifying before Scavenge..."); |
808 heap_->Verify(kForbidMarked); | 827 heap_->Verify(kForbidMarked); |
809 OS::PrintErr(" done.\n"); | 828 OS::PrintErr(" done.\n"); |
810 } | 829 } |
811 | 830 |
812 // Prepare for a scavenge. | 831 // Prepare for a scavenge. |
813 SpaceUsage usage_before = GetCurrentUsage(); | 832 SpaceUsage usage_before = GetCurrentUsage(); |
814 intptr_t promo_candidate_words = | 833 intptr_t promo_candidate_words = |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 // The latter means even if the scavenge promotes every object in the new | 927 // The latter means even if the scavenge promotes every object in the new |
909 // space, the new allocation means the space is not empty, | 928 // space, the new allocation means the space is not empty, |
910 // causing the assertion below to fail. | 929 // causing the assertion below to fail. |
911 SafepointOperationScope scope(Thread::Current()); | 930 SafepointOperationScope scope(Thread::Current()); |
912 | 931 |
913 // Forces the next scavenge to promote all the objects in the new space. | 932 // Forces the next scavenge to promote all the objects in the new space. |
914 survivor_end_ = top_; | 933 survivor_end_ = top_; |
915 | 934 |
916 if (heap_->isolate()->IsMutatorThreadScheduled()) { | 935 if (heap_->isolate()->IsMutatorThreadScheduled()) { |
917 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 936 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
918 survivor_end_ = mutator_thread->top(); | 937 if (mutator_thread->HasActiveTLAB()) { |
| 938 survivor_end_ = mutator_thread->top(); |
| 939 } |
919 } | 940 } |
920 | 941 |
921 Scavenge(); | 942 Scavenge(); |
922 | 943 |
923 // It is possible for objects to stay in the new space | 944 // It is possible for objects to stay in the new space |
924 // if the VM cannot create more pages for these objects. | 945 // if the VM cannot create more pages for these objects. |
925 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 946 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
926 } | 947 } |
927 | 948 |
| 949 int64_t Scavenger::UsedInWords() const { |
| 950 uword saved_top = FlushTLS(); |
| 951 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; |
| 952 UnflushTLS(saved_top); |
| 953 return used_in_words; |
| 954 } |
| 955 |
928 } // namespace dart | 956 } // namespace dart |
OLD | NEW |