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 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 } | 365 } |
366 double garbage = stats_history_.Get(0).GarbageFraction(); | 366 double garbage = stats_history_.Get(0).GarbageFraction(); |
367 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { | 367 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { |
368 return Utils::Minimum(max_semi_capacity_in_words_, | 368 return Utils::Minimum(max_semi_capacity_in_words_, |
369 old_size_in_words * FLAG_new_gen_growth_factor); | 369 old_size_in_words * FLAG_new_gen_growth_factor); |
370 } else { | 370 } else { |
371 return old_size_in_words; | 371 return old_size_in_words; |
372 } | 372 } |
373 } | 373 } |
374 | 374 |
375 SemiSpace* Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { | 375 SemiSpace* Scavenger::Prologue(Isolate* isolate) { |
376 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { | |
377 (isolate->gc_prologue_callback())(); | |
378 } | |
379 isolate->PrepareForGC(); | 376 isolate->PrepareForGC(); |
380 | 377 |
381 // Flip the two semi-spaces so that to_ is always the space for allocating | 378 // Flip the two semi-spaces so that to_ is always the space for allocating |
382 // objects. | 379 // objects. |
383 SemiSpace* from = to_; | 380 SemiSpace* from = to_; |
384 | 381 |
385 const intptr_t kVmNameSize = 128; | 382 const intptr_t kVmNameSize = 128; |
386 char vm_name[kVmNameSize]; | 383 char vm_name[kVmNameSize]; |
387 Heap::RegionName(heap_, Heap::kNew, vm_name, kVmNameSize); | 384 Heap::RegionName(heap_, Heap::kNew, vm_name, kVmNameSize); |
388 to_ = SemiSpace::New(NewSizeInWords(from->size_in_words()), vm_name); | 385 to_ = SemiSpace::New(NewSizeInWords(from->size_in_words()), vm_name); |
389 if (to_ == NULL) { | 386 if (to_ == NULL) { |
390 // TODO(koda): We could try to recover (collect old space, wait for another | 387 // TODO(koda): We could try to recover (collect old space, wait for another |
391 // isolate to finish scavenge, etc.). | 388 // isolate to finish scavenge, etc.). |
392 OUT_OF_MEMORY(); | 389 OUT_OF_MEMORY(); |
393 } | 390 } |
394 UpdateMaxHeapCapacity(); | 391 UpdateMaxHeapCapacity(); |
395 top_ = FirstObjectStart(); | 392 top_ = FirstObjectStart(); |
396 resolved_top_ = top_; | 393 resolved_top_ = top_; |
397 end_ = to_->end(); | 394 end_ = to_->end(); |
398 | 395 |
399 return from; | 396 return from; |
400 } | 397 } |
401 | 398 |
402 void Scavenger::Epilogue(Isolate* isolate, | 399 void Scavenger::Epilogue(Isolate* isolate, SemiSpace* from) { |
403 SemiSpace* from, | |
404 bool invoke_api_callbacks) { | |
405 // All objects in the to space have been copied from the from space at this | 400 // All objects in the to space have been copied from the from space at this |
406 // moment. | 401 // moment. |
407 | 402 |
408 // Ensure the mutator thread will fail the next allocation. This will force | 403 // Ensure the mutator thread will fail the next allocation. This will force |
409 // mutator to allocate a new TLAB | 404 // mutator to allocate a new TLAB |
410 Thread* mutator_thread = isolate->mutator_thread(); | 405 Thread* mutator_thread = isolate->mutator_thread(); |
411 ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB())); | 406 ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB())); |
412 | 407 |
413 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); | 408 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); |
414 if (stats_history_.Size() >= 2) { | 409 if (stats_history_.Size() >= 2) { |
(...skipping 20 matching lines...) Expand all Loading... |
435 VerifyStoreBufferPointerVisitor verify_store_buffer_visitor(isolate, to_); | 430 VerifyStoreBufferPointerVisitor verify_store_buffer_visitor(isolate, to_); |
436 heap_->old_space()->VisitObjectPointers(&verify_store_buffer_visitor); | 431 heap_->old_space()->VisitObjectPointers(&verify_store_buffer_visitor); |
437 } | 432 } |
438 } | 433 } |
439 #endif // defined(DEBUG) | 434 #endif // defined(DEBUG) |
440 from->Delete(); | 435 from->Delete(); |
441 UpdateMaxHeapUsage(); | 436 UpdateMaxHeapUsage(); |
442 if (heap_ != NULL) { | 437 if (heap_ != NULL) { |
443 heap_->UpdateGlobalMaxUsed(); | 438 heap_->UpdateGlobalMaxUsed(); |
444 } | 439 } |
445 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { | |
446 (isolate->gc_epilogue_callback())(); | |
447 } | |
448 } | 440 } |
449 | 441 |
450 void Scavenger::IterateStoreBuffers(Isolate* isolate, | 442 void Scavenger::IterateStoreBuffers(Isolate* isolate, |
451 ScavengerVisitor* visitor) { | 443 ScavengerVisitor* visitor) { |
452 // Iterating through the store buffers. | 444 // Iterating through the store buffers. |
453 // Grab the deduplication sets out of the isolate's consolidated store buffer. | 445 // Grab the deduplication sets out of the isolate's consolidated store buffer. |
454 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); | 446 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); |
455 intptr_t total_count = 0; | 447 intptr_t total_count = 0; |
456 while (pending != NULL) { | 448 while (pending != NULL) { |
457 StoreBufferBlock* next = pending->next(); | 449 StoreBufferBlock* next = pending->next(); |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 return raw_obj; // Found object, return it. | 780 return raw_obj; // Found object, return it. |
789 } | 781 } |
790 cur = next; | 782 cur = next; |
791 } | 783 } |
792 ASSERT(cur == top_); | 784 ASSERT(cur == top_); |
793 } | 785 } |
794 return Object::null(); | 786 return Object::null(); |
795 } | 787 } |
796 | 788 |
797 void Scavenger::Scavenge() { | 789 void Scavenger::Scavenge() { |
798 // TODO(cshapiro): Add a decision procedure for determining when the | |
799 // the API callbacks should be invoked. | |
800 Scavenge(false); | |
801 } | |
802 | |
803 void Scavenger::Scavenge(bool invoke_api_callbacks) { | |
804 Isolate* isolate = heap_->isolate(); | 790 Isolate* isolate = heap_->isolate(); |
805 // Ensure that all threads for this isolate are at a safepoint (either stopped | 791 // Ensure that all threads for this isolate are at a safepoint (either stopped |
806 // or in native code). If two threads are racing at this point, the loser | 792 // or in native code). If two threads are racing at this point, the loser |
807 // will continue with its scavenge after waiting for the winner to complete. | 793 // will continue with its scavenge after waiting for the winner to complete. |
808 // TODO(koda): Consider moving SafepointThreads into allocation failure/retry | 794 // TODO(koda): Consider moving SafepointThreads into allocation failure/retry |
809 // logic to avoid needless collections. | 795 // logic to avoid needless collections. |
810 | 796 |
811 int64_t pre_safe_point = OS::GetCurrentMonotonicMicros(); | 797 int64_t pre_safe_point = OS::GetCurrentMonotonicMicros(); |
812 | 798 |
813 Thread* thread = Thread::Current(); | 799 Thread* thread = Thread::Current(); |
(...skipping 17 matching lines...) Expand all Loading... |
831 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 817 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
832 OS::PrintErr("Verifying before Scavenge..."); | 818 OS::PrintErr("Verifying before Scavenge..."); |
833 heap_->Verify(kForbidMarked); | 819 heap_->Verify(kForbidMarked); |
834 OS::PrintErr(" done.\n"); | 820 OS::PrintErr(" done.\n"); |
835 } | 821 } |
836 | 822 |
837 // Prepare for a scavenge. | 823 // Prepare for a scavenge. |
838 SpaceUsage usage_before = GetCurrentUsage(); | 824 SpaceUsage usage_before = GetCurrentUsage(); |
839 intptr_t promo_candidate_words = | 825 intptr_t promo_candidate_words = |
840 (survivor_end_ - FirstObjectStart()) / kWordSize; | 826 (survivor_end_ - FirstObjectStart()) / kWordSize; |
841 SemiSpace* from = Prologue(isolate, invoke_api_callbacks); | 827 SemiSpace* from = Prologue(isolate); |
842 // The API prologue/epilogue may create/destroy zones, so we must not | 828 // The API prologue/epilogue may create/destroy zones, so we must not |
843 // depend on zone allocations surviving beyond the epilogue callback. | 829 // depend on zone allocations surviving beyond the epilogue callback. |
844 { | 830 { |
845 StackZone zone(thread); | 831 StackZone zone(thread); |
846 // Setup the visitor and run the scavenge. | 832 // Setup the visitor and run the scavenge. |
847 ScavengerVisitor visitor(isolate, this, from); | 833 ScavengerVisitor visitor(isolate, this, from); |
848 page_space->AcquireDataLock(); | 834 page_space->AcquireDataLock(); |
849 IterateRoots(isolate, &visitor); | 835 IterateRoots(isolate, &visitor); |
850 int64_t start = OS::GetCurrentMonotonicMicros(); | 836 int64_t start = OS::GetCurrentMonotonicMicros(); |
851 ProcessToSpace(&visitor); | 837 ProcessToSpace(&visitor); |
852 int64_t middle = OS::GetCurrentMonotonicMicros(); | 838 int64_t middle = OS::GetCurrentMonotonicMicros(); |
853 { | 839 { |
854 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); | 840 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); |
855 ScavengerWeakVisitor weak_visitor(thread, this); | 841 ScavengerWeakVisitor weak_visitor(thread, this); |
856 IterateWeakRoots(isolate, &weak_visitor); | 842 IterateWeakRoots(isolate, &weak_visitor); |
857 } | 843 } |
858 ProcessWeakReferences(); | 844 ProcessWeakReferences(); |
859 page_space->ReleaseDataLock(); | 845 page_space->ReleaseDataLock(); |
860 | 846 |
861 // Scavenge finished. Run accounting. | 847 // Scavenge finished. Run accounting. |
862 int64_t end = OS::GetCurrentMonotonicMicros(); | 848 int64_t end = OS::GetCurrentMonotonicMicros(); |
863 heap_->RecordTime(kProcessToSpace, middle - start); | 849 heap_->RecordTime(kProcessToSpace, middle - start); |
864 heap_->RecordTime(kIterateWeaks, end - middle); | 850 heap_->RecordTime(kIterateWeaks, end - middle); |
865 stats_history_.Add(ScavengeStats( | 851 stats_history_.Add(ScavengeStats( |
866 start, end, usage_before, GetCurrentUsage(), promo_candidate_words, | 852 start, end, usage_before, GetCurrentUsage(), promo_candidate_words, |
867 visitor.bytes_promoted() >> kWordSizeLog2)); | 853 visitor.bytes_promoted() >> kWordSizeLog2)); |
868 } | 854 } |
869 Epilogue(isolate, from, invoke_api_callbacks); | 855 Epilogue(isolate, from); |
870 | 856 |
871 // TODO(koda): Make verification more compatible with concurrent sweep. | 857 // TODO(koda): Make verification more compatible with concurrent sweep. |
872 if (FLAG_verify_after_gc && !FLAG_concurrent_sweep) { | 858 if (FLAG_verify_after_gc && !FLAG_concurrent_sweep) { |
873 OS::PrintErr("Verifying after Scavenge..."); | 859 OS::PrintErr("Verifying after Scavenge..."); |
874 heap_->Verify(kForbidMarked); | 860 heap_->Verify(kForbidMarked); |
875 OS::PrintErr(" done.\n"); | 861 OS::PrintErr(" done.\n"); |
876 } | 862 } |
877 | 863 |
878 // Done scavenging. Reset the marker. | 864 // Done scavenging. Reset the marker. |
879 ASSERT(scavenging_); | 865 ASSERT(scavenging_); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 return free_space >> kWordSizeLog2; | 949 return free_space >> kWordSizeLog2; |
964 } | 950 } |
965 | 951 |
966 int64_t Scavenger::UsedInWords() const { | 952 int64_t Scavenger::UsedInWords() const { |
967 int64_t free_space_in_tlab = FreeSpaceInWords(heap_->isolate()); | 953 int64_t free_space_in_tlab = FreeSpaceInWords(heap_->isolate()); |
968 int64_t max_space_used = (top_ - FirstObjectStart()) >> kWordSizeLog2; | 954 int64_t max_space_used = (top_ - FirstObjectStart()) >> kWordSizeLog2; |
969 return max_space_used - free_space_in_tlab; | 955 return max_space_used - free_space_in_tlab; |
970 } | 956 } |
971 | 957 |
972 } // namespace dart | 958 } // namespace dart |
OLD | NEW |