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