Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(603)

Side by Side Diff: runtime/vm/scavenger.cc

Issue 11734028: - Consolidate verbose-gc output to be a single line which can be imported easily into spreadsheets. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/vm/heap.h ('K') | « runtime/vm/scavenger.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
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),
78 visiting_old_pointers_(false), 77 visiting_old_pointers_(false),
79 in_scavenge_pointer_(false) {} 78 in_scavenge_pointer_(false) {}
80 79
81 void VisitPointers(RawObject** first, RawObject** last) { 80 void VisitPointers(RawObject** first, RawObject** last) {
82 for (RawObject** current = first; current <= last; current++) { 81 for (RawObject** current = first; current <= last; current++) {
83 ScavengePointer(current); 82 ScavengePointer(current);
84 } 83 }
85 } 84 }
86 85
87 GrowableArray<RawObject*>* DelayedWeakStack() { 86 GrowableArray<RawObject*>* DelayedWeakStack() {
(...skipping 14 matching lines...) Expand all
102 delay_set_.insert(std::make_pair(raw_key, raw_weak)); 101 delay_set_.insert(std::make_pair(raw_key, raw_weak));
103 } 102 }
104 103
105 void Finalize() { 104 void Finalize() {
106 DelaySet::iterator it = delay_set_.begin(); 105 DelaySet::iterator it = delay_set_.begin();
107 for (; it != delay_set_.end(); ++it) { 106 for (; it != delay_set_.end(); ++it) {
108 WeakProperty::Clear(it->second); 107 WeakProperty::Clear(it->second);
109 } 108 }
110 } 109 }
111 110
112 intptr_t bytes_promoted() { return bytes_promoted_; }
113
114 private: 111 private:
115 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { 112 void UpdateStoreBuffer(RawObject** p, RawObject* obj) {
116 uword ptr = reinterpret_cast<uword>(p); 113 uword ptr = reinterpret_cast<uword>(p);
117 ASSERT(obj->IsHeapObject()); 114 ASSERT(obj->IsHeapObject());
118 ASSERT(!scavenger_->Contains(ptr)); 115 ASSERT(!scavenger_->Contains(ptr));
119 ASSERT(!heap_->CodeContains(ptr)); 116 ASSERT(!heap_->CodeContains(ptr));
120 ASSERT(heap_->Contains(ptr)); 117 ASSERT(heap_->Contains(ptr));
121 // If the newly written object is not a new object, drop it immediately. 118 // If the newly written object is not a new object, drop it immediately.
122 if (!obj->IsNewObject()) return; 119 if (!obj->IsNewObject()) return;
123 isolate()->store_buffer()->AddPointer(ptr); 120 isolate()->store_buffer()->AddPointer(ptr);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 // a coin toss determines if an object is promoted or whether it should 177 // a coin toss determines if an object is promoted or whether it should
181 // survive in this generation. 178 // survive in this generation.
182 // 179 //
183 // This object is a survivor of a previous scavenge. Attempt to promote 180 // This object is a survivor of a previous scavenge. Attempt to promote
184 // the object. 181 // the object.
185 new_addr = heap_->TryAllocate(size, Heap::kOld, growth_policy_); 182 new_addr = heap_->TryAllocate(size, Heap::kOld, growth_policy_);
186 if (new_addr != 0) { 183 if (new_addr != 0) {
187 // If promotion succeeded then we need to remember it so that it can 184 // If promotion succeeded then we need to remember it so that it can
188 // be traversed later. 185 // be traversed later.
189 scavenger_->PushToPromotedStack(new_addr); 186 scavenger_->PushToPromotedStack(new_addr);
190 bytes_promoted_ += size;
191 if (HeapTrace::is_enabled()) { 187 if (HeapTrace::is_enabled()) {
192 heap_->trace()->TracePromotion(raw_addr, new_addr); 188 heap_->trace()->TracePromotion(raw_addr, new_addr);
193 } 189 }
194 } else if (!scavenger_->had_promotion_failure_) { 190 } else if (!scavenger_->had_promotion_failure_) {
195 // Signal a promotion failure and set the growth policy for 191 // Signal a promotion failure and set the growth policy for
196 // this, and all subsequent promotion allocations, to force 192 // this, and all subsequent promotion allocations, to force
197 // growth. 193 // growth.
198 scavenger_->had_promotion_failure_ = true; 194 scavenger_->had_promotion_failure_ = true;
199 growth_policy_ = PageSpace::kForceGrowth; 195 growth_policy_ = PageSpace::kForceGrowth;
200 new_addr = heap_->TryAllocate(size, Heap::kOld, growth_policy_); 196 new_addr = heap_->TryAllocate(size, Heap::kOld, growth_policy_);
201 if (new_addr != 0) { 197 if (new_addr != 0) {
202 scavenger_->PushToPromotedStack(new_addr); 198 scavenger_->PushToPromotedStack(new_addr);
203 bytes_promoted_ += size;
204 if (HeapTrace::is_enabled()) { 199 if (HeapTrace::is_enabled()) {
205 heap_->trace()->TracePromotion(raw_addr, new_addr); 200 heap_->trace()->TracePromotion(raw_addr, new_addr);
206 } 201 }
207 } else { 202 } else {
208 // Promotion did not succeed. Copy into the to space 203 // Promotion did not succeed. Copy into the to space
209 // instead. 204 // instead.
210 new_addr = scavenger_->TryAllocate(size); 205 new_addr = scavenger_->TryAllocate(size);
211 if (HeapTrace::is_enabled()) { 206 if (HeapTrace::is_enabled()) {
212 heap_->trace()->TraceCopy(raw_addr, new_addr); 207 heap_->trace()->TraceCopy(raw_addr, new_addr);
213 } 208 }
(...skipping 26 matching lines...) Expand all
240 } 235 }
241 } 236 }
242 237
243 Scavenger* scavenger_; 238 Scavenger* scavenger_;
244 Heap* heap_; 239 Heap* heap_;
245 Heap* vm_heap_; 240 Heap* vm_heap_;
246 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; 241 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet;
247 DelaySet delay_set_; 242 DelaySet delay_set_;
248 GrowableArray<RawObject*> delayed_weak_stack_; 243 GrowableArray<RawObject*> delayed_weak_stack_;
249 PageSpace::GrowthPolicy growth_policy_; 244 PageSpace::GrowthPolicy growth_policy_;
250 intptr_t bytes_promoted_;
251 245
252 bool visiting_old_pointers_; 246 bool visiting_old_pointers_;
253 bool in_scavenge_pointer_; 247 bool in_scavenge_pointer_;
254 248
255 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); 249 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor);
256 }; 250 };
257 251
258 252
259 class ScavengerWeakVisitor : public HandleVisitor { 253 class ScavengerWeakVisitor : public HandleVisitor {
260 public: 254 public:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 private: 290 private:
297 MemoryRegion* to_; 291 MemoryRegion* to_;
298 292
299 DISALLOW_COPY_AND_ASSIGN(VerifyStoreBufferPointerVisitor); 293 DISALLOW_COPY_AND_ASSIGN(VerifyStoreBufferPointerVisitor);
300 }; 294 };
301 295
302 296
303 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) 297 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment)
304 : heap_(heap), 298 : heap_(heap),
305 object_alignment_(object_alignment), 299 object_alignment_(object_alignment),
306 count_(0),
307 scavenging_(false) { 300 scavenging_(false) {
308 // Verify assumptions about the first word in objects which the scavenger is 301 // Verify assumptions about the first word in objects which the scavenger is
309 // going to use for forwarding pointers. 302 // going to use for forwarding pointers.
310 ASSERT(Object::tags_offset() == 0); 303 ASSERT(Object::tags_offset() == 0);
311 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit)); 304 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit));
312 305
313 // Allocate the virtual memory for this scavenge heap. 306 // Allocate the virtual memory for this scavenge heap.
314 space_ = VirtualMemory::Reserve(max_capacity); 307 space_ = VirtualMemory::Reserve(max_capacity);
315 ASSERT(space_ != NULL); 308 ASSERT(space_ != NULL);
316 309
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 } 403 }
411 handled++; 404 handled++;
412 if (handled == count) { 405 if (handled == count) {
413 break; 406 break;
414 } 407 }
415 } 408 }
416 } 409 }
417 delete pending; 410 delete pending;
418 pending = next; 411 pending = next;
419 } 412 }
420 if (FLAG_verbose_gc) { 413 heap_->RecordData(0, entries);
421 OS::PrintErr("StoreBuffer: %"Pd", %"Pd" (entries, dups)\n", 414 heap_->RecordData(1, duplicates);
422 entries, duplicates);
423 }
424 StoreBufferBlock* block = isolate->store_buffer_block(); 415 StoreBufferBlock* block = isolate->store_buffer_block();
425 entries = block->Count(); 416 entries = block->Count();
426 duplicates = 0; 417 duplicates = 0;
427 for (intptr_t i = 0; i < entries; i++) { 418 for (intptr_t i = 0; i < entries; i++) {
428 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i)); 419 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i));
429 RawObject* value = *pointer; 420 RawObject* value = *pointer;
430 if (value->IsHeapObject()) { 421 if (value->IsHeapObject()) {
431 if (from_->Contains(RawObject::ToAddr(value))) { 422 if (from_->Contains(RawObject::ToAddr(value))) {
432 visitor->VisitPointer(pointer); 423 visitor->VisitPointer(pointer);
433 } else { 424 } else {
434 duplicates++; 425 duplicates++;
435 } 426 }
436 } 427 }
437 } 428 }
438 block->Reset(); 429 block->Reset();
439 if (FLAG_verbose_gc) { 430 heap_->RecordData(2, entries);
440 OS::PrintErr("StoreBufferBlock: %"Pd", %"Pd" (entries, dups)\n", 431 heap_->RecordData(3, duplicates);
siva 2013/01/04 01:40:12 It might be more readable to have an enumeration o
Ivan Posva 2013/01/04 02:14:31 Done. Here and in pages.cc
441 entries, duplicates);
442 }
443 } 432 }
444 433
445 434
446 void Scavenger::IterateRoots(Isolate* isolate, 435 void Scavenger::IterateRoots(Isolate* isolate,
447 ScavengerVisitor* visitor, 436 ScavengerVisitor* visitor,
448 bool visit_prologue_weak_persistent_handles) { 437 bool visit_prologue_weak_persistent_handles) {
449 IterateStoreBuffers(isolate, visitor); 438 int64_t start = OS::GetCurrentTimeMicros();
450 isolate->VisitObjectPointers(visitor, 439 isolate->VisitObjectPointers(visitor,
451 visit_prologue_weak_persistent_handles, 440 visit_prologue_weak_persistent_handles,
452 StackFrameIterator::kDontValidateFrames); 441 StackFrameIterator::kDontValidateFrames);
442 int64_t middle = OS::GetCurrentTimeMicros();
443 IterateStoreBuffers(isolate, visitor);
444 int64_t end = OS::GetCurrentTimeMicros();
445 heap_->RecordTime(0, middle - start);
446 heap_->RecordTime(1, end - middle);
453 } 447 }
454 448
455 449
456 bool Scavenger::IsUnreachable(RawObject** p) { 450 bool Scavenger::IsUnreachable(RawObject** p) {
457 RawObject* raw_obj = *p; 451 RawObject* raw_obj = *p;
458 if (!raw_obj->IsHeapObject()) { 452 if (!raw_obj->IsHeapObject()) {
459 return false; 453 return false;
460 } 454 }
461 if (!raw_obj->IsNewObject()) { 455 if (!raw_obj->IsNewObject()) {
462 return false; 456 return false;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { 613 void Scavenger::VisitObjects(ObjectVisitor* visitor) const {
620 uword cur = FirstObjectStart(); 614 uword cur = FirstObjectStart();
621 while (cur < top_) { 615 while (cur < top_) {
622 RawObject* raw_obj = RawObject::FromAddr(cur); 616 RawObject* raw_obj = RawObject::FromAddr(cur);
623 visitor->VisitObject(raw_obj); 617 visitor->VisitObject(raw_obj);
624 cur += raw_obj->Size(); 618 cur += raw_obj->Size();
625 } 619 }
626 } 620 }
627 621
628 622
629 void Scavenger::Scavenge(const char* gc_reason) { 623 void Scavenger::Scavenge() {
630 // TODO(cshapiro): Add a decision procedure for determining when the 624 // TODO(cshapiro): Add a decision procedure for determining when the
631 // the API callbacks should be invoked. 625 // the API callbacks should be invoked.
632 Scavenge(false, gc_reason); 626 Scavenge(false);
633 } 627 }
634 628
635 629
636 void Scavenger::Scavenge(bool invoke_api_callbacks, const char* gc_reason) { 630 void Scavenger::Scavenge(bool invoke_api_callbacks) {
637 // Scavenging is not reentrant. Make sure that is the case. 631 // Scavenging is not reentrant. Make sure that is the case.
638 ASSERT(!scavenging_); 632 ASSERT(!scavenging_);
639 scavenging_ = true; 633 scavenging_ = true;
640 had_promotion_failure_ = false; 634 had_promotion_failure_ = false;
641 Isolate* isolate = Isolate::Current(); 635 Isolate* isolate = Isolate::Current();
642 NoHandleScope no_handles(isolate); 636 NoHandleScope no_handles(isolate);
643 637
644 if (FLAG_verify_before_gc) { 638 if (FLAG_verify_before_gc) {
645 OS::PrintErr("Verifying before Scavenge..."); 639 OS::PrintErr("Verifying before Scavenge...");
646 heap_->Verify(); 640 heap_->Verify();
647 OS::PrintErr(" done.\n"); 641 OS::PrintErr(" done.\n");
648 } 642 }
649 643
650 if (FLAG_verbose_gc) {
651 OS::PrintErr("Start scavenge for %s collection\n", gc_reason);
652 }
653 uword prev_first_obj_start = FirstObjectStart(); 644 uword prev_first_obj_start = FirstObjectStart();
654 uword prev_top_addr = *(TopAddress()); 645 uword prev_top_addr = *(TopAddress());
655 Timer timer(FLAG_verbose_gc, "Scavenge");
656 timer.Start();
657
658 intptr_t in_use_before = in_use();
659 646
660 // Setup the visitor and run a scavenge. 647 // Setup the visitor and run a scavenge.
661 ScavengerVisitor visitor(isolate, this); 648 ScavengerVisitor visitor(isolate, this);
662 Prologue(isolate, invoke_api_callbacks); 649 Prologue(isolate, invoke_api_callbacks);
663 IterateRoots(isolate, &visitor, !invoke_api_callbacks); 650 IterateRoots(isolate, &visitor, !invoke_api_callbacks);
651 int64_t start = OS::GetCurrentTimeMicros();
664 ProcessToSpace(&visitor); 652 ProcessToSpace(&visitor);
653 int64_t middle = OS::GetCurrentTimeMicros();
665 IterateWeakReferences(isolate, &visitor); 654 IterateWeakReferences(isolate, &visitor);
666 ScavengerWeakVisitor weak_visitor(this); 655 ScavengerWeakVisitor weak_visitor(this);
667 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); 656 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks);
668 visitor.Finalize(); 657 visitor.Finalize();
669 ProcessPeerReferents(); 658 ProcessPeerReferents();
659 int64_t end = OS::GetCurrentTimeMicros();
660 heap_->RecordTime(2, middle - start);
661 heap_->RecordTime(3, end - middle);
siva 2013/01/04 01:40:12 Ditto for these 0, 1, 2, 3 values.
670 Epilogue(isolate, invoke_api_callbacks); 662 Epilogue(isolate, invoke_api_callbacks);
671 timer.Stop();
672
673 if (FLAG_verbose_gc) {
674 const intptr_t KB2 = KB / 2;
675 double survival = ((in_use() + visitor.bytes_promoted()) /
676 static_cast<double>(in_use_before)) * 100.0;
677 double promoted = (visitor.bytes_promoted() /
678 static_cast<double>(in_use() + visitor.bytes_promoted()))
679 * 100.0;
680 OS::PrintErr("Scavenge[%d]: %"Pd64"us (%"Pd"K -> %"Pd"K, %"Pd"K)\n"
681 "Surviving %"Pd"K %.1f%%\n"
682 "Promoted survivors %"Pd"K %.1f%%\n",
683 count_,
684 timer.TotalElapsedTime(),
685 (in_use_before + KB2) / KB,
686 (in_use() + KB2) / KB,
687 (capacity() + KB2) / KB,
688 (in_use() + visitor.bytes_promoted() + KB2) / KB,
689 survival,
690 (visitor.bytes_promoted() + KB2) / KB,
691 promoted);
692 }
693 663
694 if (FLAG_verify_after_gc) { 664 if (FLAG_verify_after_gc) {
695 OS::PrintErr("Verifying after Scavenge..."); 665 OS::PrintErr("Verifying after Scavenge...");
696 heap_->Verify(); 666 heap_->Verify();
697 OS::PrintErr(" done.\n"); 667 OS::PrintErr(" done.\n");
698 } 668 }
699 669
700 if (HeapTrace::is_enabled()) { 670 if (HeapTrace::is_enabled()) {
701 heap_->trace()->TraceDeathRange(prev_first_obj_start, prev_top_addr); 671 heap_->trace()->TraceDeathRange(prev_first_obj_start, prev_top_addr);
702 } 672 }
703 673
704 count_++;
705 // Done scavenging. Reset the marker. 674 // Done scavenging. Reset the marker.
706 ASSERT(scavenging_); 675 ASSERT(scavenging_);
707 scavenging_ = false; 676 scavenging_ = false;
708 } 677 }
709 678
710 679
711 void Scavenger::WriteProtect(bool read_only) { 680 void Scavenger::WriteProtect(bool read_only) {
712 space_->Protect( 681 space_->Protect(
713 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); 682 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite);
714 } 683 }
(...skipping 12 matching lines...) Expand all
727 PeerTable::iterator it = peer_table_.find(raw_obj); 696 PeerTable::iterator it = peer_table_.find(raw_obj);
728 return (it == peer_table_.end()) ? NULL : it->second; 697 return (it == peer_table_.end()) ? NULL : it->second;
729 } 698 }
730 699
731 700
732 int64_t Scavenger::PeerCount() const { 701 int64_t Scavenger::PeerCount() const {
733 return static_cast<int64_t>(peer_table_.size()); 702 return static_cast<int64_t>(peer_table_.size());
734 } 703 }
735 704
736 } // namespace dart 705 } // namespace dart
OLDNEW
« runtime/vm/heap.h ('K') | « runtime/vm/scavenger.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698