| 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> | |
| 8 #include <map> | |
| 9 #include <utility> | |
| 10 | |
| 11 #include "vm/dart.h" | 7 #include "vm/dart.h" |
| 12 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
| 13 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 14 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| 15 #include "vm/object.h" | 11 #include "vm/object.h" |
| 16 #include "vm/object_id_ring.h" | 12 #include "vm/object_id_ring.h" |
| 17 #include "vm/safepoint.h" | 13 #include "vm/safepoint.h" |
| 18 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
| 19 #include "vm/store_buffer.h" | 15 #include "vm/store_buffer.h" |
| 20 #include "vm/thread_registry.h" | 16 #include "vm/thread_registry.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 } | 52 } |
| 57 | 53 |
| 58 | 54 |
| 59 static inline void ForwardTo(uword original, uword target) { | 55 static inline void ForwardTo(uword original, uword target) { |
| 60 // Make sure forwarding can be encoded. | 56 // Make sure forwarding can be encoded. |
| 61 ASSERT((target & kForwardingMask) == 0); | 57 ASSERT((target & kForwardingMask) == 0); |
| 62 *reinterpret_cast<uword*>(original) = target | kForwarded; | 58 *reinterpret_cast<uword*>(original) = target | kForwarded; |
| 63 } | 59 } |
| 64 | 60 |
| 65 | 61 |
| 66 class BoolScope : public ValueObject { | |
| 67 public: | |
| 68 BoolScope(bool* addr, bool value) : _addr(addr), _value(*addr) { | |
| 69 *_addr = value; | |
| 70 } | |
| 71 ~BoolScope() { | |
| 72 *_addr = _value; | |
| 73 } | |
| 74 | |
| 75 private: | |
| 76 bool* _addr; | |
| 77 bool _value; | |
| 78 }; | |
| 79 | |
| 80 | |
| 81 class ScavengerVisitor : public ObjectPointerVisitor { | 62 class ScavengerVisitor : public ObjectPointerVisitor { |
| 82 public: | 63 public: |
| 83 explicit ScavengerVisitor(Isolate* isolate, | 64 explicit ScavengerVisitor(Isolate* isolate, |
| 84 Scavenger* scavenger, | 65 Scavenger* scavenger, |
| 85 SemiSpace* from) | 66 SemiSpace* from) |
| 86 : ObjectPointerVisitor(isolate), | 67 : ObjectPointerVisitor(isolate), |
| 87 thread_(Thread::Current()), | 68 thread_(Thread::Current()), |
| 88 scavenger_(scavenger), | 69 scavenger_(scavenger), |
| 89 from_(from), | 70 from_(from), |
| 90 heap_(scavenger->heap_), | 71 heap_(scavenger->heap_), |
| 91 vm_heap_(Dart::vm_isolate()->heap()), | 72 vm_heap_(Dart::vm_isolate()->heap()), |
| 92 page_space_(scavenger->heap_->old_space()), | 73 page_space_(scavenger->heap_->old_space()), |
| 93 delayed_weak_stack_(), | |
| 94 bytes_promoted_(0), | 74 bytes_promoted_(0), |
| 95 visiting_old_object_(NULL), | 75 visiting_old_object_(NULL) { } |
| 96 in_scavenge_pointer_(false) { } | |
| 97 | 76 |
| 98 void VisitPointers(RawObject** first, RawObject** last) { | 77 void VisitPointers(RawObject** first, RawObject** last) { |
| 78 ASSERT((visiting_old_object_ != NULL) || |
| 79 scavenger_->Contains(reinterpret_cast<uword>(first)) || |
| 80 !heap_->Contains(reinterpret_cast<uword>(first))); |
| 99 for (RawObject** current = first; current <= last; current++) { | 81 for (RawObject** current = first; current <= last; current++) { |
| 100 ScavengePointer(current); | 82 ScavengePointer(current); |
| 101 } | 83 } |
| 102 } | 84 } |
| 103 | 85 |
| 104 GrowableArray<RawObject*>* DelayedWeakStack() { | |
| 105 return &delayed_weak_stack_; | |
| 106 } | |
| 107 | |
| 108 void VisitingOldObject(RawObject* obj) { | 86 void VisitingOldObject(RawObject* obj) { |
| 109 ASSERT((obj == NULL) || obj->IsOldObject()); | 87 ASSERT((obj == NULL) || obj->IsOldObject()); |
| 110 visiting_old_object_ = obj; | 88 visiting_old_object_ = obj; |
| 111 } | 89 } |
| 112 | 90 |
| 113 void DelayWeakProperty(RawWeakProperty* raw_weak) { | |
| 114 RawObject* raw_key = raw_weak->ptr()->key_; | |
| 115 DelaySet::iterator it = delay_set_.find(raw_key); | |
| 116 if (it != delay_set_.end()) { | |
| 117 ASSERT(raw_key->IsWatched()); | |
| 118 } else { | |
| 119 ASSERT(!raw_key->IsWatched()); | |
| 120 raw_key->SetWatchedBitUnsynchronized(); | |
| 121 } | |
| 122 delay_set_.insert(std::make_pair(raw_key, raw_weak)); | |
| 123 } | |
| 124 | |
| 125 void Finalize() { | |
| 126 DelaySet::iterator it = delay_set_.begin(); | |
| 127 for (; it != delay_set_.end(); ++it) { | |
| 128 WeakProperty::Clear(it->second); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 intptr_t bytes_promoted() const { return bytes_promoted_; } | 91 intptr_t bytes_promoted() const { return bytes_promoted_; } |
| 133 | 92 |
| 134 private: | 93 private: |
| 135 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 94 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
| 136 uword ptr = reinterpret_cast<uword>(p); | 95 uword ptr = reinterpret_cast<uword>(p); |
| 137 ASSERT(obj->IsHeapObject()); | 96 ASSERT(obj->IsHeapObject()); |
| 138 ASSERT(!scavenger_->Contains(ptr)); | 97 ASSERT(!scavenger_->Contains(ptr)); |
| 139 ASSERT(!heap_->CodeContains(ptr)); | 98 ASSERT(!heap_->CodeContains(ptr)); |
| 140 ASSERT(heap_->Contains(ptr)); | 99 ASSERT(heap_->Contains(ptr)); |
| 141 // If the newly written object is not a new object, drop it immediately. | 100 // If the newly written object is not a new object, drop it immediately. |
| 142 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { | 101 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { |
| 143 return; | 102 return; |
| 144 } | 103 } |
| 145 visiting_old_object_->SetRememberedBit(); | 104 visiting_old_object_->SetRememberedBit(); |
| 146 thread_->StoreBufferAddObjectGC(visiting_old_object_); | 105 thread_->StoreBufferAddObjectGC(visiting_old_object_); |
| 147 } | 106 } |
| 148 | 107 |
| 149 void ScavengePointer(RawObject** p) { | 108 void ScavengePointer(RawObject** p) { |
| 150 // ScavengePointer cannot be called recursively. | 109 // ScavengePointer cannot be called recursively. |
| 151 #ifdef DEBUG | |
| 152 ASSERT(!in_scavenge_pointer_); | |
| 153 BoolScope bs(&in_scavenge_pointer_, true); | |
| 154 #endif | |
| 155 | |
| 156 RawObject* raw_obj = *p; | 110 RawObject* raw_obj = *p; |
| 157 | 111 |
| 158 if (raw_obj->IsSmiOrOldObject()) { | 112 if (raw_obj->IsSmiOrOldObject()) { |
| 159 return; | 113 return; |
| 160 } | 114 } |
| 161 | 115 |
| 162 uword raw_addr = RawObject::ToAddr(raw_obj); | 116 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 163 // The scavenger is only expects objects located in the from space. | 117 // The scavenger is only expects objects located in the from space. |
| 164 ASSERT(from_->Contains(raw_addr)); | 118 ASSERT(from_->Contains(raw_addr)); |
| 165 // Read the header word of the object and determine if the object has | 119 // Read the header word of the object and determine if the object has |
| 166 // already been copied. | 120 // already been copied. |
| 167 uword header = *reinterpret_cast<uword*>(raw_addr); | 121 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 168 uword new_addr = 0; | 122 uword new_addr = 0; |
| 169 if (IsForwarding(header)) { | 123 if (IsForwarding(header)) { |
| 170 // Get the new location of the object. | 124 // Get the new location of the object. |
| 171 new_addr = ForwardedAddr(header); | 125 new_addr = ForwardedAddr(header); |
| 172 } else { | 126 } else { |
| 173 if (raw_obj->IsWatched()) { | |
| 174 raw_obj->ClearWatchedBitUnsynchronized(); | |
| 175 std::pair<DelaySet::iterator, DelaySet::iterator> ret; | |
| 176 // Visit all elements with a key equal to this raw_obj. | |
| 177 ret = delay_set_.equal_range(raw_obj); | |
| 178 for (DelaySet::iterator it = ret.first; it != ret.second; ++it) { | |
| 179 // Remember the delayed WeakProperty. These objects have been | |
| 180 // forwarded, but have not been scavenged because their key was not | |
| 181 // known to be reachable. Now that the key object is known to be | |
| 182 // reachable, we need to visit its key and value pointers. | |
| 183 delayed_weak_stack_.Add(it->second); | |
| 184 } | |
| 185 delay_set_.erase(ret.first, ret.second); | |
| 186 } | |
| 187 intptr_t size = raw_obj->Size(); | 127 intptr_t size = raw_obj->Size(); |
| 188 intptr_t cid = raw_obj->GetClassId(); | 128 intptr_t cid = raw_obj->GetClassId(); |
| 189 ClassTable* class_table = isolate()->class_table(); | 129 ClassTable* class_table = isolate()->class_table(); |
| 190 // Check whether object should be promoted. | 130 // Check whether object should be promoted. |
| 191 if (scavenger_->survivor_end_ <= raw_addr) { | 131 if (scavenger_->survivor_end_ <= raw_addr) { |
| 192 // Not a survivor of a previous scavenge. Just copy the object into the | 132 // Not a survivor of a previous scavenge. Just copy the object into the |
| 193 // to space. | 133 // to space. |
| 194 new_addr = scavenger_->TryAllocate(size); | 134 new_addr = scavenger_->TryAllocate(size); |
| 195 class_table->UpdateLiveNew(cid, size); | 135 class_table->UpdateLiveNew(cid, size); |
| 196 } else { | 136 } else { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 UpdateStoreBuffer(p, new_obj); | 174 UpdateStoreBuffer(p, new_obj); |
| 235 } | 175 } |
| 236 } | 176 } |
| 237 | 177 |
| 238 Thread* thread_; | 178 Thread* thread_; |
| 239 Scavenger* scavenger_; | 179 Scavenger* scavenger_; |
| 240 SemiSpace* from_; | 180 SemiSpace* from_; |
| 241 Heap* heap_; | 181 Heap* heap_; |
| 242 Heap* vm_heap_; | 182 Heap* vm_heap_; |
| 243 PageSpace* page_space_; | 183 PageSpace* page_space_; |
| 244 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 184 RawWeakProperty* delayed_weak_properties_; |
| 245 DelaySet delay_set_; | |
| 246 GrowableArray<RawObject*> delayed_weak_stack_; | |
| 247 // TODO(cshapiro): use this value to compute survival statistics for | |
| 248 // new space growth policy. | |
| 249 intptr_t bytes_promoted_; | 185 intptr_t bytes_promoted_; |
| 250 RawObject* visiting_old_object_; | 186 RawObject* visiting_old_object_; |
| 251 bool in_scavenge_pointer_; | 187 |
| 188 friend class Scavenger; |
| 252 | 189 |
| 253 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 190 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
| 254 }; | 191 }; |
| 255 | 192 |
| 256 | 193 |
| 257 class ScavengerWeakVisitor : public HandleVisitor { | 194 class ScavengerWeakVisitor : public HandleVisitor { |
| 258 public: | 195 public: |
| 259 explicit ScavengerWeakVisitor(Scavenger* scavenger) | 196 explicit ScavengerWeakVisitor(Scavenger* scavenger) |
| 260 : HandleVisitor(Thread::Current()), | 197 : HandleVisitor(Thread::Current()), |
| 261 scavenger_(scavenger) { | 198 scavenger_(scavenger) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 327 } |
| 391 | 328 |
| 392 | 329 |
| 393 Scavenger::Scavenger(Heap* heap, | 330 Scavenger::Scavenger(Heap* heap, |
| 394 intptr_t max_semi_capacity_in_words, | 331 intptr_t max_semi_capacity_in_words, |
| 395 uword object_alignment) | 332 uword object_alignment) |
| 396 : heap_(heap), | 333 : heap_(heap), |
| 397 max_semi_capacity_in_words_(max_semi_capacity_in_words), | 334 max_semi_capacity_in_words_(max_semi_capacity_in_words), |
| 398 object_alignment_(object_alignment), | 335 object_alignment_(object_alignment), |
| 399 scavenging_(false), | 336 scavenging_(false), |
| 337 delayed_weak_properties_(NULL), |
| 400 gc_time_micros_(0), | 338 gc_time_micros_(0), |
| 401 collections_(0), | 339 collections_(0), |
| 402 external_size_(0) { | 340 external_size_(0) { |
| 403 // Verify assumptions about the first word in objects which the scavenger is | 341 // Verify assumptions about the first word in objects which the scavenger is |
| 404 // going to use for forwarding pointers. | 342 // going to use for forwarding pointers. |
| 405 ASSERT(Object::tags_offset() == 0); | 343 ASSERT(Object::tags_offset() == 0); |
| 406 | 344 |
| 407 // Set initial size resulting in a total of three different levels. | 345 // Set initial size resulting in a total of three different levels. |
| 408 const intptr_t initial_semi_capacity_in_words = max_semi_capacity_in_words / | 346 const intptr_t initial_semi_capacity_in_words = max_semi_capacity_in_words / |
| 409 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); | 347 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 return true; | 532 return true; |
| 595 } | 533 } |
| 596 | 534 |
| 597 | 535 |
| 598 void Scavenger::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { | 536 void Scavenger::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { |
| 599 isolate->VisitWeakPersistentHandles(visitor); | 537 isolate->VisitWeakPersistentHandles(visitor); |
| 600 } | 538 } |
| 601 | 539 |
| 602 | 540 |
| 603 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { | 541 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
| 604 GrowableArray<RawObject*>* delayed_weak_stack = visitor->DelayedWeakStack(); | |
| 605 | |
| 606 // Iterate until all work has been drained. | 542 // Iterate until all work has been drained. |
| 607 while ((resolved_top_ < top_) || | 543 while ((resolved_top_ < top_) || |
| 608 PromotedStackHasMore() || | 544 PromotedStackHasMore()) { |
| 609 !delayed_weak_stack->is_empty()) { | |
| 610 while (resolved_top_ < top_) { | 545 while (resolved_top_ < top_) { |
| 611 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 546 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
| 612 intptr_t class_id = raw_obj->GetClassId(); | 547 intptr_t class_id = raw_obj->GetClassId(); |
| 613 if (class_id != kWeakPropertyCid) { | 548 if (class_id != kWeakPropertyCid) { |
| 614 resolved_top_ += raw_obj->VisitPointers(visitor); | 549 resolved_top_ += raw_obj->VisitPointers(visitor); |
| 615 } else { | 550 } else { |
| 616 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | 551 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
| 617 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); | 552 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); |
| 618 } | 553 } |
| 619 } | 554 } |
| 620 { | 555 { |
| 556 // Visit all the promoted objects and update/scavenge their internal |
| 557 // pointers. Potentially this adds more objects to the to space. |
| 621 while (PromotedStackHasMore()) { | 558 while (PromotedStackHasMore()) { |
| 622 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 559 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
| 623 // Resolve or copy all objects referred to by the current object. This | 560 // Resolve or copy all objects referred to by the current object. This |
| 624 // can potentially push more objects on this stack as well as add more | 561 // can potentially push more objects on this stack as well as add more |
| 625 // objects to be resolved in the to space. | 562 // objects to be resolved in the to space. |
| 626 ASSERT(!raw_object->IsRemembered()); | 563 ASSERT(!raw_object->IsRemembered()); |
| 627 visitor->VisitingOldObject(raw_object); | 564 visitor->VisitingOldObject(raw_object); |
| 628 raw_object->VisitPointers(visitor); | 565 raw_object->VisitPointers(visitor); |
| 629 } | 566 } |
| 630 visitor->VisitingOldObject(NULL); | 567 visitor->VisitingOldObject(NULL); |
| 631 } | 568 } |
| 632 while (!delayed_weak_stack->is_empty()) { | 569 { |
| 633 // Pop the delayed weak object from the stack and visit its pointers. | 570 // Finished this round of scavenging. Process the pending weak properties |
| 634 RawObject* weak_property = delayed_weak_stack->RemoveLast(); | 571 // for which the keys have become reachable. Potentially this adds more |
| 635 weak_property->VisitPointers(visitor); | 572 // objects to the to space. |
| 573 RawWeakProperty* cur_weak = delayed_weak_properties_; |
| 574 delayed_weak_properties_ = NULL; |
| 575 while (cur_weak != NULL) { |
| 576 uword next_weak = cur_weak->ptr()->next_; |
| 577 // Promoted weak properties are not enqueued. So we can guarantee that |
| 578 // we do not need to think about store barriers here. |
| 579 ASSERT(cur_weak->IsNewObject()); |
| 580 RawObject* raw_key = cur_weak->ptr()->key_; |
| 581 ASSERT(raw_key->IsHeapObject()); |
| 582 // Key still points into from space even if the object has been |
| 583 // promoted to old space by now. The key will be updated accordingly |
| 584 // below when VisitPointers is run. |
| 585 ASSERT(raw_key->IsNewObject()); |
| 586 uword raw_addr = RawObject::ToAddr(raw_key); |
| 587 ASSERT(visitor->from_->Contains(raw_addr)); |
| 588 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 589 // Reset the next pointer in the weak property. |
| 590 cur_weak->ptr()->next_ = 0; |
| 591 if (IsForwarding(header)) { |
| 592 cur_weak->VisitPointers(visitor); |
| 593 } else { |
| 594 EnqueueWeakProperty(cur_weak); |
| 595 } |
| 596 // Advance to next weak property in the queue. |
| 597 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
| 598 } |
| 636 } | 599 } |
| 637 } | 600 } |
| 638 } | 601 } |
| 639 | 602 |
| 640 | 603 |
| 641 void Scavenger::UpdateMaxHeapCapacity() { | 604 void Scavenger::UpdateMaxHeapCapacity() { |
| 642 if (heap_ == NULL) { | 605 if (heap_ == NULL) { |
| 643 // Some unit tests. | 606 // Some unit tests. |
| 644 return; | 607 return; |
| 645 } | 608 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 658 return; | 621 return; |
| 659 } | 622 } |
| 660 ASSERT(to_ != NULL); | 623 ASSERT(to_ != NULL); |
| 661 ASSERT(heap_ != NULL); | 624 ASSERT(heap_ != NULL); |
| 662 Isolate* isolate = heap_->isolate(); | 625 Isolate* isolate = heap_->isolate(); |
| 663 ASSERT(isolate != NULL); | 626 ASSERT(isolate != NULL); |
| 664 isolate->GetHeapNewUsedMaxMetric()->SetValue(UsedInWords() * kWordSize); | 627 isolate->GetHeapNewUsedMaxMetric()->SetValue(UsedInWords() * kWordSize); |
| 665 } | 628 } |
| 666 | 629 |
| 667 | 630 |
| 631 void Scavenger::EnqueueWeakProperty(RawWeakProperty* raw_weak) { |
| 632 ASSERT(raw_weak->IsHeapObject()); |
| 633 ASSERT(raw_weak->IsNewObject()); |
| 634 ASSERT(raw_weak->IsWeakProperty()); |
| 635 DEBUG_ONLY( |
| 636 uword raw_addr = RawObject::ToAddr(raw_weak); |
| 637 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 638 ASSERT(!IsForwarding(header)); |
| 639 ) |
| 640 ASSERT(raw_weak->ptr()->next_ == 0); |
| 641 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_); |
| 642 delayed_weak_properties_ = raw_weak; |
| 643 } |
| 644 |
| 645 |
| 668 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, | 646 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, |
| 669 ScavengerVisitor* visitor) { | 647 ScavengerVisitor* visitor) { |
| 670 // The fate of the weak property is determined by its key. | 648 // The fate of the weak property is determined by its key. |
| 671 RawObject* raw_key = raw_weak->ptr()->key_; | 649 RawObject* raw_key = raw_weak->ptr()->key_; |
| 672 if (raw_key->IsHeapObject() && raw_key->IsNewObject()) { | 650 if (raw_key->IsHeapObject() && raw_key->IsNewObject()) { |
| 673 uword raw_addr = RawObject::ToAddr(raw_key); | 651 uword raw_addr = RawObject::ToAddr(raw_key); |
| 674 uword header = *reinterpret_cast<uword*>(raw_addr); | 652 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 675 if (!IsForwarding(header)) { | 653 if (!IsForwarding(header)) { |
| 676 // Key is white. Delay the weak property. | 654 // Key is white. Enqueue the weak property. |
| 677 visitor->DelayWeakProperty(raw_weak); | 655 EnqueueWeakProperty(raw_weak); |
| 678 return raw_weak->Size(); | 656 return raw_weak->Size(); |
| 679 } | 657 } |
| 680 } | 658 } |
| 681 // Key is gray or black. Make the weak property black. | 659 // Key is gray or black. Make the weak property black. |
| 682 return raw_weak->VisitPointers(visitor); | 660 return raw_weak->VisitPointers(visitor); |
| 683 } | 661 } |
| 684 | 662 |
| 685 | 663 |
| 686 void Scavenger::ProcessWeakTables() { | 664 void Scavenger::ProcessWeakReferences() { |
| 665 // Rehash the weak tables now that we know which objects survive this cycle. |
| 687 for (int sel = 0; | 666 for (int sel = 0; |
| 688 sel < Heap::kNumWeakSelectors; | 667 sel < Heap::kNumWeakSelectors; |
| 689 sel++) { | 668 sel++) { |
| 690 WeakTable* table = heap_->GetWeakTable( | 669 WeakTable* table = heap_->GetWeakTable( |
| 691 Heap::kNew, static_cast<Heap::WeakSelector>(sel)); | 670 Heap::kNew, static_cast<Heap::WeakSelector>(sel)); |
| 692 heap_->SetWeakTable(Heap::kNew, | 671 heap_->SetWeakTable(Heap::kNew, |
| 693 static_cast<Heap::WeakSelector>(sel), | 672 static_cast<Heap::WeakSelector>(sel), |
| 694 WeakTable::NewFrom(table)); | 673 WeakTable::NewFrom(table)); |
| 695 intptr_t size = table->size(); | 674 intptr_t size = table->size(); |
| 696 for (intptr_t i = 0; i < size; i++) { | 675 for (intptr_t i = 0; i < size; i++) { |
| 697 if (table->IsValidEntryAt(i)) { | 676 if (table->IsValidEntryAt(i)) { |
| 698 RawObject* raw_obj = table->ObjectAt(i); | 677 RawObject* raw_obj = table->ObjectAt(i); |
| 699 ASSERT(raw_obj->IsHeapObject()); | 678 ASSERT(raw_obj->IsHeapObject()); |
| 700 uword raw_addr = RawObject::ToAddr(raw_obj); | 679 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 701 uword header = *reinterpret_cast<uword*>(raw_addr); | 680 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 702 if (IsForwarding(header)) { | 681 if (IsForwarding(header)) { |
| 703 // The object has survived. Preserve its record. | 682 // The object has survived. Preserve its record. |
| 704 uword new_addr = ForwardedAddr(header); | 683 uword new_addr = ForwardedAddr(header); |
| 705 raw_obj = RawObject::FromAddr(new_addr); | 684 raw_obj = RawObject::FromAddr(new_addr); |
| 706 heap_->SetWeakEntry(raw_obj, | 685 heap_->SetWeakEntry(raw_obj, |
| 707 static_cast<Heap::WeakSelector>(sel), | 686 static_cast<Heap::WeakSelector>(sel), |
| 708 table->ValueAt(i)); | 687 table->ValueAt(i)); |
| 709 } | 688 } |
| 710 } | 689 } |
| 711 } | 690 } |
| 712 // Remove the old table as it has been replaced with the newly allocated | 691 // Remove the old table as it has been replaced with the newly allocated |
| 713 // table above. | 692 // table above. |
| 714 delete table; | 693 delete table; |
| 715 } | 694 } |
| 695 |
| 696 // The queued weak properties at this point do not refer to reachable keys, |
| 697 // so we clear their key and value fields. |
| 698 { |
| 699 RawWeakProperty* cur_weak = delayed_weak_properties_; |
| 700 delayed_weak_properties_ = NULL; |
| 701 while (cur_weak != NULL) { |
| 702 uword next_weak = cur_weak->ptr()->next_; |
| 703 // Reset the next pointer in the weak property. |
| 704 cur_weak->ptr()->next_ = 0; |
| 705 |
| 706 DEBUG_ONLY( |
| 707 RawObject* raw_key = cur_weak->ptr()->key_; |
| 708 uword raw_addr = RawObject::ToAddr(raw_key); |
| 709 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 710 ASSERT(!IsForwarding(header)); |
| 711 ASSERT(raw_key->IsHeapObject()); |
| 712 ASSERT(raw_key->IsNewObject()); // Key still points into from space. |
| 713 ) |
| 714 |
| 715 WeakProperty::Clear(cur_weak); |
| 716 |
| 717 // Advance to next weak property in the queue. |
| 718 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
| 719 } |
| 720 } |
| 716 } | 721 } |
| 717 | 722 |
| 718 | 723 |
| 719 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 724 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 720 uword cur = FirstObjectStart(); | 725 uword cur = FirstObjectStart(); |
| 721 while (cur < top_) { | 726 while (cur < top_) { |
| 722 RawObject* raw_obj = RawObject::FromAddr(cur); | 727 RawObject* raw_obj = RawObject::FromAddr(cur); |
| 723 cur += raw_obj->VisitPointers(visitor); | 728 cur += raw_obj->VisitPointers(visitor); |
| 724 } | 729 } |
| 725 } | 730 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 StackZone zone(Thread::Current()); | 799 StackZone zone(Thread::Current()); |
| 795 // Setup the visitor and run the scavenge. | 800 // Setup the visitor and run the scavenge. |
| 796 ScavengerVisitor visitor(isolate, this, from); | 801 ScavengerVisitor visitor(isolate, this, from); |
| 797 page_space->AcquireDataLock(); | 802 page_space->AcquireDataLock(); |
| 798 IterateRoots(isolate, &visitor); | 803 IterateRoots(isolate, &visitor); |
| 799 int64_t start = OS::GetCurrentTimeMicros(); | 804 int64_t start = OS::GetCurrentTimeMicros(); |
| 800 ProcessToSpace(&visitor); | 805 ProcessToSpace(&visitor); |
| 801 int64_t middle = OS::GetCurrentTimeMicros(); | 806 int64_t middle = OS::GetCurrentTimeMicros(); |
| 802 ScavengerWeakVisitor weak_visitor(this); | 807 ScavengerWeakVisitor weak_visitor(this); |
| 803 IterateWeakRoots(isolate, &weak_visitor); | 808 IterateWeakRoots(isolate, &weak_visitor); |
| 804 visitor.Finalize(); | 809 ProcessWeakReferences(); |
| 805 ProcessWeakTables(); | |
| 806 page_space->ReleaseDataLock(); | 810 page_space->ReleaseDataLock(); |
| 807 | 811 |
| 808 // Scavenge finished. Run accounting. | 812 // Scavenge finished. Run accounting. |
| 809 int64_t end = OS::GetCurrentTimeMicros(); | 813 int64_t end = OS::GetCurrentTimeMicros(); |
| 810 heap_->RecordTime(kProcessToSpace, middle - start); | 814 heap_->RecordTime(kProcessToSpace, middle - start); |
| 811 heap_->RecordTime(kIterateWeaks, end - middle); | 815 heap_->RecordTime(kIterateWeaks, end - middle); |
| 812 stats_history_.Add( | 816 stats_history_.Add( |
| 813 ScavengeStats(start, end, | 817 ScavengeStats(start, end, |
| 814 usage_before, GetCurrentUsage(), | 818 usage_before, GetCurrentUsage(), |
| 815 promo_candidate_words, | 819 promo_candidate_words, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 } | 875 } |
| 872 | 876 |
| 873 | 877 |
| 874 void Scavenger::FreeExternal(intptr_t size) { | 878 void Scavenger::FreeExternal(intptr_t size) { |
| 875 ASSERT(size >= 0); | 879 ASSERT(size >= 0); |
| 876 external_size_ -= size; | 880 external_size_ -= size; |
| 877 ASSERT(external_size_ >= 0); | 881 ASSERT(external_size_ >= 0); |
| 878 } | 882 } |
| 879 | 883 |
| 880 } // namespace dart | 884 } // namespace dart |
| OLD | NEW |