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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 new_addr = | 150 new_addr = |
151 page_space_->TryAllocatePromoLocked(size, PageSpace::kForceGrowth); | 151 page_space_->TryAllocatePromoLocked(size, PageSpace::kForceGrowth); |
152 if (new_addr != 0) { | 152 if (new_addr != 0) { |
153 // If promotion succeeded then we need to remember it so that it can | 153 // If promotion succeeded then we need to remember it so that it can |
154 // be traversed later. | 154 // be traversed later. |
155 scavenger_->PushToPromotedStack(new_addr); | 155 scavenger_->PushToPromotedStack(new_addr); |
156 bytes_promoted_ += size; | 156 bytes_promoted_ += size; |
157 NOT_IN_PRODUCT(class_table->UpdateAllocatedOld(cid, size)); | 157 NOT_IN_PRODUCT(class_table->UpdateAllocatedOld(cid, size)); |
158 } else { | 158 } else { |
159 // Promotion did not succeed. Copy into the to space instead. | 159 // Promotion did not succeed. Copy into the to space instead. |
| 160 scavenger_->failed_to_promote_ = true; |
160 new_addr = scavenger_->TryAllocate(size); | 161 new_addr = scavenger_->TryAllocate(size); |
161 NOT_IN_PRODUCT(class_table->UpdateLiveNew(cid, size)); | 162 NOT_IN_PRODUCT(class_table->UpdateLiveNew(cid, size)); |
162 } | 163 } |
163 } | 164 } |
164 // During a scavenge we always succeed to at least copy all of the | 165 // During a scavenge we always succeed to at least copy all of the |
165 // current objects to the to space. | 166 // current objects to the to space. |
166 ASSERT(new_addr != 0); | 167 ASSERT(new_addr != 0); |
167 // Copy the object to the new location. | 168 // Copy the object to the new location. |
168 memmove(reinterpret_cast<void*>(new_addr), | 169 memmove(reinterpret_cast<void*>(new_addr), |
169 reinterpret_cast<void*>(raw_addr), size); | 170 reinterpret_cast<void*>(raw_addr), size); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 Scavenger::Scavenger(Heap* heap, | 332 Scavenger::Scavenger(Heap* heap, |
332 intptr_t max_semi_capacity_in_words, | 333 intptr_t max_semi_capacity_in_words, |
333 uword object_alignment) | 334 uword object_alignment) |
334 : heap_(heap), | 335 : heap_(heap), |
335 max_semi_capacity_in_words_(max_semi_capacity_in_words), | 336 max_semi_capacity_in_words_(max_semi_capacity_in_words), |
336 object_alignment_(object_alignment), | 337 object_alignment_(object_alignment), |
337 scavenging_(false), | 338 scavenging_(false), |
338 delayed_weak_properties_(NULL), | 339 delayed_weak_properties_(NULL), |
339 gc_time_micros_(0), | 340 gc_time_micros_(0), |
340 collections_(0), | 341 collections_(0), |
341 external_size_(0) { | 342 external_size_(0), |
| 343 failed_to_promote_(false) { |
342 // Verify assumptions about the first word in objects which the scavenger is | 344 // Verify assumptions about the first word in objects which the scavenger is |
343 // going to use for forwarding pointers. | 345 // going to use for forwarding pointers. |
344 ASSERT(Object::tags_offset() == 0); | 346 ASSERT(Object::tags_offset() == 0); |
345 | 347 |
346 // Set initial size resulting in a total of three different levels. | 348 // Set initial size resulting in a total of three different levels. |
347 const intptr_t initial_semi_capacity_in_words = | 349 const intptr_t initial_semi_capacity_in_words = |
348 max_semi_capacity_in_words / | 350 max_semi_capacity_in_words / |
349 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); | 351 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); |
350 | 352 |
351 const intptr_t kVmNameSize = 128; | 353 const intptr_t kVmNameSize = 128; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 791 |
790 int64_t pre_safe_point = OS::GetCurrentMonotonicMicros(); | 792 int64_t pre_safe_point = OS::GetCurrentMonotonicMicros(); |
791 | 793 |
792 Thread* thread = Thread::Current(); | 794 Thread* thread = Thread::Current(); |
793 SafepointOperationScope safepoint_scope(thread); | 795 SafepointOperationScope safepoint_scope(thread); |
794 | 796 |
795 // Scavenging is not reentrant. Make sure that is the case. | 797 // Scavenging is not reentrant. Make sure that is the case. |
796 ASSERT(!scavenging_); | 798 ASSERT(!scavenging_); |
797 scavenging_ = true; | 799 scavenging_ = true; |
798 | 800 |
| 801 failed_to_promote_ = false; |
| 802 |
799 PageSpace* page_space = heap_->old_space(); | 803 PageSpace* page_space = heap_->old_space(); |
800 NoSafepointScope no_safepoints; | 804 NoSafepointScope no_safepoints; |
801 | 805 |
802 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); | 806 int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
803 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); | 807 heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
804 | 808 |
805 // TODO(koda): Make verification more compatible with concurrent sweep. | 809 // TODO(koda): Make verification more compatible with concurrent sweep. |
806 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { | 810 if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) { |
807 OS::PrintErr("Verifying before Scavenge..."); | 811 OS::PrintErr("Verifying before Scavenge..."); |
808 heap_->Verify(kForbidMarked); | 812 heap_->Verify(kForbidMarked); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 external_size_ += size; | 902 external_size_ += size; |
899 } | 903 } |
900 | 904 |
901 | 905 |
902 void Scavenger::FreeExternal(intptr_t size) { | 906 void Scavenger::FreeExternal(intptr_t size) { |
903 ASSERT(size >= 0); | 907 ASSERT(size >= 0); |
904 external_size_ -= size; | 908 external_size_ -= size; |
905 ASSERT(external_size_ >= 0); | 909 ASSERT(external_size_ >= 0); |
906 } | 910 } |
907 | 911 |
| 912 |
| 913 void Scavenger::Evacuate() { |
| 914 // We need a safepoint here to prevent allocation right before or right after |
| 915 // the scavenge. |
| 916 // The former can introduce an object that we might fail to collect. |
| 917 // The latter means even if the scavenge promotes every object in the new |
| 918 // space, the new allocation means the space is not empty, |
| 919 // causing the assertion below to fail. |
| 920 SafepointOperationScope scope(Thread::Current()); |
| 921 |
| 922 // Forces the next scavenge to promote all the objects in the new space. |
| 923 survivor_end_ = top_; |
| 924 Scavenge(); |
| 925 |
| 926 // It is possible for objects to stay in the new space |
| 927 // if the VM cannot create more pages for these objects. |
| 928 ASSERT((UsedInWords() == 0) || failed_to_promote_); |
| 929 } |
| 930 |
908 } // namespace dart | 931 } // namespace dart |
OLD | NEW |