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