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 |
11 #include "vm/dart.h" | 11 #include "vm/dart.h" |
12 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
13 #include "vm/isolate.h" | 13 #include "vm/isolate.h" |
14 #include "vm/object.h" | 14 #include "vm/object.h" |
15 #include "vm/stack_frame.h" | 15 #include "vm/stack_frame.h" |
16 #include "vm/store_buffer.h" | 16 #include "vm/store_buffer.h" |
17 #include "vm/verifier.h" | 17 #include "vm/verifier.h" |
18 #include "vm/visitor.h" | 18 #include "vm/visitor.h" |
19 | 19 |
20 namespace dart { | 20 namespace dart { |
21 | 21 |
22 // Scavenger uses RawObject::kFreeBit to distinguish forwaded and non-forwarded | 22 // Scavenger uses RawObject::kMarkBit to distinguish forwaded and non-forwarded |
23 // objects because scavenger can never encounter free list element during | 23 // objects because scavenger can never encounter marked elements during |
24 // evacuation and thus all objects scavenger encounters have | 24 // evacuation and thus all objects scavenger encounters have the |
25 // kFreeBit cleared. | 25 // kMarkBit cleared. |
26 enum { | 26 enum { |
27 kForwardingMask = 1, | 27 kForwardingMask = RawObject::kMarkBit, |
28 kNotForwarded = 0, | 28 kNotForwarded = 0, |
29 kForwarded = 1, | 29 kForwarded = kForwardingMask, |
30 }; | 30 }; |
31 | 31 |
32 | 32 |
33 static inline bool IsForwarding(uword header) { | 33 static inline bool IsForwarding(uword header) { |
34 uword bits = header & kForwardingMask; | 34 uword bits = header & kForwardingMask; |
35 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); | 35 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); |
36 return bits == kForwarded; | 36 return bits == kForwarded; |
37 } | 37 } |
38 | 38 |
39 | 39 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 intptr_t bytes_promoted() const { return bytes_promoted_; } | 115 intptr_t bytes_promoted() const { return bytes_promoted_; } |
116 | 116 |
117 private: | 117 private: |
118 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 118 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
119 uword ptr = reinterpret_cast<uword>(p); | 119 uword ptr = reinterpret_cast<uword>(p); |
120 ASSERT(obj->IsHeapObject()); | 120 ASSERT(obj->IsHeapObject()); |
121 ASSERT(!scavenger_->Contains(ptr)); | 121 ASSERT(!scavenger_->Contains(ptr)); |
122 ASSERT(!heap_->CodeContains(ptr)); | 122 ASSERT(!heap_->CodeContains(ptr)); |
123 ASSERT(heap_->Contains(ptr)); | 123 ASSERT(heap_->Contains(ptr)); |
124 // 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. |
125 if (!obj->IsNewObject()) return; | 125 if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) { |
| 126 return; |
| 127 } |
| 128 visiting_old_object_->SetRememberedBit(); |
126 isolate()->store_buffer()->AddPointer( | 129 isolate()->store_buffer()->AddPointer( |
127 reinterpret_cast<uword>(visiting_old_object_)); | 130 reinterpret_cast<uword>(visiting_old_object_)); |
128 } | 131 } |
129 | 132 |
130 void ScavengePointer(RawObject** p) { | 133 void ScavengePointer(RawObject** p) { |
131 // ScavengePointer cannot be called recursively. | 134 // ScavengePointer cannot be called recursively. |
132 #ifdef DEBUG | 135 #ifdef DEBUG |
133 ASSERT(!in_scavenge_pointer_); | 136 ASSERT(!in_scavenge_pointer_); |
134 BoolScope bs(&in_scavenge_pointer_, true); | 137 BoolScope bs(&in_scavenge_pointer_, true); |
135 #endif | 138 #endif |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 }; | 295 }; |
293 | 296 |
294 | 297 |
295 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) | 298 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) |
296 : heap_(heap), | 299 : heap_(heap), |
297 object_alignment_(object_alignment), | 300 object_alignment_(object_alignment), |
298 scavenging_(false) { | 301 scavenging_(false) { |
299 // Verify assumptions about the first word in objects which the scavenger is | 302 // Verify assumptions about the first word in objects which the scavenger is |
300 // going to use for forwarding pointers. | 303 // going to use for forwarding pointers. |
301 ASSERT(Object::tags_offset() == 0); | 304 ASSERT(Object::tags_offset() == 0); |
302 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit)); | |
303 | 305 |
304 // Allocate the virtual memory for this scavenge heap. | 306 // Allocate the virtual memory for this scavenge heap. |
305 space_ = VirtualMemory::Reserve(max_capacity); | 307 space_ = VirtualMemory::Reserve(max_capacity); |
306 if (space_ == NULL) { | 308 if (space_ == NULL) { |
307 FATAL("Out of memory.\n"); | 309 FATAL("Out of memory.\n"); |
308 } | 310 } |
309 | 311 |
310 // Allocate the entire space at the beginning. | 312 // Allocate the entire space at the beginning. |
311 space_->Commit(false); | 313 space_->Commit(false); |
312 | 314 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 while (pending != NULL) { | 394 while (pending != NULL) { |
393 StoreBuffer::DedupSet* next = pending->next(); | 395 StoreBuffer::DedupSet* next = pending->next(); |
394 HashSet* set = pending->set(); | 396 HashSet* set = pending->set(); |
395 intptr_t count = set->Count(); | 397 intptr_t count = set->Count(); |
396 intptr_t size = set->Size(); | 398 intptr_t size = set->Size(); |
397 intptr_t handled = 0; | 399 intptr_t handled = 0; |
398 entries += count; | 400 entries += count; |
399 for (intptr_t i = 0; i < size; i++) { | 401 for (intptr_t i = 0; i < size; i++) { |
400 RawObject* raw_object = reinterpret_cast<RawObject*>(set->At(i)); | 402 RawObject* raw_object = reinterpret_cast<RawObject*>(set->At(i)); |
401 if (raw_object != NULL) { | 403 if (raw_object != NULL) { |
| 404 ASSERT(raw_object->IsRemembered()); |
| 405 raw_object->ClearRememberedBit(); |
402 visitor->VisitingOldObject(raw_object); | 406 visitor->VisitingOldObject(raw_object); |
403 raw_object->VisitPointers(visitor); | 407 raw_object->VisitPointers(visitor); |
404 handled++; | 408 handled++; |
405 if (handled == count) { | 409 if (handled == count) { |
406 break; | 410 break; |
407 } | 411 } |
408 } | 412 } |
409 } | 413 } |
410 delete pending; | 414 delete pending; |
411 pending = next; | 415 pending = next; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | 533 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
530 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); | 534 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); |
531 } | 535 } |
532 } | 536 } |
533 { | 537 { |
534 while (PromotedStackHasMore()) { | 538 while (PromotedStackHasMore()) { |
535 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); | 539 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); |
536 // Resolve or copy all objects referred to by the current object. This | 540 // Resolve or copy all objects referred to by the current object. This |
537 // can potentially push more objects on this stack as well as add more | 541 // can potentially push more objects on this stack as well as add more |
538 // objects to be resolved in the to space. | 542 // objects to be resolved in the to space. |
| 543 ASSERT(!raw_object->IsRemembered()); |
539 visitor->VisitingOldObject(raw_object); | 544 visitor->VisitingOldObject(raw_object); |
540 raw_object->VisitPointers(visitor); | 545 raw_object->VisitPointers(visitor); |
541 } | 546 } |
542 visitor->VisitingOldObject(NULL); | 547 visitor->VisitingOldObject(NULL); |
543 } | 548 } |
544 while (!delayed_weak_stack->is_empty()) { | 549 while (!delayed_weak_stack->is_empty()) { |
545 // Pop the delayed weak object from the stack and visit its pointers. | 550 // Pop the delayed weak object from the stack and visit its pointers. |
546 RawObject* weak_property = delayed_weak_stack->RemoveLast(); | 551 RawObject* weak_property = delayed_weak_stack->RemoveLast(); |
547 weak_property->VisitPointers(visitor); | 552 weak_property->VisitPointers(visitor); |
548 } | 553 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 PeerTable::iterator it = peer_table_.find(raw_obj); | 679 PeerTable::iterator it = peer_table_.find(raw_obj); |
675 return (it == peer_table_.end()) ? NULL : it->second; | 680 return (it == peer_table_.end()) ? NULL : it->second; |
676 } | 681 } |
677 | 682 |
678 | 683 |
679 int64_t Scavenger::PeerCount() const { | 684 int64_t Scavenger::PeerCount() const { |
680 return static_cast<int64_t>(peer_table_.size()); | 685 return static_cast<int64_t>(peer_table_.size()); |
681 } | 686 } |
682 | 687 |
683 } // namespace dart | 688 } // namespace dart |
OLD | NEW |