Chromium Code Reviews| 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/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/stack_frame.h" | 11 #include "vm/stack_frame.h" |
| 12 #include "vm/store_buffer.h" | |
| 12 #include "vm/verifier.h" | 13 #include "vm/verifier.h" |
| 13 #include "vm/visitor.h" | 14 #include "vm/visitor.h" |
| 14 | 15 |
| 15 namespace dart { | 16 namespace dart { |
| 16 | 17 |
| 17 // Scavenger uses RawObject::kFreeBit to distinguish forwaded and non-forwarded | 18 // Scavenger uses RawObject::kFreeBit to distinguish forwaded and non-forwarded |
| 18 // objects because scavenger can never encounter free list element during | 19 // objects because scavenger can never encounter free list element during |
| 19 // evacuation and thus all objects scavenger encounters have | 20 // evacuation and thus all objects scavenger encounters have |
| 20 // kFreeBit cleared. | 21 // kFreeBit cleared. |
| 21 enum { | 22 enum { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 44 *reinterpret_cast<uword*>(orignal) = target | kForwarded; | 45 *reinterpret_cast<uword*>(orignal) = target | kForwarded; |
| 45 } | 46 } |
| 46 | 47 |
| 47 | 48 |
| 48 class ScavengerVisitor : public ObjectPointerVisitor { | 49 class ScavengerVisitor : public ObjectPointerVisitor { |
| 49 public: | 50 public: |
| 50 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) | 51 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) |
| 51 : ObjectPointerVisitor(isolate), | 52 : ObjectPointerVisitor(isolate), |
| 52 scavenger_(scavenger), | 53 scavenger_(scavenger), |
| 53 heap_(scavenger->heap_), | 54 heap_(scavenger->heap_), |
| 54 vm_heap_(Dart::vm_isolate()->heap()) {} | 55 vm_heap_(Dart::vm_isolate()->heap()), |
| 56 visiting_old_pointers_(false) {} | |
| 55 | 57 |
| 56 void VisitPointers(RawObject** first, RawObject** last) { | 58 void VisitPointers(RawObject** first, RawObject** last) { |
| 57 for (RawObject** current = first; current <= last; current++) { | 59 for (RawObject** current = first; current <= last; current++) { |
| 58 ScavengePointer(current); | 60 ScavengePointer(current); |
| 59 } | 61 } |
| 60 } | 62 } |
| 61 | 63 |
| 64 void VisitingOldPointers(bool value) { visiting_old_pointers_ = value; } | |
| 65 | |
| 62 private: | 66 private: |
| 63 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 67 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
| 64 // TODO(iposva): Implement store buffers. | 68 uword ptr = reinterpret_cast<uword>(p); |
| 69 ASSERT(obj->IsHeapObject()); | |
| 70 ASSERT(!scavenger_->Contains(ptr)); | |
| 71 ASSERT(!heap_->CodeContains(ptr)); | |
| 72 ASSERT(heap_->Contains(ptr)); | |
| 73 // If the newly written object is not a new object, drop it immediately. | |
| 74 if (!obj->IsNewObject()) return; | |
| 75 isolate()->store_buffer()->AddPointer(ptr); | |
| 65 } | 76 } |
| 66 | 77 |
| 67 void ScavengePointer(RawObject** p) { | 78 void ScavengePointer(RawObject** p) { |
| 68 RawObject* raw_obj = *p; | 79 RawObject* raw_obj = *p; |
| 69 | 80 |
| 70 // Fast exit if the raw object is a Smi or an old object. | 81 // Fast exit if the raw object is a Smi or an old object. |
| 71 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { | 82 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { |
| 72 return; | 83 return; |
| 73 } | 84 } |
| 74 | 85 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 memmove(reinterpret_cast<void*>(new_addr), | 131 memmove(reinterpret_cast<void*>(new_addr), |
| 121 reinterpret_cast<void*>(raw_addr), | 132 reinterpret_cast<void*>(raw_addr), |
| 122 size); | 133 size); |
| 123 // Remember forwarding address. | 134 // Remember forwarding address. |
| 124 ForwardTo(raw_addr, new_addr); | 135 ForwardTo(raw_addr, new_addr); |
| 125 } | 136 } |
| 126 // Update the reference. | 137 // Update the reference. |
| 127 RawObject* new_obj = RawObject::FromAddr(new_addr); | 138 RawObject* new_obj = RawObject::FromAddr(new_addr); |
| 128 *p = new_obj; | 139 *p = new_obj; |
| 129 // Update the store buffer as needed. | 140 // Update the store buffer as needed. |
| 130 UpdateStoreBuffer(p, new_obj); | 141 if (visiting_old_pointers_) { |
| 142 UpdateStoreBuffer(p, new_obj); | |
| 143 } | |
| 131 } | 144 } |
| 132 | 145 |
| 133 Scavenger* scavenger_; | 146 Scavenger* scavenger_; |
| 134 Heap* heap_; | 147 Heap* heap_; |
| 135 Heap* vm_heap_; | 148 Heap* vm_heap_; |
| 136 | 149 |
| 150 bool visiting_old_pointers_; | |
| 151 | |
| 137 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 152 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
| 138 }; | 153 }; |
| 139 | 154 |
| 140 | 155 |
| 141 class ScavengerWeakVisitor : public HandleVisitor { | 156 class ScavengerWeakVisitor : public HandleVisitor { |
| 142 public: | 157 public: |
| 143 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { | 158 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
| 144 } | 159 } |
| 145 | 160 |
| 146 void VisitHandle(uword addr) { | 161 void VisitHandle(uword addr) { |
| 147 FinalizablePersistentHandle* handle = | 162 FinalizablePersistentHandle* handle = |
| 148 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 163 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
| 149 RawObject** p = reinterpret_cast<RawObject**>(handle); | 164 RawObject** p = reinterpret_cast<RawObject**>(handle); |
| 150 if (scavenger_->IsUnreachable(p)) { | 165 if (scavenger_->IsUnreachable(p)) { |
| 151 FinalizablePersistentHandle::Finalize(handle); | 166 FinalizablePersistentHandle::Finalize(handle); |
| 152 } | 167 } |
| 153 } | 168 } |
| 154 | 169 |
| 155 private: | 170 private: |
| 156 Scavenger* scavenger_; | 171 Scavenger* scavenger_; |
| 157 | 172 |
| 158 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); | 173 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); |
| 159 }; | 174 }; |
| 160 | 175 |
| 161 | 176 |
| 177 // Visitor used to verify that all old->new references have been added to the | |
| 178 // StoreBuffers. | |
| 179 class VerifyStoreBufferPointerVisitor : public ObjectPointerVisitor { | |
| 180 public: | |
| 181 VerifyStoreBufferPointerVisitor(Isolate* isolate, MemoryRegion* to) | |
| 182 : ObjectPointerVisitor(isolate), to_(to) {} | |
| 183 | |
| 184 void VisitPointers(RawObject** first, RawObject** last) { | |
| 185 for (RawObject** current = first; current <= last; current++) { | |
| 186 RawObject* obj = *current; | |
| 187 if (obj->IsHeapObject() && obj->IsNewObject()) { | |
| 188 ASSERT(to_->Contains(RawObject::ToAddr(obj))); | |
| 189 } | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 private: | |
| 194 MemoryRegion* to_; | |
| 195 | |
| 196 DISALLOW_COPY_AND_ASSIGN(VerifyStoreBufferPointerVisitor); | |
| 197 }; | |
| 198 | |
| 199 | |
| 162 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) | 200 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) |
| 163 : heap_(heap), | 201 : heap_(heap), |
| 164 object_alignment_(object_alignment), | 202 object_alignment_(object_alignment), |
| 165 count_(0), | 203 count_(0), |
| 166 scavenging_(false) { | 204 scavenging_(false) { |
| 167 // Verify assumptions about the first word in objects which the scavenger is | 205 // Verify assumptions about the first word in objects which the scavenger is |
| 168 // going to use for forwarding pointers. | 206 // going to use for forwarding pointers. |
| 169 ASSERT(Object::tags_offset() == 0); | 207 ASSERT(Object::tags_offset() == 0); |
| 170 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit)); | 208 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit)); |
| 171 | 209 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 end_ = to_->end(); | 260 end_ = to_->end(); |
| 223 } | 261 } |
| 224 | 262 |
| 225 | 263 |
| 226 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { | 264 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { |
| 227 // All objects in the to space have been copied from the from space at this | 265 // All objects in the to space have been copied from the from space at this |
| 228 // moment. | 266 // moment. |
| 229 survivor_end_ = top_; | 267 survivor_end_ = top_; |
| 230 | 268 |
| 231 #if defined(DEBUG) | 269 #if defined(DEBUG) |
| 270 VerifyStoreBufferPointerVisitor verify_store_buffer_visitor(isolate, to_); | |
| 271 heap_->IterateOldPointers(&verify_store_buffer_visitor); | |
|
siva
2012/07/19 17:36:06
This verification doesn't quite ensure that the st
Ivan Posva
2012/07/20 15:37:46
Discussed offline: Suggestion would work and has t
| |
| 272 | |
| 232 memset(from_->pointer(), 0xf3, from_->size()); | 273 memset(from_->pointer(), 0xf3, from_->size()); |
| 233 #endif // defined(DEBUG) | 274 #endif // defined(DEBUG) |
| 234 if (invoke_api_callbacks) { | 275 if (invoke_api_callbacks) { |
| 235 isolate->gc_epilogue_callbacks().Invoke(); | 276 isolate->gc_epilogue_callbacks().Invoke(); |
| 236 } | 277 } |
| 237 } | 278 } |
| 238 | 279 |
| 239 | 280 |
| 240 void Scavenger::IterateRoots(Isolate* isolate, | 281 void Scavenger::IterateRoots(Isolate* isolate, |
| 241 ObjectPointerVisitor* visitor, | 282 ScavengerVisitor* visitor, |
| 242 bool visit_prologue_weak_persistent_handles) { | 283 bool visit_prologue_weak_persistent_handles) { |
| 284 // Iterating though the store buffers. | |
|
siva
2012/07/19 17:36:06
spelling!!
Ivan Posva
2012/07/20 15:37:46
Done.
| |
| 285 visitor->VisitingOldPointers(true); | |
| 286 // Grab the deduplication sets out of the store buffer. | |
| 287 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets(); | |
| 288 intptr_t entries = 0; | |
| 289 intptr_t duplicates = 0; | |
| 290 while (pending != NULL) { | |
| 291 StoreBuffer::DedupSet* next = pending->next(); | |
| 292 HashSet* set = pending->set(); | |
| 293 intptr_t count = set->Count(); | |
| 294 intptr_t size = set->Size(); | |
| 295 intptr_t handled = 0; | |
| 296 entries += count; | |
| 297 for (intptr_t i = 0; i < size; i++) { | |
| 298 RawObject** pointer = reinterpret_cast<RawObject**>(set->At(i)); | |
| 299 if (pointer != NULL) { | |
| 300 RawObject* value = *pointer; | |
| 301 // Skip entries that have been overwritten with Smis. | |
| 302 if (value->IsHeapObject()) { | |
| 303 if (from_->Contains(RawObject::ToAddr(value))) { | |
| 304 visitor->VisitPointer(pointer); | |
| 305 } else { | |
| 306 duplicates++; | |
| 307 } | |
| 308 } | |
| 309 handled++; | |
| 310 if (handled == count) { | |
| 311 break; | |
| 312 } | |
| 313 } | |
| 314 } | |
| 315 delete pending; | |
| 316 pending = next; | |
| 317 } | |
| 318 if (FLAG_verbose_gc) { | |
| 319 OS::PrintErr("StoreBuffer: %d, %d (entries, dups)\n", | |
| 320 entries, duplicates); | |
| 321 } | |
| 322 StoreBufferBlock* block = isolate->store_buffer_block(); | |
| 323 entries = block->Count(); | |
| 324 duplicates = 0; | |
| 325 for (intptr_t i = 0; i < entries; i++) { | |
| 326 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i)); | |
| 327 if (from_->Contains(RawObject::ToAddr(*pointer))) { | |
| 328 visitor->VisitPointer(pointer); | |
| 329 } else { | |
| 330 duplicates++; | |
| 331 } | |
| 332 } | |
|
siva
2012/07/19 17:36:06
Instead of processing this StoreBufferBlock separa
Ivan Posva
2012/07/20 15:37:46
The number of addresses visited here is limited so
| |
| 333 if (FLAG_verbose_gc) { | |
| 334 OS::PrintErr("StoreBufferBlock: %d, %d (entries, dups)\n", | |
| 335 entries, duplicates); | |
| 336 } | |
| 337 // Done iterating through the store buffers. | |
| 338 visitor->VisitingOldPointers(false); | |
| 339 | |
| 243 isolate->VisitObjectPointers(visitor, | 340 isolate->VisitObjectPointers(visitor, |
| 244 visit_prologue_weak_persistent_handles, | 341 visit_prologue_weak_persistent_handles, |
| 245 StackFrameIterator::kDontValidateFrames); | 342 StackFrameIterator::kDontValidateFrames); |
| 246 heap_->IterateOldPointers(visitor); | |
| 247 } | 343 } |
| 248 | 344 |
| 249 | 345 |
| 250 bool Scavenger::IsUnreachable(RawObject** p) { | 346 bool Scavenger::IsUnreachable(RawObject** p) { |
| 251 RawObject* raw_obj = *p; | 347 RawObject* raw_obj = *p; |
| 252 if (!raw_obj->IsHeapObject()) { | 348 if (!raw_obj->IsHeapObject()) { |
| 253 return false; | 349 return false; |
| 254 } | 350 } |
| 255 if (!raw_obj->IsNewObject()) { | 351 if (!raw_obj->IsNewObject()) { |
| 256 return false; | 352 return false; |
| 257 } | 353 } |
| 258 uword raw_addr = RawObject::ToAddr(raw_obj); | 354 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 259 if (!from_->Contains(raw_addr)) { | 355 if (!from_->Contains(raw_addr)) { |
| 260 return false; | 356 return false; |
| 261 } | 357 } |
| 262 uword header = *reinterpret_cast<uword*>(raw_addr); | 358 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 263 if (IsForwarding(header)) { | 359 if (IsForwarding(header)) { |
| 264 uword new_addr = ForwardedAddr(header); | 360 uword new_addr = ForwardedAddr(header); |
| 265 *p = RawObject::FromAddr(new_addr); | 361 *p = RawObject::FromAddr(new_addr); |
| 266 return false; | 362 return false; |
| 267 } | 363 } |
| 268 return true; | 364 return true; |
| 269 } | 365 } |
| 270 | 366 |
| 271 | 367 |
| 272 void Scavenger::IterateWeakReferences(Isolate* isolate, | 368 void Scavenger::IterateWeakReferences(Isolate* isolate, |
| 273 ObjectPointerVisitor* visitor) { | 369 ScavengerVisitor* visitor) { |
| 274 ApiState* state = isolate->api_state(); | 370 ApiState* state = isolate->api_state(); |
| 275 ASSERT(state != NULL); | 371 ASSERT(state != NULL); |
| 276 while (true) { | 372 while (true) { |
| 277 WeakReference* queue = state->delayed_weak_references(); | 373 WeakReference* queue = state->delayed_weak_references(); |
| 278 if (queue == NULL) { | 374 if (queue == NULL) { |
| 279 // The delay queue is empty therefore no clean-up is required. | 375 // The delay queue is empty therefore no clean-up is required. |
| 280 return; | 376 return; |
| 281 } | 377 } |
| 282 state->set_delayed_weak_references(NULL); | 378 state->set_delayed_weak_references(NULL); |
| 283 while (queue != NULL) { | 379 while (queue != NULL) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 | 418 |
| 323 | 419 |
| 324 void Scavenger::IterateWeakRoots(Isolate* isolate, | 420 void Scavenger::IterateWeakRoots(Isolate* isolate, |
| 325 HandleVisitor* visitor, | 421 HandleVisitor* visitor, |
| 326 bool visit_prologue_weak_persistent_handles) { | 422 bool visit_prologue_weak_persistent_handles) { |
| 327 isolate->VisitWeakPersistentHandles(visitor, | 423 isolate->VisitWeakPersistentHandles(visitor, |
| 328 visit_prologue_weak_persistent_handles); | 424 visit_prologue_weak_persistent_handles); |
| 329 } | 425 } |
| 330 | 426 |
| 331 | 427 |
| 332 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 428 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
| 333 // Iterate until all work has been drained. | 429 // Iterate until all work has been drained. |
| 334 while ((resolved_top_ < top_) || PromotedStackHasMore()) { | 430 while ((resolved_top_ < top_) || PromotedStackHasMore()) { |
| 335 while (resolved_top_ < top_) { | 431 while (resolved_top_ < top_) { |
| 336 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 432 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
| 337 resolved_top_ += raw_obj->VisitPointers(visitor); | 433 resolved_top_ += raw_obj->VisitPointers(visitor); |
| 338 } | 434 } |
| 435 visitor->VisitingOldPointers(true); | |
| 339 while (PromotedStackHasMore()) { | 436 while (PromotedStackHasMore()) { |
| 340 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 437 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
| 341 // Resolve or copy all objects referred to by the current object. This | 438 // Resolve or copy all objects referred to by the current object. This |
| 342 // can potentially push more objects on this stack as well as add more | 439 // can potentially push more objects on this stack as well as add more |
| 343 // objects to be resolved in the to space. | 440 // objects to be resolved in the to space. |
| 344 raw_object->VisitPointers(visitor); | 441 raw_object->VisitPointers(visitor); |
| 345 } | 442 } |
| 443 visitor->VisitingOldPointers(false); | |
| 346 } | 444 } |
| 347 } | 445 } |
| 348 | 446 |
| 349 | 447 |
| 350 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 448 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 351 uword cur = FirstObjectStart(); | 449 uword cur = FirstObjectStart(); |
| 352 while (cur < top_) { | 450 while (cur < top_) { |
| 353 RawObject* raw_obj = RawObject::FromAddr(cur); | 451 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 354 cur += raw_obj->VisitPointers(visitor); | 452 cur += raw_obj->VisitPointers(visitor); |
| 355 } | 453 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 380 had_promotion_failure_ = false; | 478 had_promotion_failure_ = false; |
| 381 Isolate* isolate = Isolate::Current(); | 479 Isolate* isolate = Isolate::Current(); |
| 382 NoHandleScope no_handles(isolate); | 480 NoHandleScope no_handles(isolate); |
| 383 | 481 |
| 384 if (FLAG_verify_before_gc) { | 482 if (FLAG_verify_before_gc) { |
| 385 OS::PrintErr("Verifying before Scavenge..."); | 483 OS::PrintErr("Verifying before Scavenge..."); |
| 386 heap_->Verify(); | 484 heap_->Verify(); |
| 387 OS::PrintErr(" done.\n"); | 485 OS::PrintErr(" done.\n"); |
| 388 } | 486 } |
| 389 | 487 |
| 488 if (FLAG_verbose_gc) { | |
| 489 OS::PrintErr("Start scavenge\n"); | |
| 490 } | |
| 390 Timer timer(FLAG_verbose_gc, "Scavenge"); | 491 Timer timer(FLAG_verbose_gc, "Scavenge"); |
| 391 timer.Start(); | 492 timer.Start(); |
| 392 // Setup the visitor and run a scavenge. | 493 // Setup the visitor and run a scavenge. |
| 393 ScavengerVisitor visitor(isolate, this); | 494 ScavengerVisitor visitor(isolate, this); |
| 394 Prologue(isolate, invoke_api_callbacks); | 495 Prologue(isolate, invoke_api_callbacks); |
| 395 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 496 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| 396 ProcessToSpace(&visitor); | 497 ProcessToSpace(&visitor); |
| 397 IterateWeakReferences(isolate, &visitor); | 498 IterateWeakReferences(isolate, &visitor); |
| 398 ScavengerWeakVisitor weak_visitor(this); | 499 ScavengerWeakVisitor weak_visitor(this); |
| 399 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 500 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| 400 Epilogue(isolate, invoke_api_callbacks); | 501 Epilogue(isolate, invoke_api_callbacks); |
| 401 timer.Stop(); | 502 timer.Stop(); |
| 402 if (FLAG_verbose_gc) { | 503 if (FLAG_verbose_gc) { |
| 403 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 504 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
| 404 } | 505 } |
| 405 | 506 |
| 406 if (FLAG_verify_after_gc) { | 507 if (FLAG_verify_after_gc) { |
| 407 OS::PrintErr("Verifying after Scavenge..."); | 508 OS::PrintErr("Verifying after Scavenge..."); |
| 408 heap_->Verify(); | 509 heap_->Verify(); |
| 409 OS::PrintErr(" done.\n"); | 510 OS::PrintErr(" done.\n"); |
| 410 } | 511 } |
| 411 | 512 |
| 412 count_++; | 513 count_++; |
| 413 // Done scavenging. Reset the marker. | 514 // Done scavenging. Reset the marker. |
| 414 ASSERT(scavenging_); | 515 ASSERT(scavenging_); |
| 415 scavenging_ = false; | 516 scavenging_ = false; |
| 416 } | 517 } |
| 417 | 518 |
| 418 } // namespace dart | 519 } // namespace dart |
| OLD | NEW |