| 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); |
| 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 |
| 281 void Scavenger::IterateStoreBuffers(Isolate* isolate, |
| 282 ScavengerVisitor* visitor) { |
| 283 // Iterating through the store buffers. |
| 284 visitor->VisitingOldPointers(true); |
| 285 // Grab the deduplication sets out of the store buffer. |
| 286 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets(); |
| 287 intptr_t entries = 0; |
| 288 intptr_t duplicates = 0; |
| 289 while (pending != NULL) { |
| 290 StoreBuffer::DedupSet* next = pending->next(); |
| 291 HashSet* set = pending->set(); |
| 292 intptr_t count = set->Count(); |
| 293 intptr_t size = set->Size(); |
| 294 intptr_t handled = 0; |
| 295 entries += count; |
| 296 for (intptr_t i = 0; i < size; i++) { |
| 297 RawObject** pointer = reinterpret_cast<RawObject**>(set->At(i)); |
| 298 if (pointer != NULL) { |
| 299 RawObject* value = *pointer; |
| 300 // Skip entries that have been overwritten with Smis. |
| 301 if (value->IsHeapObject()) { |
| 302 if (from_->Contains(RawObject::ToAddr(value))) { |
| 303 visitor->VisitPointer(pointer); |
| 304 } else { |
| 305 duplicates++; |
| 306 } |
| 307 } |
| 308 handled++; |
| 309 if (handled == count) { |
| 310 break; |
| 311 } |
| 312 } |
| 313 } |
| 314 delete pending; |
| 315 pending = next; |
| 316 } |
| 317 if (FLAG_verbose_gc) { |
| 318 OS::PrintErr("StoreBuffer: %d, %d (entries, dups)\n", |
| 319 entries, duplicates); |
| 320 } |
| 321 StoreBufferBlock* block = isolate->store_buffer_block(); |
| 322 entries = block->Count(); |
| 323 duplicates = 0; |
| 324 for (intptr_t i = 0; i < entries; i++) { |
| 325 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i)); |
| 326 if (from_->Contains(RawObject::ToAddr(*pointer))) { |
| 327 visitor->VisitPointer(pointer); |
| 328 } else { |
| 329 duplicates++; |
| 330 } |
| 331 } |
| 332 block->Reset(); |
| 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 } |
| 340 |
| 341 |
| 240 void Scavenger::IterateRoots(Isolate* isolate, | 342 void Scavenger::IterateRoots(Isolate* isolate, |
| 241 ObjectPointerVisitor* visitor, | 343 ScavengerVisitor* visitor, |
| 242 bool visit_prologue_weak_persistent_handles) { | 344 bool visit_prologue_weak_persistent_handles) { |
| 345 IterateStoreBuffers(isolate, visitor); |
| 243 isolate->VisitObjectPointers(visitor, | 346 isolate->VisitObjectPointers(visitor, |
| 244 visit_prologue_weak_persistent_handles, | 347 visit_prologue_weak_persistent_handles, |
| 245 StackFrameIterator::kDontValidateFrames); | 348 StackFrameIterator::kDontValidateFrames); |
| 246 heap_->IterateOldPointers(visitor); | |
| 247 } | 349 } |
| 248 | 350 |
| 249 | 351 |
| 250 bool Scavenger::IsUnreachable(RawObject** p) { | 352 bool Scavenger::IsUnreachable(RawObject** p) { |
| 251 RawObject* raw_obj = *p; | 353 RawObject* raw_obj = *p; |
| 252 if (!raw_obj->IsHeapObject()) { | 354 if (!raw_obj->IsHeapObject()) { |
| 253 return false; | 355 return false; |
| 254 } | 356 } |
| 255 if (!raw_obj->IsNewObject()) { | 357 if (!raw_obj->IsNewObject()) { |
| 256 return false; | 358 return false; |
| 257 } | 359 } |
| 258 uword raw_addr = RawObject::ToAddr(raw_obj); | 360 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 259 if (!from_->Contains(raw_addr)) { | 361 if (!from_->Contains(raw_addr)) { |
| 260 return false; | 362 return false; |
| 261 } | 363 } |
| 262 uword header = *reinterpret_cast<uword*>(raw_addr); | 364 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 263 if (IsForwarding(header)) { | 365 if (IsForwarding(header)) { |
| 264 uword new_addr = ForwardedAddr(header); | 366 uword new_addr = ForwardedAddr(header); |
| 265 *p = RawObject::FromAddr(new_addr); | 367 *p = RawObject::FromAddr(new_addr); |
| 266 return false; | 368 return false; |
| 267 } | 369 } |
| 268 return true; | 370 return true; |
| 269 } | 371 } |
| 270 | 372 |
| 271 | 373 |
| 272 void Scavenger::IterateWeakReferences(Isolate* isolate, | 374 void Scavenger::IterateWeakReferences(Isolate* isolate, |
| 273 ObjectPointerVisitor* visitor) { | 375 ScavengerVisitor* visitor) { |
| 274 ApiState* state = isolate->api_state(); | 376 ApiState* state = isolate->api_state(); |
| 275 ASSERT(state != NULL); | 377 ASSERT(state != NULL); |
| 276 while (true) { | 378 while (true) { |
| 277 WeakReference* queue = state->delayed_weak_references(); | 379 WeakReference* queue = state->delayed_weak_references(); |
| 278 if (queue == NULL) { | 380 if (queue == NULL) { |
| 279 // The delay queue is empty therefore no clean-up is required. | 381 // The delay queue is empty therefore no clean-up is required. |
| 280 return; | 382 return; |
| 281 } | 383 } |
| 282 state->set_delayed_weak_references(NULL); | 384 state->set_delayed_weak_references(NULL); |
| 283 while (queue != NULL) { | 385 while (queue != NULL) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 | 424 |
| 323 | 425 |
| 324 void Scavenger::IterateWeakRoots(Isolate* isolate, | 426 void Scavenger::IterateWeakRoots(Isolate* isolate, |
| 325 HandleVisitor* visitor, | 427 HandleVisitor* visitor, |
| 326 bool visit_prologue_weak_persistent_handles) { | 428 bool visit_prologue_weak_persistent_handles) { |
| 327 isolate->VisitWeakPersistentHandles(visitor, | 429 isolate->VisitWeakPersistentHandles(visitor, |
| 328 visit_prologue_weak_persistent_handles); | 430 visit_prologue_weak_persistent_handles); |
| 329 } | 431 } |
| 330 | 432 |
| 331 | 433 |
| 332 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 434 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
| 333 // Iterate until all work has been drained. | 435 // Iterate until all work has been drained. |
| 334 while ((resolved_top_ < top_) || PromotedStackHasMore()) { | 436 while ((resolved_top_ < top_) || PromotedStackHasMore()) { |
| 335 while (resolved_top_ < top_) { | 437 while (resolved_top_ < top_) { |
| 336 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 438 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
| 337 resolved_top_ += raw_obj->VisitPointers(visitor); | 439 resolved_top_ += raw_obj->VisitPointers(visitor); |
| 338 } | 440 } |
| 441 visitor->VisitingOldPointers(true); |
| 339 while (PromotedStackHasMore()) { | 442 while (PromotedStackHasMore()) { |
| 340 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 443 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
| 341 // Resolve or copy all objects referred to by the current object. This | 444 // 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 | 445 // can potentially push more objects on this stack as well as add more |
| 343 // objects to be resolved in the to space. | 446 // objects to be resolved in the to space. |
| 344 raw_object->VisitPointers(visitor); | 447 raw_object->VisitPointers(visitor); |
| 345 } | 448 } |
| 449 visitor->VisitingOldPointers(false); |
| 346 } | 450 } |
| 347 } | 451 } |
| 348 | 452 |
| 349 | 453 |
| 350 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 454 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 351 uword cur = FirstObjectStart(); | 455 uword cur = FirstObjectStart(); |
| 352 while (cur < top_) { | 456 while (cur < top_) { |
| 353 RawObject* raw_obj = RawObject::FromAddr(cur); | 457 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 354 cur += raw_obj->VisitPointers(visitor); | 458 cur += raw_obj->VisitPointers(visitor); |
| 355 } | 459 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 380 had_promotion_failure_ = false; | 484 had_promotion_failure_ = false; |
| 381 Isolate* isolate = Isolate::Current(); | 485 Isolate* isolate = Isolate::Current(); |
| 382 NoHandleScope no_handles(isolate); | 486 NoHandleScope no_handles(isolate); |
| 383 | 487 |
| 384 if (FLAG_verify_before_gc) { | 488 if (FLAG_verify_before_gc) { |
| 385 OS::PrintErr("Verifying before Scavenge..."); | 489 OS::PrintErr("Verifying before Scavenge..."); |
| 386 heap_->Verify(); | 490 heap_->Verify(); |
| 387 OS::PrintErr(" done.\n"); | 491 OS::PrintErr(" done.\n"); |
| 388 } | 492 } |
| 389 | 493 |
| 494 if (FLAG_verbose_gc) { |
| 495 OS::PrintErr("Start scavenge\n"); |
| 496 } |
| 390 Timer timer(FLAG_verbose_gc, "Scavenge"); | 497 Timer timer(FLAG_verbose_gc, "Scavenge"); |
| 391 timer.Start(); | 498 timer.Start(); |
| 392 // Setup the visitor and run a scavenge. | 499 // Setup the visitor and run a scavenge. |
| 393 ScavengerVisitor visitor(isolate, this); | 500 ScavengerVisitor visitor(isolate, this); |
| 394 Prologue(isolate, invoke_api_callbacks); | 501 Prologue(isolate, invoke_api_callbacks); |
| 395 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 502 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| 396 ProcessToSpace(&visitor); | 503 ProcessToSpace(&visitor); |
| 397 IterateWeakReferences(isolate, &visitor); | 504 IterateWeakReferences(isolate, &visitor); |
| 398 ScavengerWeakVisitor weak_visitor(this); | 505 ScavengerWeakVisitor weak_visitor(this); |
| 399 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 506 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| 400 Epilogue(isolate, invoke_api_callbacks); | 507 Epilogue(isolate, invoke_api_callbacks); |
| 401 timer.Stop(); | 508 timer.Stop(); |
| 402 if (FLAG_verbose_gc) { | 509 if (FLAG_verbose_gc) { |
| 403 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 510 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
| 404 } | 511 } |
| 405 | 512 |
| 406 if (FLAG_verify_after_gc) { | 513 if (FLAG_verify_after_gc) { |
| 407 OS::PrintErr("Verifying after Scavenge..."); | 514 OS::PrintErr("Verifying after Scavenge..."); |
| 408 heap_->Verify(); | 515 heap_->Verify(); |
| 409 OS::PrintErr(" done.\n"); | 516 OS::PrintErr(" done.\n"); |
| 410 } | 517 } |
| 411 | 518 |
| 412 count_++; | 519 count_++; |
| 413 // Done scavenging. Reset the marker. | 520 // Done scavenging. Reset the marker. |
| 414 ASSERT(scavenging_); | 521 ASSERT(scavenging_); |
| 415 scavenging_ = false; | 522 scavenging_ = false; |
| 416 } | 523 } |
| 417 | 524 |
| 418 } // namespace dart | 525 } // namespace dart |
| OLD | NEW |