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