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