Index: runtime/vm/scavenger.cc |
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc |
index a13bcce75a27f8ceee815933cd333ac69f8ebe6e..34810a109fe21f4382c01d7ad88892b38b329592 100644 |
--- a/runtime/vm/scavenger.cc |
+++ b/runtime/vm/scavenger.cc |
@@ -157,6 +157,7 @@ class ScavengerVisitor : public ObjectPointerVisitor { |
NOT_IN_PRODUCT(class_table->UpdateAllocatedOld(cid, size)); |
} else { |
// Promotion did not succeed. Copy into the to space instead. |
+ scavenger_->failed_to_promote_ = true; |
new_addr = scavenger_->TryAllocate(size); |
NOT_IN_PRODUCT(class_table->UpdateLiveNew(cid, size)); |
} |
@@ -338,7 +339,8 @@ Scavenger::Scavenger(Heap* heap, |
delayed_weak_properties_(NULL), |
gc_time_micros_(0), |
collections_(0), |
- external_size_(0) { |
+ external_size_(0), |
+ failed_to_promote_(false) { |
// Verify assumptions about the first word in objects which the scavenger is |
// going to use for forwarding pointers. |
ASSERT(Object::tags_offset() == 0); |
@@ -796,6 +798,8 @@ void Scavenger::Scavenge(bool invoke_api_callbacks) { |
ASSERT(!scavenging_); |
scavenging_ = true; |
+ failed_to_promote_ = false; |
+ |
PageSpace* page_space = heap_->old_space(); |
NoSafepointScope no_safepoints; |
@@ -905,4 +909,23 @@ void Scavenger::FreeExternal(intptr_t size) { |
ASSERT(external_size_ >= 0); |
} |
+ |
+void Scavenger::Evacuate() { |
+ // We need a safepoint here to prevent allocation right before or right after |
+ // the scavenge. |
+ // The former can introduce an object that we might fail to collect. |
+ // The latter means even if the scavenge promotes every object in the new |
+ // space, the new allocation means the space is not empty, |
+ // causing the assertion below to fail. |
+ SafepointOperationScope scope(Thread::Current()); |
+ |
+ // Forces the next scavenge to promote all the objects in the new space. |
+ survivor_end_ = top_; |
+ Scavenge(); |
+ |
+ // It is possible for objects to stay in the new space |
+ // if the VM cannot create more pages for these objects. |
+ ASSERT((UsedInWords() == 0) || failed_to_promote_); |
+} |
+ |
} // namespace dart |