| 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> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 class ScavengerVisitor : public ObjectPointerVisitor { | 68 class ScavengerVisitor : public ObjectPointerVisitor { |
| 69 public: | 69 public: |
| 70 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) | 70 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) |
| 71 : ObjectPointerVisitor(isolate), | 71 : ObjectPointerVisitor(isolate), |
| 72 scavenger_(scavenger), | 72 scavenger_(scavenger), |
| 73 heap_(scavenger->heap_), | 73 heap_(scavenger->heap_), |
| 74 vm_heap_(Dart::vm_isolate()->heap()), | 74 vm_heap_(Dart::vm_isolate()->heap()), |
| 75 delayed_weak_stack_(), | 75 delayed_weak_stack_(), |
| 76 growth_policy_(PageSpace::kControlGrowth), | 76 growth_policy_(PageSpace::kControlGrowth), |
| 77 bytes_promoted_(0), | 77 bytes_promoted_(0), |
| 78 #ifdef DEBUG | 78 visiting_old_object_(NULL), |
| 79 in_scavenge_pointer_(false), | 79 in_scavenge_pointer_(false) { } |
| 80 #endif | |
| 81 visiting_old_pointers_(false) { } | |
| 82 | 80 |
| 83 void VisitPointers(RawObject** first, RawObject** last) { | 81 void VisitPointers(RawObject** first, RawObject** last) { |
| 84 for (RawObject** current = first; current <= last; current++) { | 82 for (RawObject** current = first; current <= last; current++) { |
| 85 ScavengePointer(current); | 83 ScavengePointer(current); |
| 86 } | 84 } |
| 87 } | 85 } |
| 88 | 86 |
| 89 GrowableArray<RawObject*>* DelayedWeakStack() { | 87 GrowableArray<RawObject*>* DelayedWeakStack() { |
| 90 return &delayed_weak_stack_; | 88 return &delayed_weak_stack_; |
| 91 } | 89 } |
| 92 | 90 |
| 93 bool* VisitingOldPointersAddr() { return &visiting_old_pointers_; } | 91 void VisitingOldObject(RawObject* obj) { |
| 92 ASSERT((obj == NULL) || obj->IsOldObject()); |
| 93 visiting_old_object_ = obj; |
| 94 } |
| 94 | 95 |
| 95 void DelayWeakProperty(RawWeakProperty* raw_weak) { | 96 void DelayWeakProperty(RawWeakProperty* raw_weak) { |
| 96 RawObject* raw_key = raw_weak->ptr()->key_; | 97 RawObject* raw_key = raw_weak->ptr()->key_; |
| 97 DelaySet::iterator it = delay_set_.find(raw_key); | 98 DelaySet::iterator it = delay_set_.find(raw_key); |
| 98 if (it != delay_set_.end()) { | 99 if (it != delay_set_.end()) { |
| 99 ASSERT(raw_key->IsWatched()); | 100 ASSERT(raw_key->IsWatched()); |
| 100 } else { | 101 } else { |
| 101 ASSERT(!raw_key->IsWatched()); | 102 ASSERT(!raw_key->IsWatched()); |
| 102 raw_key->SetWatchedBit(); | 103 raw_key->SetWatchedBit(); |
| 103 } | 104 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 115 | 116 |
| 116 private: | 117 private: |
| 117 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 118 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
| 118 uword ptr = reinterpret_cast<uword>(p); | 119 uword ptr = reinterpret_cast<uword>(p); |
| 119 ASSERT(obj->IsHeapObject()); | 120 ASSERT(obj->IsHeapObject()); |
| 120 ASSERT(!scavenger_->Contains(ptr)); | 121 ASSERT(!scavenger_->Contains(ptr)); |
| 121 ASSERT(!heap_->CodeContains(ptr)); | 122 ASSERT(!heap_->CodeContains(ptr)); |
| 122 ASSERT(heap_->Contains(ptr)); | 123 ASSERT(heap_->Contains(ptr)); |
| 123 // If the newly written object is not a new object, drop it immediately. | 124 // If the newly written object is not a new object, drop it immediately. |
| 124 if (!obj->IsNewObject()) return; | 125 if (!obj->IsNewObject()) return; |
| 125 isolate()->store_buffer()->AddPointer(ptr); | 126 isolate()->store_buffer()->AddPointer( |
| 127 reinterpret_cast<uword>(visiting_old_object_)); |
| 126 } | 128 } |
| 127 | 129 |
| 128 void ScavengePointer(RawObject** p) { | 130 void ScavengePointer(RawObject** p) { |
| 129 // ScavengePointer cannot be called recursively. | 131 // ScavengePointer cannot be called recursively. |
| 130 #ifdef DEBUG | 132 #ifdef DEBUG |
| 131 ASSERT(!in_scavenge_pointer_); | 133 ASSERT(!in_scavenge_pointer_); |
| 132 BoolScope bs(&in_scavenge_pointer_, true); | 134 BoolScope bs(&in_scavenge_pointer_, true); |
| 133 #endif | 135 #endif |
| 134 | 136 |
| 135 RawObject* raw_obj = *p; | 137 RawObject* raw_obj = *p; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 memmove(reinterpret_cast<void*>(new_addr), | 234 memmove(reinterpret_cast<void*>(new_addr), |
| 233 reinterpret_cast<void*>(raw_addr), | 235 reinterpret_cast<void*>(raw_addr), |
| 234 size); | 236 size); |
| 235 // Remember forwarding address. | 237 // Remember forwarding address. |
| 236 ForwardTo(raw_addr, new_addr); | 238 ForwardTo(raw_addr, new_addr); |
| 237 } | 239 } |
| 238 // Update the reference. | 240 // Update the reference. |
| 239 RawObject* new_obj = RawObject::FromAddr(new_addr); | 241 RawObject* new_obj = RawObject::FromAddr(new_addr); |
| 240 *p = new_obj; | 242 *p = new_obj; |
| 241 // Update the store buffer as needed. | 243 // Update the store buffer as needed. |
| 242 if (visiting_old_pointers_) { | 244 if (visiting_old_object_ != NULL) { |
| 243 UpdateStoreBuffer(p, new_obj); | 245 UpdateStoreBuffer(p, new_obj); |
| 244 } | 246 } |
| 245 } | 247 } |
| 246 | 248 |
| 247 Scavenger* scavenger_; | 249 Scavenger* scavenger_; |
| 248 Heap* heap_; | 250 Heap* heap_; |
| 249 Heap* vm_heap_; | 251 Heap* vm_heap_; |
| 250 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 252 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
| 251 DelaySet delay_set_; | 253 DelaySet delay_set_; |
| 252 GrowableArray<RawObject*> delayed_weak_stack_; | 254 GrowableArray<RawObject*> delayed_weak_stack_; |
| 253 PageSpace::GrowthPolicy growth_policy_; | 255 PageSpace::GrowthPolicy growth_policy_; |
| 254 // TODO(cshapiro): use this value to compute survival statistics for | 256 // TODO(cshapiro): use this value to compute survival statistics for |
| 255 // new space growth policy. | 257 // new space growth policy. |
| 256 intptr_t bytes_promoted_; | 258 intptr_t bytes_promoted_; |
| 257 | 259 RawObject* visiting_old_object_; |
| 258 #ifdef DEBUG | |
| 259 bool in_scavenge_pointer_; | 260 bool in_scavenge_pointer_; |
| 260 #endif | |
| 261 bool visiting_old_pointers_; | |
| 262 | 261 |
| 263 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 262 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
| 264 }; | 263 }; |
| 265 | 264 |
| 266 | 265 |
| 267 class ScavengerWeakVisitor : public HandleVisitor { | 266 class ScavengerWeakVisitor : public HandleVisitor { |
| 268 public: | 267 public: |
| 269 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { | 268 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
| 270 } | 269 } |
| 271 | 270 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 #endif // defined(DEBUG) | 385 #endif // defined(DEBUG) |
| 387 if (invoke_api_callbacks) { | 386 if (invoke_api_callbacks) { |
| 388 isolate->gc_epilogue_callbacks().Invoke(); | 387 isolate->gc_epilogue_callbacks().Invoke(); |
| 389 } | 388 } |
| 390 } | 389 } |
| 391 | 390 |
| 392 | 391 |
| 393 void Scavenger::IterateStoreBuffers(Isolate* isolate, | 392 void Scavenger::IterateStoreBuffers(Isolate* isolate, |
| 394 ScavengerVisitor* visitor) { | 393 ScavengerVisitor* visitor) { |
| 395 // Iterating through the store buffers. | 394 // Iterating through the store buffers. |
| 396 BoolScope bs(visitor->VisitingOldPointersAddr(), true); | |
| 397 // Grab the deduplication sets out of the store buffer. | 395 // Grab the deduplication sets out of the store buffer. |
| 398 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets(); | 396 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets(); |
| 399 intptr_t entries = 0; | 397 intptr_t entries = 0; |
| 400 intptr_t duplicates = 0; | |
| 401 while (pending != NULL) { | 398 while (pending != NULL) { |
| 402 StoreBuffer::DedupSet* next = pending->next(); | 399 StoreBuffer::DedupSet* next = pending->next(); |
| 403 HashSet* set = pending->set(); | 400 HashSet* set = pending->set(); |
| 404 intptr_t count = set->Count(); | 401 intptr_t count = set->Count(); |
| 405 intptr_t size = set->Size(); | 402 intptr_t size = set->Size(); |
| 406 intptr_t handled = 0; | 403 intptr_t handled = 0; |
| 407 entries += count; | 404 entries += count; |
| 408 for (intptr_t i = 0; i < size; i++) { | 405 for (intptr_t i = 0; i < size; i++) { |
| 409 RawObject** pointer = reinterpret_cast<RawObject**>(set->At(i)); | 406 RawObject* raw_object = reinterpret_cast<RawObject*>(set->At(i)); |
| 410 if (pointer != NULL) { | 407 if (raw_object != NULL) { |
| 411 RawObject* value = *pointer; | 408 visitor->VisitingOldObject(raw_object); |
| 412 // Skip entries that have been overwritten with Smis. | 409 raw_object->VisitPointers(visitor); |
| 413 if (value->IsHeapObject()) { | |
| 414 if (from_->Contains(RawObject::ToAddr(value))) { | |
| 415 visitor->VisitPointer(pointer); | |
| 416 } else { | |
| 417 duplicates++; | |
| 418 } | |
| 419 } | |
| 420 handled++; | 410 handled++; |
| 421 if (handled == count) { | 411 if (handled == count) { |
| 422 break; | 412 break; |
| 423 } | 413 } |
| 424 } | 414 } |
| 425 } | 415 } |
| 426 delete pending; | 416 delete pending; |
| 427 pending = next; | 417 pending = next; |
| 428 } | 418 } |
| 429 heap_->RecordData(kStoreBufferEntries, entries); | 419 heap_->RecordData(kStoreBufferEntries, entries); |
| 430 heap_->RecordData(kStoreBufferDuplicates, duplicates); | |
| 431 StoreBufferBlock* block = isolate->store_buffer_block(); | 420 StoreBufferBlock* block = isolate->store_buffer_block(); |
| 432 entries = block->Count(); | 421 entries = block->Count(); |
| 433 duplicates = 0; | |
| 434 for (intptr_t i = 0; i < entries; i++) { | 422 for (intptr_t i = 0; i < entries; i++) { |
| 435 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i)); | 423 RawObject* raw_object = reinterpret_cast<RawObject*>(block->At(i)); |
| 436 RawObject* value = *pointer; | 424 ASSERT(raw_object->IsHeapObject()); |
| 437 if (value->IsHeapObject()) { | 425 visitor->VisitingOldObject(raw_object); |
| 438 if (from_->Contains(RawObject::ToAddr(value))) { | 426 raw_object->VisitPointers(visitor); |
| 439 visitor->VisitPointer(pointer); | |
| 440 } else { | |
| 441 duplicates++; | |
| 442 } | |
| 443 } | |
| 444 } | 427 } |
| 445 block->Reset(); | 428 block->Reset(); |
| 446 heap_->RecordData(kStoreBufferBlockEntries, entries); | 429 heap_->RecordData(kStoreBufferBlockEntries, entries); |
| 447 heap_->RecordData(kStoreBufferBlockDuplicates, duplicates); | 430 // Done iterating through old objects remembered in the store buffers. |
| 431 visitor->VisitingOldObject(NULL); |
| 448 } | 432 } |
| 449 | 433 |
| 450 | 434 |
| 451 void Scavenger::IterateRoots(Isolate* isolate, | 435 void Scavenger::IterateRoots(Isolate* isolate, |
| 452 ScavengerVisitor* visitor, | 436 ScavengerVisitor* visitor, |
| 453 bool visit_prologue_weak_persistent_handles) { | 437 bool visit_prologue_weak_persistent_handles) { |
| 454 int64_t start = OS::GetCurrentTimeMicros(); | 438 int64_t start = OS::GetCurrentTimeMicros(); |
| 455 isolate->VisitObjectPointers(visitor, | 439 isolate->VisitObjectPointers(visitor, |
| 456 visit_prologue_weak_persistent_handles, | 440 visit_prologue_weak_persistent_handles, |
| 457 StackFrameIterator::kDontValidateFrames); | 441 StackFrameIterator::kDontValidateFrames); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 540 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
| 557 intptr_t class_id = raw_obj->GetClassId(); | 541 intptr_t class_id = raw_obj->GetClassId(); |
| 558 if (class_id != kWeakPropertyCid) { | 542 if (class_id != kWeakPropertyCid) { |
| 559 resolved_top_ += raw_obj->VisitPointers(visitor); | 543 resolved_top_ += raw_obj->VisitPointers(visitor); |
| 560 } else { | 544 } else { |
| 561 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | 545 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
| 562 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); | 546 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); |
| 563 } | 547 } |
| 564 } | 548 } |
| 565 { | 549 { |
| 566 BoolScope bs(visitor->VisitingOldPointersAddr(), true); | |
| 567 while (PromotedStackHasMore()) { | 550 while (PromotedStackHasMore()) { |
| 568 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 551 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
| 569 // Resolve or copy all objects referred to by the current object. This | 552 // Resolve or copy all objects referred to by the current object. This |
| 570 // can potentially push more objects on this stack as well as add more | 553 // can potentially push more objects on this stack as well as add more |
| 571 // objects to be resolved in the to space. | 554 // objects to be resolved in the to space. |
| 555 visitor->VisitingOldObject(raw_object); |
| 572 raw_object->VisitPointers(visitor); | 556 raw_object->VisitPointers(visitor); |
| 573 } | 557 } |
| 558 visitor->VisitingOldObject(NULL); |
| 574 } | 559 } |
| 575 while (!delayed_weak_stack->is_empty()) { | 560 while (!delayed_weak_stack->is_empty()) { |
| 576 // Pop the delayed weak object from the stack and visit its pointers. | 561 // Pop the delayed weak object from the stack and visit its pointers. |
| 577 RawObject* weak_property = delayed_weak_stack->RemoveLast(); | 562 RawObject* weak_property = delayed_weak_stack->RemoveLast(); |
| 578 weak_property->VisitPointers(visitor); | 563 weak_property->VisitPointers(visitor); |
| 579 } | 564 } |
| 580 } | 565 } |
| 581 } | 566 } |
| 582 | 567 |
| 583 | 568 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 PeerTable::iterator it = peer_table_.find(raw_obj); | 697 PeerTable::iterator it = peer_table_.find(raw_obj); |
| 713 return (it == peer_table_.end()) ? NULL : it->second; | 698 return (it == peer_table_.end()) ? NULL : it->second; |
| 714 } | 699 } |
| 715 | 700 |
| 716 | 701 |
| 717 int64_t Scavenger::PeerCount() const { | 702 int64_t Scavenger::PeerCount() const { |
| 718 return static_cast<int64_t>(peer_table_.size()); | 703 return static_cast<int64_t>(peer_table_.size()); |
| 719 } | 704 } |
| 720 | 705 |
| 721 } // namespace dart | 706 } // namespace dart |
| OLD | NEW |