| 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 <map> |
| 8 #include <utility> |
| 9 |
| 7 #include "vm/dart.h" | 10 #include "vm/dart.h" |
| 8 #include "vm/dart_api_state.h" | 11 #include "vm/dart_api_state.h" |
| 9 #include "vm/isolate.h" | 12 #include "vm/isolate.h" |
| 10 #include "vm/object.h" | 13 #include "vm/object.h" |
| 11 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
| 12 #include "vm/store_buffer.h" | 15 #include "vm/store_buffer.h" |
| 13 #include "vm/verifier.h" | 16 #include "vm/verifier.h" |
| 14 #include "vm/visitor.h" | 17 #include "vm/visitor.h" |
| 15 | 18 |
| 16 namespace dart { | 19 namespace dart { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 visiting_old_pointers_(false) {} | 59 visiting_old_pointers_(false) {} |
| 57 | 60 |
| 58 void VisitPointers(RawObject** first, RawObject** last) { | 61 void VisitPointers(RawObject** first, RawObject** last) { |
| 59 for (RawObject** current = first; current <= last; current++) { | 62 for (RawObject** current = first; current <= last; current++) { |
| 60 ScavengePointer(current); | 63 ScavengePointer(current); |
| 61 } | 64 } |
| 62 } | 65 } |
| 63 | 66 |
| 64 void VisitingOldPointers(bool value) { visiting_old_pointers_ = value; } | 67 void VisitingOldPointers(bool value) { visiting_old_pointers_ = value; } |
| 65 | 68 |
| 69 void DelayWeakProperty(RawWeakProperty* raw_weak) { |
| 70 RawObject* raw_key = raw_weak->ptr()->key_; |
| 71 DelaySet::iterator it = delay_set_.find(raw_key); |
| 72 if (it != delay_set_.end()) { |
| 73 ASSERT(raw_key->IsWatched()); |
| 74 } else { |
| 75 ASSERT(!raw_key->IsWatched()); |
| 76 raw_key->SetWatchedBit(); |
| 77 } |
| 78 delay_set_.insert(std::make_pair(raw_key, raw_weak)); |
| 79 } |
| 80 |
| 81 void Finalize() { |
| 82 DelaySet::iterator it = delay_set_.begin(); |
| 83 for (; it != delay_set_.end(); ++it) { |
| 84 WeakProperty::Clear(it->second); |
| 85 } |
| 86 } |
| 87 |
| 66 private: | 88 private: |
| 67 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 89 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
| 68 uword ptr = reinterpret_cast<uword>(p); | 90 uword ptr = reinterpret_cast<uword>(p); |
| 69 ASSERT(obj->IsHeapObject()); | 91 ASSERT(obj->IsHeapObject()); |
| 70 ASSERT(!scavenger_->Contains(ptr)); | 92 ASSERT(!scavenger_->Contains(ptr)); |
| 71 ASSERT(!heap_->CodeContains(ptr)); | 93 ASSERT(!heap_->CodeContains(ptr)); |
| 72 ASSERT(heap_->Contains(ptr)); | 94 ASSERT(heap_->Contains(ptr)); |
| 73 // If the newly written object is not a new object, drop it immediately. | 95 // If the newly written object is not a new object, drop it immediately. |
| 74 if (!obj->IsNewObject()) return; | 96 if (!obj->IsNewObject()) return; |
| 75 isolate()->store_buffer()->AddPointer(ptr); | 97 isolate()->store_buffer()->AddPointer(ptr); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 93 } | 115 } |
| 94 | 116 |
| 95 // Read the header word of the object and determine if the object has | 117 // Read the header word of the object and determine if the object has |
| 96 // already been copied. | 118 // already been copied. |
| 97 uword header = *reinterpret_cast<uword*>(raw_addr); | 119 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 98 uword new_addr = 0; | 120 uword new_addr = 0; |
| 99 if (IsForwarding(header)) { | 121 if (IsForwarding(header)) { |
| 100 // Get the new location of the object. | 122 // Get the new location of the object. |
| 101 new_addr = ForwardedAddr(header); | 123 new_addr = ForwardedAddr(header); |
| 102 } else { | 124 } else { |
| 125 if (raw_obj->IsWatched()) { |
| 126 std::pair<DelaySet::iterator, DelaySet::iterator> ret; |
| 127 // Visit all elements with a key equal to raw_obj. |
| 128 ret = delay_set_.equal_range(raw_obj); |
| 129 for (DelaySet::iterator it = ret.first; it != ret.second; ++it) { |
| 130 it->second->VisitPointers(this); |
| 131 } |
| 132 delay_set_.erase(ret.first, ret.second); |
| 133 raw_obj->ClearWatchedBit(); |
| 134 } |
| 103 intptr_t size = raw_obj->Size(); | 135 intptr_t size = raw_obj->Size(); |
| 104 // Check whether object should be promoted. | 136 // Check whether object should be promoted. |
| 105 if (scavenger_->survivor_end_ <= raw_addr) { | 137 if (scavenger_->survivor_end_ <= raw_addr) { |
| 106 // Not a survivor of a previous scavenge. Just copy the object into the | 138 // Not a survivor of a previous scavenge. Just copy the object into the |
| 107 // to space. | 139 // to space. |
| 108 new_addr = scavenger_->TryAllocate(size); | 140 new_addr = scavenger_->TryAllocate(size); |
| 109 } else { | 141 } else { |
| 110 // TODO(iposva): Experiment with less aggressive promotion. For example | 142 // TODO(iposva): Experiment with less aggressive promotion. For example |
| 111 // a coin toss determines if an object is promoted or whether it should | 143 // a coin toss determines if an object is promoted or whether it should |
| 112 // survive in this generation. | 144 // survive in this generation. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 139 *p = new_obj; | 171 *p = new_obj; |
| 140 // Update the store buffer as needed. | 172 // Update the store buffer as needed. |
| 141 if (visiting_old_pointers_) { | 173 if (visiting_old_pointers_) { |
| 142 UpdateStoreBuffer(p, new_obj); | 174 UpdateStoreBuffer(p, new_obj); |
| 143 } | 175 } |
| 144 } | 176 } |
| 145 | 177 |
| 146 Scavenger* scavenger_; | 178 Scavenger* scavenger_; |
| 147 Heap* heap_; | 179 Heap* heap_; |
| 148 Heap* vm_heap_; | 180 Heap* vm_heap_; |
| 181 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
| 182 DelaySet delay_set_; |
| 149 | 183 |
| 150 bool visiting_old_pointers_; | 184 bool visiting_old_pointers_; |
| 151 | 185 |
| 152 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 186 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
| 153 }; | 187 }; |
| 154 | 188 |
| 155 | 189 |
| 156 class ScavengerWeakVisitor : public HandleVisitor { | 190 class ScavengerWeakVisitor : public HandleVisitor { |
| 157 public: | 191 public: |
| 158 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { | 192 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 isolate->VisitWeakPersistentHandles(visitor, | 466 isolate->VisitWeakPersistentHandles(visitor, |
| 433 visit_prologue_weak_persistent_handles); | 467 visit_prologue_weak_persistent_handles); |
| 434 } | 468 } |
| 435 | 469 |
| 436 | 470 |
| 437 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { | 471 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
| 438 // Iterate until all work has been drained. | 472 // Iterate until all work has been drained. |
| 439 while ((resolved_top_ < top_) || PromotedStackHasMore()) { | 473 while ((resolved_top_ < top_) || PromotedStackHasMore()) { |
| 440 while (resolved_top_ < top_) { | 474 while (resolved_top_ < top_) { |
| 441 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 475 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
| 442 resolved_top_ += raw_obj->VisitPointers(visitor); | 476 intptr_t class_id = raw_obj->GetClassId(); |
| 477 if (class_id != kWeakPropertyCid) { |
| 478 resolved_top_ += raw_obj->VisitPointers(visitor); |
| 479 } else { |
| 480 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
| 481 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); |
| 482 } |
| 443 } | 483 } |
| 444 visitor->VisitingOldPointers(true); | 484 visitor->VisitingOldPointers(true); |
| 445 while (PromotedStackHasMore()) { | 485 while (PromotedStackHasMore()) { |
| 446 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 486 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
| 447 // Resolve or copy all objects referred to by the current object. This | 487 // Resolve or copy all objects referred to by the current object. This |
| 448 // can potentially push more objects on this stack as well as add more | 488 // can potentially push more objects on this stack as well as add more |
| 449 // objects to be resolved in the to space. | 489 // objects to be resolved in the to space. |
| 450 raw_object->VisitPointers(visitor); | 490 raw_object->VisitPointers(visitor); |
| 451 } | 491 } |
| 452 visitor->VisitingOldPointers(false); | 492 visitor->VisitingOldPointers(false); |
| 453 } | 493 } |
| 454 } | 494 } |
| 455 | 495 |
| 456 | 496 |
| 497 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, |
| 498 ScavengerVisitor* visitor) { |
| 499 // The fate of the weak property is determined by its key. |
| 500 RawObject* raw_key = raw_weak->ptr()->key_; |
| 501 uword raw_addr = RawObject::ToAddr(raw_key); |
| 502 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 503 if (!IsForwarding(header)) { |
| 504 // Key is white. Delay the weak property. |
| 505 visitor->DelayWeakProperty(raw_weak); |
| 506 return raw_weak->Size(); |
| 507 } else { |
| 508 // Key is gray or black. Make the weak property black. |
| 509 return raw_weak->VisitPointers(visitor); |
| 510 } |
| 511 } |
| 512 |
| 513 |
| 457 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 514 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 458 uword cur = FirstObjectStart(); | 515 uword cur = FirstObjectStart(); |
| 459 while (cur < top_) { | 516 while (cur < top_) { |
| 460 RawObject* raw_obj = RawObject::FromAddr(cur); | 517 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 461 cur += raw_obj->VisitPointers(visitor); | 518 cur += raw_obj->VisitPointers(visitor); |
| 462 } | 519 } |
| 463 } | 520 } |
| 464 | 521 |
| 465 | 522 |
| 466 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 523 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 Timer timer(FLAG_verbose_gc, "Scavenge"); | 557 Timer timer(FLAG_verbose_gc, "Scavenge"); |
| 501 timer.Start(); | 558 timer.Start(); |
| 502 // Setup the visitor and run a scavenge. | 559 // Setup the visitor and run a scavenge. |
| 503 ScavengerVisitor visitor(isolate, this); | 560 ScavengerVisitor visitor(isolate, this); |
| 504 Prologue(isolate, invoke_api_callbacks); | 561 Prologue(isolate, invoke_api_callbacks); |
| 505 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 562 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| 506 ProcessToSpace(&visitor); | 563 ProcessToSpace(&visitor); |
| 507 IterateWeakReferences(isolate, &visitor); | 564 IterateWeakReferences(isolate, &visitor); |
| 508 ScavengerWeakVisitor weak_visitor(this); | 565 ScavengerWeakVisitor weak_visitor(this); |
| 509 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 566 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| 567 visitor.Finalize(); |
| 510 Epilogue(isolate, invoke_api_callbacks); | 568 Epilogue(isolate, invoke_api_callbacks); |
| 511 timer.Stop(); | 569 timer.Stop(); |
| 512 if (FLAG_verbose_gc) { | 570 if (FLAG_verbose_gc) { |
| 513 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 571 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
| 514 } | 572 } |
| 515 | 573 |
| 516 if (FLAG_verify_after_gc) { | 574 if (FLAG_verify_after_gc) { |
| 517 OS::PrintErr("Verifying after Scavenge..."); | 575 OS::PrintErr("Verifying after Scavenge..."); |
| 518 heap_->Verify(); | 576 heap_->Verify(); |
| 519 OS::PrintErr(" done.\n"); | 577 OS::PrintErr(" done.\n"); |
| 520 } | 578 } |
| 521 | 579 |
| 522 count_++; | 580 count_++; |
| 523 // Done scavenging. Reset the marker. | 581 // Done scavenging. Reset the marker. |
| 524 ASSERT(scavenging_); | 582 ASSERT(scavenging_); |
| 525 scavenging_ = false; | 583 scavenging_ = false; |
| 526 } | 584 } |
| 527 | 585 |
| 528 | 586 |
| 529 void Scavenger::WriteProtect(bool read_only) { | 587 void Scavenger::WriteProtect(bool read_only) { |
| 530 space_->Protect( | 588 space_->Protect( |
| 531 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); | 589 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); |
| 532 } | 590 } |
| 533 | 591 |
| 534 } // namespace dart | 592 } // namespace dart |
| OLD | NEW |