| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 private: | 73 private: |
| 74 bool* _addr; | 74 bool* _addr; |
| 75 bool _value; | 75 bool _value; |
| 76 }; | 76 }; |
| 77 | 77 |
| 78 | 78 |
| 79 class ScavengerVisitor : public ObjectPointerVisitor { | 79 class ScavengerVisitor : public ObjectPointerVisitor { |
| 80 public: | 80 public: |
| 81 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) | 81 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) |
| 82 : ObjectPointerVisitor(isolate), | 82 : ObjectPointerVisitor(isolate), |
| 83 thread_(Thread::Current()), |
| 83 scavenger_(scavenger), | 84 scavenger_(scavenger), |
| 84 from_start_(scavenger_->from_->start()), | 85 from_start_(scavenger_->from_->start()), |
| 85 from_size_(scavenger_->from_->end() - scavenger_->from_->start()), | 86 from_size_(scavenger_->from_->end() - scavenger_->from_->start()), |
| 86 heap_(scavenger->heap_), | 87 heap_(scavenger->heap_), |
| 87 vm_heap_(Dart::vm_isolate()->heap()), | 88 vm_heap_(Dart::vm_isolate()->heap()), |
| 88 page_space_(scavenger->heap_->old_space()), | 89 page_space_(scavenger->heap_->old_space()), |
| 89 delayed_weak_stack_(), | 90 delayed_weak_stack_(), |
| 90 bytes_promoted_(0), | 91 bytes_promoted_(0), |
| 91 visiting_old_object_(NULL), | 92 visiting_old_object_(NULL), |
| 92 in_scavenge_pointer_(false) { } | 93 in_scavenge_pointer_(false) { } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 uword ptr = reinterpret_cast<uword>(p); | 133 uword ptr = reinterpret_cast<uword>(p); |
| 133 ASSERT(obj->IsHeapObject()); | 134 ASSERT(obj->IsHeapObject()); |
| 134 ASSERT(!scavenger_->Contains(ptr)); | 135 ASSERT(!scavenger_->Contains(ptr)); |
| 135 ASSERT(!heap_->CodeContains(ptr)); | 136 ASSERT(!heap_->CodeContains(ptr)); |
| 136 ASSERT(heap_->Contains(ptr)); | 137 ASSERT(heap_->Contains(ptr)); |
| 137 // If the newly written object is not a new object, drop it immediately. | 138 // If the newly written object is not a new object, drop it immediately. |
| 138 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { | 139 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { |
| 139 return; | 140 return; |
| 140 } | 141 } |
| 141 visiting_old_object_->SetRememberedBit(); | 142 visiting_old_object_->SetRememberedBit(); |
| 142 isolate()->store_buffer()->AddObjectGC(visiting_old_object_); | 143 thread_->StoreBufferAddObjectGC(visiting_old_object_); |
| 143 } | 144 } |
| 144 | 145 |
| 145 void ScavengePointer(RawObject** p) { | 146 void ScavengePointer(RawObject** p) { |
| 146 // ScavengePointer cannot be called recursively. | 147 // ScavengePointer cannot be called recursively. |
| 147 #ifdef DEBUG | 148 #ifdef DEBUG |
| 148 ASSERT(!in_scavenge_pointer_); | 149 ASSERT(!in_scavenge_pointer_); |
| 149 BoolScope bs(&in_scavenge_pointer_, true); | 150 BoolScope bs(&in_scavenge_pointer_, true); |
| 150 #endif | 151 #endif |
| 151 | 152 |
| 152 RawObject* raw_obj = *p; | 153 RawObject* raw_obj = *p; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 // Update the reference. | 233 // Update the reference. |
| 233 RawObject* new_obj = RawObject::FromAddr(new_addr); | 234 RawObject* new_obj = RawObject::FromAddr(new_addr); |
| 234 *p = new_obj; | 235 *p = new_obj; |
| 235 // Update the store buffer as needed. | 236 // Update the store buffer as needed. |
| 236 if (visiting_old_object_ != NULL) { | 237 if (visiting_old_object_ != NULL) { |
| 237 VerifiedMemory::Accept(reinterpret_cast<uword>(p), sizeof(*p)); | 238 VerifiedMemory::Accept(reinterpret_cast<uword>(p), sizeof(*p)); |
| 238 UpdateStoreBuffer(p, new_obj); | 239 UpdateStoreBuffer(p, new_obj); |
| 239 } | 240 } |
| 240 } | 241 } |
| 241 | 242 |
| 243 Thread* thread_; |
| 242 Scavenger* scavenger_; | 244 Scavenger* scavenger_; |
| 243 uword from_start_; | 245 uword from_start_; |
| 244 uword from_size_; | 246 uword from_size_; |
| 245 Heap* heap_; | 247 Heap* heap_; |
| 246 Heap* vm_heap_; | 248 Heap* vm_heap_; |
| 247 PageSpace* page_space_; | 249 PageSpace* page_space_; |
| 248 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 250 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
| 249 DelaySet delay_set_; | 251 DelaySet delay_set_; |
| 250 GrowableArray<RawObject*> delayed_weak_stack_; | 252 GrowableArray<RawObject*> delayed_weak_stack_; |
| 251 // TODO(cshapiro): use this value to compute survival statistics for | 253 // TODO(cshapiro): use this value to compute survival statistics for |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 } else { | 451 } else { |
| 450 return old_size_in_words; | 452 return old_size_in_words; |
| 451 } | 453 } |
| 452 } | 454 } |
| 453 | 455 |
| 454 | 456 |
| 455 void Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { | 457 void Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { |
| 456 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { | 458 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { |
| 457 (isolate->gc_prologue_callback())(); | 459 (isolate->gc_prologue_callback())(); |
| 458 } | 460 } |
| 461 Thread::PrepareForGC(); |
| 459 // Flip the two semi-spaces so that to_ is always the space for allocating | 462 // Flip the two semi-spaces so that to_ is always the space for allocating |
| 460 // objects. | 463 // objects. |
| 461 from_ = to_; | 464 from_ = to_; |
| 462 to_ = SemiSpace::New(NewSizeInWords(from_->size_in_words())); | 465 to_ = SemiSpace::New(NewSizeInWords(from_->size_in_words())); |
| 463 if (to_ == NULL) { | 466 if (to_ == NULL) { |
| 464 // TODO(koda): We could try to recover (collect old space, wait for another | 467 // TODO(koda): We could try to recover (collect old space, wait for another |
| 465 // isolate to finish scavenge, etc.). | 468 // isolate to finish scavenge, etc.). |
| 466 FATAL("Out of memory.\n"); | 469 FATAL("Out of memory.\n"); |
| 467 } | 470 } |
| 468 top_ = FirstObjectStart(); | 471 top_ = FirstObjectStart(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 from_->Delete(); | 509 from_->Delete(); |
| 507 from_ = NULL; | 510 from_ = NULL; |
| 508 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { | 511 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { |
| 509 (isolate->gc_epilogue_callback())(); | 512 (isolate->gc_epilogue_callback())(); |
| 510 } | 513 } |
| 511 } | 514 } |
| 512 | 515 |
| 513 | 516 |
| 514 void Scavenger::IterateStoreBuffers(Isolate* isolate, | 517 void Scavenger::IterateStoreBuffers(Isolate* isolate, |
| 515 ScavengerVisitor* visitor) { | 518 ScavengerVisitor* visitor) { |
| 516 StoreBuffer* buffer = isolate->store_buffer(); | |
| 517 heap_->RecordData(kStoreBufferEntries, buffer->Count()); | |
| 518 | |
| 519 // Iterating through the store buffers. | 519 // Iterating through the store buffers. |
| 520 // Grab the deduplication sets out of the store buffer. | 520 // Grab the deduplication sets out of the isolate's consolidated store buffer. |
| 521 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); | 521 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); |
| 522 intptr_t total_count = 0; |
| 522 while (pending != NULL) { | 523 while (pending != NULL) { |
| 523 StoreBufferBlock* next = pending->next(); | 524 StoreBufferBlock* next = pending->next(); |
| 524 // Generated code appends to store buffers; tell MemorySanitizer. | 525 // Generated code appends to store buffers; tell MemorySanitizer. |
| 525 MSAN_UNPOISON(pending, sizeof(*pending)); | 526 MSAN_UNPOISON(pending, sizeof(*pending)); |
| 526 intptr_t count = pending->Count(); | 527 intptr_t count = pending->Count(); |
| 528 total_count += count; |
| 527 for (intptr_t i = 0; i < count; i++) { | 529 for (intptr_t i = 0; i < count; i++) { |
| 528 RawObject* raw_object = pending->At(i); | 530 RawObject* raw_object = pending->At(i); |
| 529 ASSERT(raw_object->IsRemembered()); | 531 ASSERT(raw_object->IsRemembered()); |
| 530 raw_object->ClearRememberedBit(); | 532 raw_object->ClearRememberedBit(); |
| 531 visitor->VisitingOldObject(raw_object); | 533 visitor->VisitingOldObject(raw_object); |
| 532 raw_object->VisitPointers(visitor); | 534 raw_object->VisitPointers(visitor); |
| 533 } | 535 } |
| 534 delete pending; | 536 delete pending; |
| 535 pending = next; | 537 pending = next; |
| 536 } | 538 } |
| 539 heap_->RecordData(kStoreBufferEntries, total_count); |
| 537 heap_->RecordData(kDataUnused1, 0); | 540 heap_->RecordData(kDataUnused1, 0); |
| 538 heap_->RecordData(kDataUnused2, 0); | 541 heap_->RecordData(kDataUnused2, 0); |
| 539 // Done iterating through old objects remembered in the store buffers. | 542 // Done iterating through old objects remembered in the store buffers. |
| 540 visitor->VisitingOldObject(NULL); | 543 visitor->VisitingOldObject(NULL); |
| 541 } | 544 } |
| 542 | 545 |
| 543 | 546 |
| 544 void Scavenger::IterateObjectIdTable(Isolate* isolate, | 547 void Scavenger::IterateObjectIdTable(Isolate* isolate, |
| 545 ScavengerVisitor* visitor) { | 548 ScavengerVisitor* visitor) { |
| 546 ObjectIdRing* ring = isolate->object_id_ring(); | 549 ObjectIdRing* ring = isolate->object_id_ring(); |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 } | 902 } |
| 900 | 903 |
| 901 | 904 |
| 902 void Scavenger::FreeExternal(intptr_t size) { | 905 void Scavenger::FreeExternal(intptr_t size) { |
| 903 ASSERT(size >= 0); | 906 ASSERT(size >= 0); |
| 904 external_size_ -= size; | 907 external_size_ -= size; |
| 905 ASSERT(external_size_ >= 0); | 908 ASSERT(external_size_ >= 0); |
| 906 } | 909 } |
| 907 | 910 |
| 908 } // namespace dart | 911 } // namespace dart |
| OLD | NEW |