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