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 |