| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "vm/dart.h" | 11 #include "vm/dart.h" |
| 12 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
| 13 #include "vm/isolate.h" | 13 #include "vm/isolate.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/stack_frame.h" | 15 #include "vm/stack_frame.h" |
| 16 #include "vm/store_buffer.h" | 16 #include "vm/store_buffer.h" |
| 17 #include "vm/verifier.h" | 17 #include "vm/verifier.h" |
| 18 #include "vm/visitor.h" | 18 #include "vm/visitor.h" |
| 19 #include "vm/weak_table.h" | |
| 20 | 19 |
| 21 namespace dart { | 20 namespace dart { |
| 22 | 21 |
| 23 // Scavenger uses RawObject::kMarkBit to distinguish forwaded and non-forwarded | 22 // Scavenger uses RawObject::kMarkBit to distinguish forwaded and non-forwarded |
| 24 // objects. The kMarkBit does not intersect with the target address because of | 23 // objects. The kMarkBit does not intersect with the target address because of |
| 25 // object alignment. | 24 // object alignment. |
| 26 enum { | 25 enum { |
| 27 kForwardingMask = 1 << RawObject::kMarkBit, | 26 kForwardingMask = 1 << RawObject::kMarkBit, |
| 28 kNotForwarded = 0, | 27 kNotForwarded = 0, |
| 29 kForwarded = kForwardingMask, | 28 kForwarded = kForwardingMask, |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 // Key is white. Delay the weak property. | 549 // Key is white. Delay the weak property. |
| 551 visitor->DelayWeakProperty(raw_weak); | 550 visitor->DelayWeakProperty(raw_weak); |
| 552 return raw_weak->Size(); | 551 return raw_weak->Size(); |
| 553 } | 552 } |
| 554 } | 553 } |
| 555 // Key is gray or black. Make the weak property black. | 554 // Key is gray or black. Make the weak property black. |
| 556 return raw_weak->VisitPointers(visitor); | 555 return raw_weak->VisitPointers(visitor); |
| 557 } | 556 } |
| 558 | 557 |
| 559 | 558 |
| 560 void Scavenger::ProcessWeakTables() { | 559 void Scavenger::ProcessPeerReferents() { |
| 561 for (int sel = 0; | 560 PeerTable prev; |
| 562 sel < Heap::kNumWeakSelectors; | 561 std::swap(prev, peer_table_); |
| 563 sel++) { | 562 for (PeerTable::iterator it = prev.begin(); it != prev.end(); ++it) { |
| 564 WeakTable* table = heap_->GetWeakTable( | 563 RawObject* raw_obj = it->first; |
| 565 Heap::kNew, static_cast<Heap::WeakSelector>(sel)); | 564 ASSERT(raw_obj->IsHeapObject()); |
| 566 intptr_t size = table->size(); | 565 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 567 heap_->SetWeakTable(Heap::kNew, | 566 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 568 static_cast<Heap::WeakSelector>(sel), | 567 if (IsForwarding(header)) { |
| 569 WeakTable::NewFrom(table)); | 568 // The object has survived. Preserve its record. |
| 570 for (intptr_t i = 0; i < size; i++) { | 569 uword new_addr = ForwardedAddr(header); |
| 571 if (table->IsValidEntryAt(i)) { | 570 raw_obj = RawObject::FromAddr(new_addr); |
| 572 RawObject* raw_obj = table->ObjectAt(i); | 571 heap_->SetPeer(raw_obj, it->second); |
| 573 ASSERT(raw_obj->IsHeapObject()); | |
| 574 uword raw_addr = RawObject::ToAddr(raw_obj); | |
| 575 uword header = *reinterpret_cast<uword*>(raw_addr); | |
| 576 if (IsForwarding(header)) { | |
| 577 // The object has survived. Preserve its record. | |
| 578 uword new_addr = ForwardedAddr(header); | |
| 579 raw_obj = RawObject::FromAddr(new_addr); | |
| 580 heap_->SetWeakEntry(raw_obj, | |
| 581 static_cast<Heap::WeakSelector>(sel), | |
| 582 table->ValueAt(i)); | |
| 583 } | |
| 584 } | |
| 585 } | 572 } |
| 586 } | 573 } |
| 587 } | 574 } |
| 588 | 575 |
| 589 | 576 |
| 590 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 577 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 591 uword cur = FirstObjectStart(); | 578 uword cur = FirstObjectStart(); |
| 592 while (cur < top_) { | 579 while (cur < top_) { |
| 593 RawObject* raw_obj = RawObject::FromAddr(cur); | 580 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 594 cur += raw_obj->VisitPointers(visitor); | 581 cur += raw_obj->VisitPointers(visitor); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 ScavengerVisitor visitor(isolate, this); | 618 ScavengerVisitor visitor(isolate, this); |
| 632 Prologue(isolate, invoke_api_callbacks); | 619 Prologue(isolate, invoke_api_callbacks); |
| 633 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 620 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| 634 int64_t start = OS::GetCurrentTimeMicros(); | 621 int64_t start = OS::GetCurrentTimeMicros(); |
| 635 ProcessToSpace(&visitor); | 622 ProcessToSpace(&visitor); |
| 636 int64_t middle = OS::GetCurrentTimeMicros(); | 623 int64_t middle = OS::GetCurrentTimeMicros(); |
| 637 IterateWeakReferences(isolate, &visitor); | 624 IterateWeakReferences(isolate, &visitor); |
| 638 ScavengerWeakVisitor weak_visitor(this); | 625 ScavengerWeakVisitor weak_visitor(this); |
| 639 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 626 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| 640 visitor.Finalize(); | 627 visitor.Finalize(); |
| 641 ProcessWeakTables(); | 628 ProcessPeerReferents(); |
| 642 int64_t end = OS::GetCurrentTimeMicros(); | 629 int64_t end = OS::GetCurrentTimeMicros(); |
| 643 heap_->RecordTime(kProcessToSpace, middle - start); | 630 heap_->RecordTime(kProcessToSpace, middle - start); |
| 644 heap_->RecordTime(kIterateWeaks, end - middle); | 631 heap_->RecordTime(kIterateWeaks, end - middle); |
| 645 Epilogue(isolate, invoke_api_callbacks); | 632 Epilogue(isolate, invoke_api_callbacks); |
| 646 | 633 |
| 647 if (FLAG_verify_after_gc) { | 634 if (FLAG_verify_after_gc) { |
| 648 OS::PrintErr("Verifying after Scavenge..."); | 635 OS::PrintErr("Verifying after Scavenge..."); |
| 649 heap_->Verify(); | 636 heap_->Verify(); |
| 650 OS::PrintErr(" done.\n"); | 637 OS::PrintErr(" done.\n"); |
| 651 } | 638 } |
| 652 | 639 |
| 653 // Done scavenging. Reset the marker. | 640 // Done scavenging. Reset the marker. |
| 654 ASSERT(scavenging_); | 641 ASSERT(scavenging_); |
| 655 scavenging_ = false; | 642 scavenging_ = false; |
| 656 } | 643 } |
| 657 | 644 |
| 658 | 645 |
| 659 void Scavenger::WriteProtect(bool read_only) { | 646 void Scavenger::WriteProtect(bool read_only) { |
| 660 space_->Protect( | 647 space_->Protect( |
| 661 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); | 648 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); |
| 662 } | 649 } |
| 663 | 650 |
| 664 | 651 |
| 652 void Scavenger::SetPeer(RawObject* raw_obj, void* peer) { |
| 653 if (peer == NULL) { |
| 654 peer_table_.erase(raw_obj); |
| 655 } else { |
| 656 peer_table_[raw_obj] = peer; |
| 657 } |
| 658 } |
| 659 |
| 660 |
| 661 void* Scavenger::GetPeer(RawObject* raw_obj) { |
| 662 PeerTable::iterator it = peer_table_.find(raw_obj); |
| 663 return (it == peer_table_.end()) ? NULL : it->second; |
| 664 } |
| 665 |
| 666 |
| 667 int64_t Scavenger::PeerCount() const { |
| 668 return static_cast<int64_t>(peer_table_.size()); |
| 669 } |
| 670 |
| 665 } // namespace dart | 671 } // namespace dart |
| OLD | NEW |