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 void Scavenger::MakeNewSpaceIterable() const { |
726 ASSERT(heap_ != NULL); | 718 ASSERT(heap_ != NULL); |
727 if (heap_->isolate()->IsMutatorThreadScheduled()) { | 719 if (heap_->isolate()->IsMutatorThreadScheduled() && !scavenging_) { |
728 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | 720 Thread* mutator_thread = heap_->isolate()->mutator_thread(); |
729 mutator_thread->heap()->new_space()->set_top(mutator_thread->top()); | 721 if (mutator_thread->HasActiveTLAB()) { |
| 722 ASSERT(mutator_thread->top() <= |
| 723 mutator_thread->heap()->new_space()->top()); |
| 724 heap_->FillRemainingTLAB(mutator_thread); |
| 725 } |
730 } | 726 } |
731 } | 727 } |
732 | 728 |
733 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 729 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
734 FlushTLS(); | 730 MakeNewSpaceIterable(); |
735 uword cur = FirstObjectStart(); | 731 uword cur = FirstObjectStart(); |
736 while (cur < top_) { | 732 while (cur < top_) { |
737 RawObject* raw_obj = RawObject::FromAddr(cur); | 733 RawObject* raw_obj = RawObject::FromAddr(cur); |
738 cur += raw_obj->VisitPointers(visitor); | 734 cur += raw_obj->VisitPointers(visitor); |
739 } | 735 } |
740 } | 736 } |
741 | 737 |
742 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 738 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
743 FlushTLS(); | 739 MakeNewSpaceIterable(); |
744 uword cur = FirstObjectStart(); | 740 uword cur = FirstObjectStart(); |
745 while (cur < top_) { | 741 while (cur < top_) { |
746 RawObject* raw_obj = RawObject::FromAddr(cur); | 742 RawObject* raw_obj = RawObject::FromAddr(cur); |
747 visitor->VisitObject(raw_obj); | 743 visitor->VisitObject(raw_obj); |
748 cur += raw_obj->Size(); | 744 cur += raw_obj->Size(); |
749 } | 745 } |
750 } | 746 } |
751 | 747 |
752 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { | 748 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { |
753 set->AddRegion(to_->start(), to_->end()); | 749 set->AddRegion(to_->start(), to_->end()); |
754 } | 750 } |
755 | 751 |
756 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { | 752 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { |
757 ASSERT(!scavenging_); | 753 ASSERT(!scavenging_); |
758 FlushTLS(); | 754 MakeNewSpaceIterable(); |
759 uword cur = FirstObjectStart(); | 755 uword cur = FirstObjectStart(); |
760 if (visitor->VisitRange(cur, top_)) { | 756 if (visitor->VisitRange(cur, top_)) { |
761 while (cur < top_) { | 757 while (cur < top_) { |
762 RawObject* raw_obj = RawObject::FromAddr(cur); | 758 RawObject* raw_obj = RawObject::FromAddr(cur); |
763 uword next = cur + raw_obj->Size(); | 759 uword next = cur + raw_obj->Size(); |
764 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { | 760 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { |
765 return raw_obj; // Found object, return it. | 761 return raw_obj; // Found object, return it. |
766 } | 762 } |
767 cur = next; | 763 cur = next; |
768 } | 764 } |
(...skipping 26 matching lines...) Expand all Loading... |
795 scavenging_ = true; | 791 scavenging_ = true; |
796 | 792 |
797 failed_to_promote_ = false; | 793 failed_to_promote_ = false; |
798 | 794 |
799 PageSpace* page_space = heap_->old_space(); | 795 PageSpace* page_space = heap_->old_space(); |
800 NoSafepointScope no_safepoints; | 796 NoSafepointScope no_safepoints; |
801 | 797 |
802 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 798 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
803 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 799 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
804 | 800 |
| 801 if (isolate->IsMutatorThreadScheduled()) { |
| 802 Thread* mutator_thread = isolate->mutator_thread(); |
| 803 if (mutator_thread->HasActiveTLAB()) { |
| 804 heap_->AbandonRemainingTLAB(mutator_thread); |
| 805 } |
| 806 } |
| 807 |
805 // TODO(koda): Make verification more compatible with concurrent sweep. | 808 // TODO(koda): Make verification more compatible with concurrent sweep. |
806 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 809 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
807 OS::PrintErr("Verifying before Scavenge..."); | 810 OS::PrintErr("Verifying before Scavenge..."); |
808 heap_->Verify(kForbidMarked); | 811 heap_->Verify(kForbidMarked); |
809 OS::PrintErr(" done.\n"); | 812 OS::PrintErr(" done.\n"); |
810 } | 813 } |
811 | 814 |
812 // Prepare for a scavenge. | 815 // Prepare for a scavenge. |
813 SpaceUsage usage_before = GetCurrentUsage(); | 816 SpaceUsage usage_before = GetCurrentUsage(); |
814 intptr_t promo_candidate_words = | 817 intptr_t promo_candidate_words = |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 // the scavenge. | 909 // the scavenge. |
907 // The former can introduce an object that we might fail to collect. | 910 // 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 | 911 // The latter means even if the scavenge promotes every object in the new |
909 // space, the new allocation means the space is not empty, | 912 // space, the new allocation means the space is not empty, |
910 // causing the assertion below to fail. | 913 // causing the assertion below to fail. |
911 SafepointOperationScope scope(Thread::Current()); | 914 SafepointOperationScope scope(Thread::Current()); |
912 | 915 |
913 // Forces the next scavenge to promote all the objects in the new space. | 916 // Forces the next scavenge to promote all the objects in the new space. |
914 survivor_end_ = top_; | 917 survivor_end_ = top_; |
915 | 918 |
916 if (heap_->isolate()->IsMutatorThreadScheduled()) { | |
917 Thread* mutator_thread = heap_->isolate()->mutator_thread(); | |
918 survivor_end_ = mutator_thread->top(); | |
919 } | |
920 | |
921 Scavenge(); | 919 Scavenge(); |
922 | 920 |
923 // It is possible for objects to stay in the new space | 921 // It is possible for objects to stay in the new space |
924 // if the VM cannot create more pages for these objects. | 922 // if the VM cannot create more pages for these objects. |
925 ASSERT((UsedInWords() == 0) || failed_to_promote_); | 923 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
926 } | 924 } |
927 | 925 |
| 926 int64_t Scavenger::UsedInWords() const { |
| 927 int64_t used_in_words = (top_ - FirstObjectStart()) >> kWordSizeLog2; |
| 928 return used_in_words; |
| 929 } |
| 930 |
928 } // namespace dart | 931 } // namespace dart |
OLD | NEW |