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

Side by Side Diff: vm/scavenger.cc

Issue 11338017: - Avoid recursion in the scavenger by remembering weak properties (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 1 month 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
« no previous file with comments | « no previous file | 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 } 43 }
44 44
45 45
46 static inline void ForwardTo(uword orignal, uword target) { 46 static inline void ForwardTo(uword orignal, uword target) {
47 // Make sure forwarding can be encoded. 47 // Make sure forwarding can be encoded.
48 ASSERT((target & kForwardingMask) == 0); 48 ASSERT((target & kForwardingMask) == 0);
49 *reinterpret_cast<uword*>(orignal) = target | kForwarded; 49 *reinterpret_cast<uword*>(orignal) = target | kForwarded;
50 } 50 }
51 51
52 52
53 class BoolScope : public ValueObject {
54 public:
55 BoolScope(bool* addr, bool value) : _addr(addr), _value(*addr) {
56 *_addr = value;
57 }
58 ~BoolScope() {
59 *_addr = _value;
60 }
61
62 private:
63 bool* _addr;
64 bool _value;
65 };
66
67
53 class ScavengerVisitor : public ObjectPointerVisitor { 68 class ScavengerVisitor : public ObjectPointerVisitor {
54 public: 69 public:
55 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) 70 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger)
56 : ObjectPointerVisitor(isolate), 71 : ObjectPointerVisitor(isolate),
57 scavenger_(scavenger), 72 scavenger_(scavenger),
58 heap_(scavenger->heap_), 73 heap_(scavenger->heap_),
59 vm_heap_(Dart::vm_isolate()->heap()), 74 vm_heap_(Dart::vm_isolate()->heap()),
60 visiting_old_pointers_(false) {} 75 delayed_weak_stack_(),
76 visiting_old_pointers_(false),
77 in_scavenge_pointer_(false) {}
61 78
62 void VisitPointers(RawObject** first, RawObject** last) { 79 void VisitPointers(RawObject** first, RawObject** last) {
63 for (RawObject** current = first; current <= last; current++) { 80 for (RawObject** current = first; current <= last; current++) {
64 ScavengePointer(current); 81 ScavengePointer(current);
65 } 82 }
66 } 83 }
67 84
68 void VisitingOldPointers(bool value) { visiting_old_pointers_ = value; } 85 GrowableArray<RawObject*>* DelayedWeakStack() {
86 return &delayed_weak_stack_;
87 }
88
89 bool* VisitingOldPointersAddr() { return &visiting_old_pointers_; }
69 90
70 void DelayWeakProperty(RawWeakProperty* raw_weak) { 91 void DelayWeakProperty(RawWeakProperty* raw_weak) {
71 RawObject* raw_key = raw_weak->ptr()->key_; 92 RawObject* raw_key = raw_weak->ptr()->key_;
72 DelaySet::iterator it = delay_set_.find(raw_key); 93 DelaySet::iterator it = delay_set_.find(raw_key);
73 if (it != delay_set_.end()) { 94 if (it != delay_set_.end()) {
74 ASSERT(raw_key->IsWatched()); 95 ASSERT(raw_key->IsWatched());
75 } else { 96 } else {
76 ASSERT(!raw_key->IsWatched()); 97 ASSERT(!raw_key->IsWatched());
77 raw_key->SetWatchedBit(); 98 raw_key->SetWatchedBit();
78 } 99 }
(...skipping 13 matching lines...) Expand all
92 ASSERT(obj->IsHeapObject()); 113 ASSERT(obj->IsHeapObject());
93 ASSERT(!scavenger_->Contains(ptr)); 114 ASSERT(!scavenger_->Contains(ptr));
94 ASSERT(!heap_->CodeContains(ptr)); 115 ASSERT(!heap_->CodeContains(ptr));
95 ASSERT(heap_->Contains(ptr)); 116 ASSERT(heap_->Contains(ptr));
96 // If the newly written object is not a new object, drop it immediately. 117 // If the newly written object is not a new object, drop it immediately.
97 if (!obj->IsNewObject()) return; 118 if (!obj->IsNewObject()) return;
98 isolate()->store_buffer()->AddPointer(ptr); 119 isolate()->store_buffer()->AddPointer(ptr);
99 } 120 }
100 121
101 void ScavengePointer(RawObject** p) { 122 void ScavengePointer(RawObject** p) {
123 // ScavengePointer cannot be called recursively.
124 ASSERT(!in_scavenge_pointer_);
125 BoolScope bs(&in_scavenge_pointer_, true);
126
102 RawObject* raw_obj = *p; 127 RawObject* raw_obj = *p;
103 128
104 // Fast exit if the raw object is a Smi or an old object. 129 // Fast exit if the raw object is a Smi or an old object.
105 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { 130 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) {
106 return; 131 return;
107 } 132 }
108 133
109 uword raw_addr = RawObject::ToAddr(raw_obj); 134 uword raw_addr = RawObject::ToAddr(raw_obj);
110 // Objects should be contained in the heap. 135 // Objects should be contained in the heap.
111 // TODO(iposva): Add an appropriate assert here or in the return block 136 // TODO(iposva): Add an appropriate assert here or in the return block
112 // below. 137 // below.
113 // The scavenger is only interested in objects located in the from space. 138 // The scavenger is only interested in objects located in the from space.
114 if (!scavenger_->from_->Contains(raw_addr)) { 139 if (!scavenger_->from_->Contains(raw_addr)) {
115 return; 140 return;
116 } 141 }
117 142
118 // Read the header word of the object and determine if the object has 143 // Read the header word of the object and determine if the object has
119 // already been copied. 144 // already been copied.
120 uword header = *reinterpret_cast<uword*>(raw_addr); 145 uword header = *reinterpret_cast<uword*>(raw_addr);
121 uword new_addr = 0; 146 uword new_addr = 0;
122 if (IsForwarding(header)) { 147 if (IsForwarding(header)) {
123 // Get the new location of the object. 148 // Get the new location of the object.
124 new_addr = ForwardedAddr(header); 149 new_addr = ForwardedAddr(header);
125 } else if (raw_obj->IsWatched()) { 150 } else {
126 // Forward the object by scavenging its watchers. 151 if (raw_obj->IsWatched()) {
127 raw_obj->ClearWatchedBit(); 152 raw_obj->ClearWatchedBit();
128 std::pair<DelaySet::iterator, DelaySet::iterator> ret; 153 std::pair<DelaySet::iterator, DelaySet::iterator> ret;
129 // Visit all elements with a key equal to raw_obj. 154 // Visit all elements with a key equal to this raw_obj.
130 ret = delay_set_.equal_range(raw_obj); 155 ret = delay_set_.equal_range(raw_obj);
131 for (DelaySet::iterator it = ret.first; it != ret.second; ++it) { 156 for (DelaySet::iterator it = ret.first; it != ret.second; ++it) {
132 // Scavenge the delayed WeakProperty. These objects have been 157 // Remember the delayed WeakProperty. These objects have been
133 // forwarded but have not been scavenged because their key 158 // forwarded, but have not been scavenged because their key was not
134 // object was not known to be reachable. Now that the key 159 // known to be reachable. Now that the key object is known to be
135 // object is known to be reachable we can scavenge the key and 160 // reachable, we need to visit its key and value pointers.
136 // value pointers. 161 delayed_weak_stack_.Add(it->second);
137 it->second->VisitPointers(this); 162 }
163 delay_set_.erase(ret.first, ret.second);
138 } 164 }
139 delay_set_.erase(ret.first, ret.second);
140 // Reread the header word to get the new location of the object.
141 header = *reinterpret_cast<uword*>(raw_addr);
142 ASSERT(IsForwarding(header));
143 new_addr = ForwardedAddr(header);
144 } else {
145 intptr_t size = raw_obj->Size(); 165 intptr_t size = raw_obj->Size();
146 // Check whether object should be promoted. 166 // Check whether object should be promoted.
147 if (scavenger_->survivor_end_ <= raw_addr) { 167 if (scavenger_->survivor_end_ <= raw_addr) {
148 // Not a survivor of a previous scavenge. Just copy the object into the 168 // Not a survivor of a previous scavenge. Just copy the object into the
149 // to space. 169 // to space.
150 new_addr = scavenger_->TryAllocate(size); 170 new_addr = scavenger_->TryAllocate(size);
151 } else { 171 } else {
152 // TODO(iposva): Experiment with less aggressive promotion. For example 172 // TODO(iposva): Experiment with less aggressive promotion. For example
153 // a coin toss determines if an object is promoted or whether it should 173 // a coin toss determines if an object is promoted or whether it should
154 // survive in this generation. 174 // survive in this generation.
(...skipping 28 matching lines...) Expand all
183 if (visiting_old_pointers_) { 203 if (visiting_old_pointers_) {
184 UpdateStoreBuffer(p, new_obj); 204 UpdateStoreBuffer(p, new_obj);
185 } 205 }
186 } 206 }
187 207
188 Scavenger* scavenger_; 208 Scavenger* scavenger_;
189 Heap* heap_; 209 Heap* heap_;
190 Heap* vm_heap_; 210 Heap* vm_heap_;
191 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; 211 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet;
192 DelaySet delay_set_; 212 DelaySet delay_set_;
213 GrowableArray<RawObject*> delayed_weak_stack_;
193 214
194 bool visiting_old_pointers_; 215 bool visiting_old_pointers_;
216 bool in_scavenge_pointer_;
195 217
196 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); 218 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor);
197 }; 219 };
198 220
199 221
200 class ScavengerWeakVisitor : public HandleVisitor { 222 class ScavengerWeakVisitor : public HandleVisitor {
201 public: 223 public:
202 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { 224 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) {
203 } 225 }
204 226
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 #endif // defined(DEBUG) 340 #endif // defined(DEBUG)
319 if (invoke_api_callbacks) { 341 if (invoke_api_callbacks) {
320 isolate->gc_epilogue_callbacks().Invoke(); 342 isolate->gc_epilogue_callbacks().Invoke();
321 } 343 }
322 } 344 }
323 345
324 346
325 void Scavenger::IterateStoreBuffers(Isolate* isolate, 347 void Scavenger::IterateStoreBuffers(Isolate* isolate,
326 ScavengerVisitor* visitor) { 348 ScavengerVisitor* visitor) {
327 // Iterating through the store buffers. 349 // Iterating through the store buffers.
328 visitor->VisitingOldPointers(true); 350 BoolScope bs(visitor->VisitingOldPointersAddr(), true);
329 // Grab the deduplication sets out of the store buffer. 351 // Grab the deduplication sets out of the store buffer.
330 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets(); 352 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets();
331 intptr_t entries = 0; 353 intptr_t entries = 0;
332 intptr_t duplicates = 0; 354 intptr_t duplicates = 0;
333 while (pending != NULL) { 355 while (pending != NULL) {
334 StoreBuffer::DedupSet* next = pending->next(); 356 StoreBuffer::DedupSet* next = pending->next();
335 HashSet* set = pending->set(); 357 HashSet* set = pending->set();
336 intptr_t count = set->Count(); 358 intptr_t count = set->Count();
337 intptr_t size = set->Size(); 359 intptr_t size = set->Size();
338 intptr_t handled = 0; 360 intptr_t handled = 0;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 } else { 396 } else {
375 duplicates++; 397 duplicates++;
376 } 398 }
377 } 399 }
378 } 400 }
379 block->Reset(); 401 block->Reset();
380 if (FLAG_verbose_gc) { 402 if (FLAG_verbose_gc) {
381 OS::PrintErr("StoreBufferBlock: %"Pd", %"Pd" (entries, dups)\n", 403 OS::PrintErr("StoreBufferBlock: %"Pd", %"Pd" (entries, dups)\n",
382 entries, duplicates); 404 entries, duplicates);
383 } 405 }
384 // Done iterating through the store buffers.
385 visitor->VisitingOldPointers(false);
386 } 406 }
387 407
388 408
389 void Scavenger::IterateRoots(Isolate* isolate, 409 void Scavenger::IterateRoots(Isolate* isolate,
390 ScavengerVisitor* visitor, 410 ScavengerVisitor* visitor,
391 bool visit_prologue_weak_persistent_handles) { 411 bool visit_prologue_weak_persistent_handles) {
392 IterateStoreBuffers(isolate, visitor); 412 IterateStoreBuffers(isolate, visitor);
393 isolate->VisitObjectPointers(visitor, 413 isolate->VisitObjectPointers(visitor,
394 visit_prologue_weak_persistent_handles, 414 visit_prologue_weak_persistent_handles,
395 StackFrameIterator::kDontValidateFrames); 415 StackFrameIterator::kDontValidateFrames);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 492
473 void Scavenger::IterateWeakRoots(Isolate* isolate, 493 void Scavenger::IterateWeakRoots(Isolate* isolate,
474 HandleVisitor* visitor, 494 HandleVisitor* visitor,
475 bool visit_prologue_weak_persistent_handles) { 495 bool visit_prologue_weak_persistent_handles) {
476 isolate->VisitWeakPersistentHandles(visitor, 496 isolate->VisitWeakPersistentHandles(visitor,
477 visit_prologue_weak_persistent_handles); 497 visit_prologue_weak_persistent_handles);
478 } 498 }
479 499
480 500
481 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { 501 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) {
502 GrowableArray<RawObject*>* delayed_weak_stack = visitor->DelayedWeakStack();
503
482 // Iterate until all work has been drained. 504 // Iterate until all work has been drained.
483 while ((resolved_top_ < top_) || PromotedStackHasMore()) { 505 while ((resolved_top_ < top_) ||
506 PromotedStackHasMore() ||
507 !delayed_weak_stack->is_empty()) {
484 while (resolved_top_ < top_) { 508 while (resolved_top_ < top_) {
485 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); 509 RawObject* raw_obj = RawObject::FromAddr(resolved_top_);
486 intptr_t class_id = raw_obj->GetClassId(); 510 intptr_t class_id = raw_obj->GetClassId();
487 if (class_id != kWeakPropertyCid) { 511 if (class_id != kWeakPropertyCid) {
488 resolved_top_ += raw_obj->VisitPointers(visitor); 512 resolved_top_ += raw_obj->VisitPointers(visitor);
489 } else { 513 } else {
490 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); 514 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
491 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); 515 resolved_top_ += ProcessWeakProperty(raw_weak, visitor);
492 } 516 }
493 } 517 }
494 visitor->VisitingOldPointers(true); 518 {
495 while (PromotedStackHasMore()) { 519 BoolScope bs(visitor->VisitingOldPointersAddr(), true);
496 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); 520 while (PromotedStackHasMore()) {
497 // Resolve or copy all objects referred to by the current object. This 521 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack());
498 // can potentially push more objects on this stack as well as add more 522 // Resolve or copy all objects referred to by the current object. This
499 // objects to be resolved in the to space. 523 // can potentially push more objects on this stack as well as add more
500 raw_object->VisitPointers(visitor); 524 // objects to be resolved in the to space.
525 raw_object->VisitPointers(visitor);
526 }
501 } 527 }
502 visitor->VisitingOldPointers(false); 528 while (!delayed_weak_stack->is_empty()) {
529 // Pop the delayed weak object from the stack and visit its pointers.
530 RawObject* weak_property = delayed_weak_stack->Last();
531 delayed_weak_stack->RemoveLast();
532 weak_property->VisitPointers(visitor);
533 }
503 } 534 }
504 } 535 }
505 536
506 537
507 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, 538 uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak,
508 ScavengerVisitor* visitor) { 539 ScavengerVisitor* visitor) {
509 // The fate of the weak property is determined by its key. 540 // The fate of the weak property is determined by its key.
510 RawObject* raw_key = raw_weak->ptr()->key_; 541 RawObject* raw_key = raw_weak->ptr()->key_;
511 if (raw_key->IsHeapObject() && raw_key->IsNewObject()) { 542 if (raw_key->IsHeapObject() && raw_key->IsNewObject()) {
512 uword raw_addr = RawObject::ToAddr(raw_key); 543 uword raw_addr = RawObject::ToAddr(raw_key);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 PeerTable::iterator it = peer_table_.find(raw_obj); 666 PeerTable::iterator it = peer_table_.find(raw_obj);
636 return (it == peer_table_.end()) ? NULL : it->second; 667 return (it == peer_table_.end()) ? NULL : it->second;
637 } 668 }
638 669
639 670
640 int64_t Scavenger::PeerCount() const { 671 int64_t Scavenger::PeerCount() const {
641 return static_cast<int64_t>(peer_table_.size()); 672 return static_cast<int64_t>(peer_table_.size());
642 } 673 }
643 674
644 } // namespace dart 675 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698