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()) { | |
turnidge
2012/08/16 23:31:46
Comment here and in similar point in other file --
| |
126 std::pair<DelaySet::iterator, DelaySet::iterator> ret; | |
127 ret = delay_set_.equal_range(raw_obj); | |
128 for (DelaySet::iterator it = ret.first; it != ret.second; ++it) { | |
129 it->second->VisitPointers(this); | |
130 } | |
131 delay_set_.erase(ret.first, ret.second); | |
132 raw_obj->ClearWatchedBit(); | |
133 } | |
103 intptr_t size = raw_obj->Size(); | 134 intptr_t size = raw_obj->Size(); |
104 // Check whether object should be promoted. | 135 // Check whether object should be promoted. |
105 if (scavenger_->survivor_end_ <= raw_addr) { | 136 if (scavenger_->survivor_end_ <= raw_addr) { |
106 // Not a survivor of a previous scavenge. Just copy the object into the | 137 // Not a survivor of a previous scavenge. Just copy the object into the |
107 // to space. | 138 // to space. |
108 new_addr = scavenger_->TryAllocate(size); | 139 new_addr = scavenger_->TryAllocate(size); |
109 } else { | 140 } else { |
110 // TODO(iposva): Experiment with less aggressive promotion. For example | 141 // TODO(iposva): Experiment with less aggressive promotion. For example |
111 // a coin toss determines if an object is promoted or whether it should | 142 // a coin toss determines if an object is promoted or whether it should |
112 // survive in this generation. | 143 // survive in this generation. |
(...skipping 26 matching lines...) Expand all Loading... | |
139 *p = new_obj; | 170 *p = new_obj; |
140 // Update the store buffer as needed. | 171 // Update the store buffer as needed. |
141 if (visiting_old_pointers_) { | 172 if (visiting_old_pointers_) { |
142 UpdateStoreBuffer(p, new_obj); | 173 UpdateStoreBuffer(p, new_obj); |
143 } | 174 } |
144 } | 175 } |
145 | 176 |
146 Scavenger* scavenger_; | 177 Scavenger* scavenger_; |
147 Heap* heap_; | 178 Heap* heap_; |
148 Heap* vm_heap_; | 179 Heap* vm_heap_; |
180 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | |
181 DelaySet delay_set_; | |
149 | 182 |
150 bool visiting_old_pointers_; | 183 bool visiting_old_pointers_; |
151 | 184 |
152 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 185 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
153 }; | 186 }; |
154 | 187 |
155 | 188 |
156 class ScavengerWeakVisitor : public HandleVisitor { | 189 class ScavengerWeakVisitor : public HandleVisitor { |
157 public: | 190 public: |
158 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { | 191 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 isolate->VisitWeakPersistentHandles(visitor, | 465 isolate->VisitWeakPersistentHandles(visitor, |
433 visit_prologue_weak_persistent_handles); | 466 visit_prologue_weak_persistent_handles); |
434 } | 467 } |
435 | 468 |
436 | 469 |
437 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { | 470 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
438 // Iterate until all work has been drained. | 471 // Iterate until all work has been drained. |
439 while ((resolved_top_ < top_) || PromotedStackHasMore()) { | 472 while ((resolved_top_ < top_) || PromotedStackHasMore()) { |
440 while (resolved_top_ < top_) { | 473 while (resolved_top_ < top_) { |
441 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 474 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
442 resolved_top_ += raw_obj->VisitPointers(visitor); | 475 intptr_t class_id = raw_obj->GetClassId(); |
476 if (class_id != kWeakPropertyCid) { | |
477 resolved_top_ += raw_obj->VisitPointers(visitor); | |
478 } else { | |
479 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | |
480 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); | |
481 } | |
443 } | 482 } |
444 visitor->VisitingOldPointers(true); | 483 visitor->VisitingOldPointers(true); |
445 while (PromotedStackHasMore()) { | 484 while (PromotedStackHasMore()) { |
446 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 485 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
447 // Resolve or copy all objects referred to by the current object. This | 486 // 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 | 487 // can potentially push more objects on this stack as well as add more |
449 // objects to be resolved in the to space. | 488 // objects to be resolved in the to space. |
450 raw_object->VisitPointers(visitor); | 489 raw_object->VisitPointers(visitor); |
451 } | 490 } |
452 visitor->VisitingOldPointers(false); | 491 visitor->VisitingOldPointers(false); |
453 } | 492 } |
454 } | 493 } |
455 | 494 |
456 | 495 |
496 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, | |
497 ScavengerVisitor* visitor) { | |
498 // The fate of the weak property is determined by its key. | |
499 RawObject* raw_key = raw_weak->ptr()->key_; | |
500 uword raw_addr = RawObject::ToAddr(raw_key); | |
501 uword header = *reinterpret_cast<uword*>(raw_addr); | |
502 if (!IsForwarding(header)) { | |
503 // Key is white. Delay the weak property. | |
504 visitor->DelayWeakProperty(raw_weak); | |
505 return raw_weak->Size(); | |
506 } else { | |
507 // Key is gray or black. Make the weak property black. | |
508 return raw_weak->VisitPointers(visitor); | |
509 } | |
510 } | |
511 | |
512 | |
457 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 513 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
458 uword cur = FirstObjectStart(); | 514 uword cur = FirstObjectStart(); |
459 while (cur < top_) { | 515 while (cur < top_) { |
460 RawObject* raw_obj = RawObject::FromAddr(cur); | 516 RawObject* raw_obj = RawObject::FromAddr(cur); |
461 cur += raw_obj->VisitPointers(visitor); | 517 cur += raw_obj->VisitPointers(visitor); |
462 } | 518 } |
463 } | 519 } |
464 | 520 |
465 | 521 |
466 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 522 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"); | 556 Timer timer(FLAG_verbose_gc, "Scavenge"); |
501 timer.Start(); | 557 timer.Start(); |
502 // Setup the visitor and run a scavenge. | 558 // Setup the visitor and run a scavenge. |
503 ScavengerVisitor visitor(isolate, this); | 559 ScavengerVisitor visitor(isolate, this); |
504 Prologue(isolate, invoke_api_callbacks); | 560 Prologue(isolate, invoke_api_callbacks); |
505 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 561 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
506 ProcessToSpace(&visitor); | 562 ProcessToSpace(&visitor); |
507 IterateWeakReferences(isolate, &visitor); | 563 IterateWeakReferences(isolate, &visitor); |
508 ScavengerWeakVisitor weak_visitor(this); | 564 ScavengerWeakVisitor weak_visitor(this); |
509 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 565 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
566 visitor.Finalize(); | |
510 Epilogue(isolate, invoke_api_callbacks); | 567 Epilogue(isolate, invoke_api_callbacks); |
511 timer.Stop(); | 568 timer.Stop(); |
512 if (FLAG_verbose_gc) { | 569 if (FLAG_verbose_gc) { |
513 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 570 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
514 } | 571 } |
515 | 572 |
516 if (FLAG_verify_after_gc) { | 573 if (FLAG_verify_after_gc) { |
517 OS::PrintErr("Verifying after Scavenge..."); | 574 OS::PrintErr("Verifying after Scavenge..."); |
518 heap_->Verify(); | 575 heap_->Verify(); |
519 OS::PrintErr(" done.\n"); | 576 OS::PrintErr(" done.\n"); |
520 } | 577 } |
521 | 578 |
522 count_++; | 579 count_++; |
523 // Done scavenging. Reset the marker. | 580 // Done scavenging. Reset the marker. |
524 ASSERT(scavenging_); | 581 ASSERT(scavenging_); |
525 scavenging_ = false; | 582 scavenging_ = false; |
526 } | 583 } |
527 | 584 |
528 | 585 |
529 void Scavenger::WriteProtect(bool read_only) { | 586 void Scavenger::WriteProtect(bool read_only) { |
530 space_->Protect( | 587 space_->Protect( |
531 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); | 588 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); |
532 } | 589 } |
533 | 590 |
534 } // namespace dart | 591 } // namespace dart |
OLD | NEW |