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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 }; | 66 }; |
67 | 67 |
68 | 68 |
69 class ScavengerVisitor : public ObjectPointerVisitor { | 69 class ScavengerVisitor : public ObjectPointerVisitor { |
70 public: | 70 public: |
71 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) | 71 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) |
72 : ObjectPointerVisitor(isolate), | 72 : ObjectPointerVisitor(isolate), |
73 scavenger_(scavenger), | 73 scavenger_(scavenger), |
74 heap_(scavenger->heap_), | 74 heap_(scavenger->heap_), |
75 vm_heap_(Dart::vm_isolate()->heap()), | 75 vm_heap_(Dart::vm_isolate()->heap()), |
| 76 visited_count_(0), |
| 77 handled_count_(0), |
76 delayed_weak_stack_(), | 78 delayed_weak_stack_(), |
77 growth_policy_(PageSpace::kControlGrowth), | 79 growth_policy_(PageSpace::kControlGrowth), |
78 bytes_promoted_(0), | 80 bytes_promoted_(0), |
79 visiting_old_object_(NULL), | 81 visiting_old_object_(NULL), |
80 in_scavenge_pointer_(false) { } | 82 in_scavenge_pointer_(false) { } |
81 | 83 |
82 void VisitPointers(RawObject** first, RawObject** last) { | 84 void VisitPointers(RawObject** first, RawObject** last) { |
83 for (RawObject** current = first; current <= last; current++) { | 85 for (RawObject** current = first; current <= last; current++) { |
84 ScavengePointer(current); | 86 ScavengePointer(current); |
85 } | 87 } |
(...skipping 20 matching lines...) Expand all Loading... |
106 delay_set_.insert(std::make_pair(raw_key, raw_weak)); | 108 delay_set_.insert(std::make_pair(raw_key, raw_weak)); |
107 } | 109 } |
108 | 110 |
109 void Finalize() { | 111 void Finalize() { |
110 DelaySet::iterator it = delay_set_.begin(); | 112 DelaySet::iterator it = delay_set_.begin(); |
111 for (; it != delay_set_.end(); ++it) { | 113 for (; it != delay_set_.end(); ++it) { |
112 WeakProperty::Clear(it->second); | 114 WeakProperty::Clear(it->second); |
113 } | 115 } |
114 } | 116 } |
115 | 117 |
| 118 intptr_t visited_count() const { return visited_count_; } |
| 119 intptr_t handled_count() const { return handled_count_; } |
116 intptr_t bytes_promoted() const { return bytes_promoted_; } | 120 intptr_t bytes_promoted() const { return bytes_promoted_; } |
117 | 121 |
118 private: | 122 private: |
119 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 123 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
120 uword ptr = reinterpret_cast<uword>(p); | 124 uword ptr = reinterpret_cast<uword>(p); |
121 ASSERT(obj->IsHeapObject()); | 125 ASSERT(obj->IsHeapObject()); |
122 ASSERT(!scavenger_->Contains(ptr)); | 126 ASSERT(!scavenger_->Contains(ptr)); |
123 ASSERT(!heap_->CodeContains(ptr)); | 127 ASSERT(!heap_->CodeContains(ptr)); |
124 ASSERT(heap_->Contains(ptr)); | 128 ASSERT(heap_->Contains(ptr)); |
125 // If the newly written object is not a new object, drop it immediately. | 129 // If the newly written object is not a new object, drop it immediately. |
126 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { | 130 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { |
127 return; | 131 return; |
128 } | 132 } |
129 visiting_old_object_->SetRememberedBit(); | 133 visiting_old_object_->SetRememberedBit(); |
130 isolate()->store_buffer()->AddObjectGC(visiting_old_object_); | 134 isolate()->store_buffer()->AddObjectGC(visiting_old_object_); |
131 } | 135 } |
132 | 136 |
133 void ScavengePointer(RawObject** p) { | 137 void ScavengePointer(RawObject** p) { |
134 // ScavengePointer cannot be called recursively. | 138 // ScavengePointer cannot be called recursively. |
135 #ifdef DEBUG | 139 #ifdef DEBUG |
136 ASSERT(!in_scavenge_pointer_); | 140 ASSERT(!in_scavenge_pointer_); |
137 BoolScope bs(&in_scavenge_pointer_, true); | 141 BoolScope bs(&in_scavenge_pointer_, true); |
138 #endif | 142 #endif |
139 | 143 |
| 144 visited_count_++; |
140 RawObject* raw_obj = *p; | 145 RawObject* raw_obj = *p; |
141 | 146 |
142 // Fast exit if the raw object is a Smi or an old object. | 147 // Fast exit if the raw object is a Smi or an old object. |
143 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { | 148 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { |
144 return; | 149 return; |
145 } | 150 } |
146 | 151 |
147 uword raw_addr = RawObject::ToAddr(raw_obj); | 152 uword raw_addr = RawObject::ToAddr(raw_obj); |
148 // Objects should be contained in the heap. | 153 // Objects should be contained in the heap. |
149 // TODO(iposva): Add an appropriate assert here or in the return block | 154 // TODO(iposva): Add an appropriate assert here or in the return block |
150 // below. | 155 // below. |
151 // The scavenger is only interested in objects located in the from space. | 156 // The scavenger is only interested in objects located in the from space. |
152 if (!scavenger_->from_->Contains(raw_addr)) { | 157 if (!scavenger_->from_->Contains(raw_addr)) { |
153 return; | 158 return; |
154 } | 159 } |
155 | 160 |
| 161 handled_count_++; |
156 // Read the header word of the object and determine if the object has | 162 // Read the header word of the object and determine if the object has |
157 // already been copied. | 163 // already been copied. |
158 uword header = *reinterpret_cast<uword*>(raw_addr); | 164 uword header = *reinterpret_cast<uword*>(raw_addr); |
159 uword new_addr = 0; | 165 uword new_addr = 0; |
160 if (IsForwarding(header)) { | 166 if (IsForwarding(header)) { |
161 // Get the new location of the object. | 167 // Get the new location of the object. |
162 new_addr = ForwardedAddr(header); | 168 new_addr = ForwardedAddr(header); |
163 } else { | 169 } else { |
164 if (raw_obj->IsWatched()) { | 170 if (raw_obj->IsWatched()) { |
165 raw_obj->ClearWatchedBit(); | 171 raw_obj->ClearWatchedBit(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 *p = new_obj; | 236 *p = new_obj; |
231 // Update the store buffer as needed. | 237 // Update the store buffer as needed. |
232 if (visiting_old_object_ != NULL) { | 238 if (visiting_old_object_ != NULL) { |
233 UpdateStoreBuffer(p, new_obj); | 239 UpdateStoreBuffer(p, new_obj); |
234 } | 240 } |
235 } | 241 } |
236 | 242 |
237 Scavenger* scavenger_; | 243 Scavenger* scavenger_; |
238 Heap* heap_; | 244 Heap* heap_; |
239 Heap* vm_heap_; | 245 Heap* vm_heap_; |
| 246 intptr_t visited_count_; |
| 247 intptr_t handled_count_; |
240 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 248 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
241 DelaySet delay_set_; | 249 DelaySet delay_set_; |
242 GrowableArray<RawObject*> delayed_weak_stack_; | 250 GrowableArray<RawObject*> delayed_weak_stack_; |
243 PageSpace::GrowthPolicy growth_policy_; | 251 PageSpace::GrowthPolicy growth_policy_; |
244 // TODO(cshapiro): use this value to compute survival statistics for | 252 // TODO(cshapiro): use this value to compute survival statistics for |
245 // new space growth policy. | 253 // new space growth policy. |
246 intptr_t bytes_promoted_; | 254 intptr_t bytes_promoted_; |
247 RawObject* visiting_old_object_; | 255 RawObject* visiting_old_object_; |
248 bool in_scavenge_pointer_; | 256 bool in_scavenge_pointer_; |
249 | 257 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 #endif // defined(DEBUG) | 380 #endif // defined(DEBUG) |
373 if (invoke_api_callbacks) { | 381 if (invoke_api_callbacks) { |
374 isolate->gc_epilogue_callbacks().Invoke(); | 382 isolate->gc_epilogue_callbacks().Invoke(); |
375 } | 383 } |
376 } | 384 } |
377 | 385 |
378 | 386 |
379 void Scavenger::IterateStoreBuffers(Isolate* isolate, | 387 void Scavenger::IterateStoreBuffers(Isolate* isolate, |
380 ScavengerVisitor* visitor) { | 388 ScavengerVisitor* visitor) { |
381 StoreBuffer* buffer = isolate->store_buffer(); | 389 StoreBuffer* buffer = isolate->store_buffer(); |
382 heap_->RecordData(kStoreBufferBlockEntries, buffer->Count()); | 390 heap_->RecordData(kStoreBufferEntries, buffer->Count()); |
383 | 391 |
384 // Iterating through the store buffers. | 392 // Iterating through the store buffers. |
385 // Grab the deduplication sets out of the store buffer. | 393 // Grab the deduplication sets out of the store buffer. |
386 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); | 394 StoreBufferBlock* pending = isolate->store_buffer()->Blocks(); |
387 intptr_t entries = 0; | 395 intptr_t visited_count_before = visitor->visited_count(); |
| 396 intptr_t handled_count_before = visitor->handled_count(); |
388 while (pending != NULL) { | 397 while (pending != NULL) { |
389 StoreBufferBlock* next = pending->next(); | 398 StoreBufferBlock* next = pending->next(); |
390 intptr_t count = pending->Count(); | 399 intptr_t count = pending->Count(); |
391 entries += count; | |
392 for (intptr_t i = 0; i < count; i++) { | 400 for (intptr_t i = 0; i < count; i++) { |
393 RawObject* raw_object = pending->At(i); | 401 RawObject* raw_object = pending->At(i); |
394 ASSERT(raw_object->IsRemembered()); | 402 ASSERT(raw_object->IsRemembered()); |
395 raw_object->ClearRememberedBit(); | 403 raw_object->ClearRememberedBit(); |
396 visitor->VisitingOldObject(raw_object); | 404 visitor->VisitingOldObject(raw_object); |
397 raw_object->VisitPointers(visitor); | 405 raw_object->VisitPointers(visitor); |
398 } | 406 } |
399 delete pending; | 407 delete pending; |
400 pending = next; | 408 pending = next; |
401 } | 409 } |
402 heap_->RecordData(kStoreBufferEntries, entries); | 410 heap_->RecordData(kStoreBufferVisited, |
| 411 visitor->visited_count() - visited_count_before); |
| 412 heap_->RecordData(kStoreBufferPointers, |
| 413 visitor->handled_count() - handled_count_before); |
403 // Done iterating through old objects remembered in the store buffers. | 414 // Done iterating through old objects remembered in the store buffers. |
404 visitor->VisitingOldObject(NULL); | 415 visitor->VisitingOldObject(NULL); |
405 } | 416 } |
406 | 417 |
407 | 418 |
408 void Scavenger::IterateObjectIdTable(Isolate* isolate, | 419 void Scavenger::IterateObjectIdTable(Isolate* isolate, |
409 ScavengerVisitor* visitor) { | 420 ScavengerVisitor* visitor) { |
410 ObjectIdRing* ring = isolate->object_id_ring(); | 421 ObjectIdRing* ring = isolate->object_id_ring(); |
411 if (ring == NULL) { | 422 if (ring == NULL) { |
412 // --gc_at_alloc can get us here before the ring has been initialized. | 423 // --gc_at_alloc can get us here before the ring has been initialized. |
413 ASSERT(FLAG_gc_at_alloc); | 424 ASSERT(FLAG_gc_at_alloc); |
414 return; | 425 return; |
415 } | 426 } |
416 ring->VisitPointers(visitor); | 427 ring->VisitPointers(visitor); |
417 } | 428 } |
418 | 429 |
419 | 430 |
420 void Scavenger::IterateRoots(Isolate* isolate, | 431 void Scavenger::IterateRoots(Isolate* isolate, |
421 ScavengerVisitor* visitor, | 432 ScavengerVisitor* visitor, |
422 bool visit_prologue_weak_persistent_handles) { | 433 bool visit_prologue_weak_persistent_handles) { |
423 int64_t start = OS::GetCurrentTimeMicros(); | 434 int64_t start = OS::GetCurrentTimeMicros(); |
424 isolate->VisitObjectPointers(visitor, | 435 isolate->VisitObjectPointers(visitor, |
425 visit_prologue_weak_persistent_handles, | 436 visit_prologue_weak_persistent_handles, |
426 StackFrameIterator::kDontValidateFrames); | 437 StackFrameIterator::kDontValidateFrames); |
427 int64_t middle = OS::GetCurrentTimeMicros(); | 438 int64_t middle = OS::GetCurrentTimeMicros(); |
428 IterateStoreBuffers(isolate, visitor); | 439 IterateStoreBuffers(isolate, visitor); |
429 IterateObjectIdTable(isolate, visitor); | 440 IterateObjectIdTable(isolate, visitor); |
430 int64_t end = OS::GetCurrentTimeMicros(); | 441 int64_t end = OS::GetCurrentTimeMicros(); |
| 442 heap_->RecordData(kToKBAfterStoreBuffer, (in_use() + (KB >> 1)) >> KBLog2); |
431 heap_->RecordTime(kVisitIsolateRoots, middle - start); | 443 heap_->RecordTime(kVisitIsolateRoots, middle - start); |
432 heap_->RecordTime(kIterateStoreBuffers, end - middle); | 444 heap_->RecordTime(kIterateStoreBuffers, end - middle); |
433 } | 445 } |
434 | 446 |
435 | 447 |
436 bool Scavenger::IsUnreachable(RawObject** p) { | 448 bool Scavenger::IsUnreachable(RawObject** p) { |
437 RawObject* raw_obj = *p; | 449 RawObject* raw_obj = *p; |
438 if (!raw_obj->IsHeapObject()) { | 450 if (!raw_obj->IsHeapObject()) { |
439 return false; | 451 return false; |
440 } | 452 } |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 } | 685 } |
674 | 686 |
675 | 687 |
676 void Scavenger::WriteProtect(bool read_only) { | 688 void Scavenger::WriteProtect(bool read_only) { |
677 space_->Protect( | 689 space_->Protect( |
678 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); | 690 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); |
679 } | 691 } |
680 | 692 |
681 | 693 |
682 } // namespace dart | 694 } // namespace dart |
OLD | NEW |