| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include "vm/gc_marker.h" |
| 6 |
| 7 #include "vm/allocation.h" |
| 8 #include "vm/isolate.h" |
| 9 #include "vm/pages.h" |
| 10 #include "vm/raw_object.h" |
| 11 #include "vm/stack_frame.h" |
| 12 #include "vm/visitor.h" |
| 13 |
| 14 namespace dart { |
| 15 |
| 16 // A simple chunked marking stack. |
| 17 class MarkingStack : public ValueObject { |
| 18 public: |
| 19 MarkingStack() |
| 20 : head_(new MarkingStackChunk()), |
| 21 empty_chunks_(NULL), |
| 22 marking_stack_(NULL), |
| 23 top_(0) { |
| 24 marking_stack_ = head_->MarkingStackChunkMemory(); |
| 25 } |
| 26 |
| 27 ~MarkingStack() { |
| 28 // TODO(iposva): Consider caching a couple emtpy marking stack chunks. |
| 29 ASSERT(IsEmpty()); |
| 30 delete head_; |
| 31 MarkingStackChunk* next; |
| 32 while (empty_chunks_ != NULL) { |
| 33 next = empty_chunks_->next(); |
| 34 delete empty_chunks_; |
| 35 empty_chunks_ = next; |
| 36 } |
| 37 } |
| 38 |
| 39 bool IsEmpty() const { |
| 40 return IsMarkingStackChunkEmpty() && (head_->next() == NULL); |
| 41 } |
| 42 |
| 43 void Push(RawObject* value) { |
| 44 ASSERT(!IsMarkingStackChunkFull()); |
| 45 marking_stack_[top_] = value; |
| 46 top_++; |
| 47 if (IsMarkingStackChunkFull()) { |
| 48 MarkingStackChunk* new_chunk; |
| 49 if (empty_chunks_ == NULL) { |
| 50 new_chunk = new MarkingStackChunk(); |
| 51 } else { |
| 52 new_chunk = empty_chunks_; |
| 53 empty_chunks_ = new_chunk->next(); |
| 54 } |
| 55 new_chunk->set_next(head_); |
| 56 head_ = new_chunk; |
| 57 marking_stack_ = head_->MarkingStackChunkMemory(); |
| 58 top_ = 0; |
| 59 } |
| 60 } |
| 61 |
| 62 RawObject* Pop() { |
| 63 ASSERT(head_ != NULL); |
| 64 ASSERT(!IsEmpty()); |
| 65 if (IsMarkingStackChunkEmpty()) { |
| 66 MarkingStackChunk* empty_chunk = head_; |
| 67 head_ = head_->next(); |
| 68 empty_chunk->set_next(empty_chunks_); |
| 69 empty_chunks_ = empty_chunk; |
| 70 marking_stack_ = head_->MarkingStackChunkMemory(); |
| 71 top_ = MarkingStackChunk::kMarkingStackChunkSize; |
| 72 } |
| 73 top_--; |
| 74 return marking_stack_[top_]; |
| 75 } |
| 76 |
| 77 private: |
| 78 class MarkingStackChunk { |
| 79 public: |
| 80 MarkingStackChunk() : next_(NULL) {} |
| 81 ~MarkingStackChunk() {} |
| 82 |
| 83 RawObject** MarkingStackChunkMemory() { |
| 84 return &memory_[0]; |
| 85 } |
| 86 |
| 87 MarkingStackChunk* next() const { return next_; } |
| 88 void set_next(MarkingStackChunk* value) { next_ = value; } |
| 89 |
| 90 static const uint32_t kMarkingStackChunkSize = 1024; |
| 91 |
| 92 private: |
| 93 RawObject* memory_[kMarkingStackChunkSize]; |
| 94 MarkingStackChunk* next_; |
| 95 |
| 96 DISALLOW_COPY_AND_ASSIGN(MarkingStackChunk); |
| 97 }; |
| 98 |
| 99 bool IsMarkingStackChunkFull() const { |
| 100 return top_ == MarkingStackChunk::kMarkingStackChunkSize; |
| 101 } |
| 102 |
| 103 bool IsMarkingStackChunkEmpty() const { |
| 104 return top_ == 0; |
| 105 } |
| 106 |
| 107 MarkingStackChunk* head_; |
| 108 MarkingStackChunk* empty_chunks_; |
| 109 RawObject** marking_stack_; |
| 110 uint32_t top_; |
| 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(MarkingStack); |
| 113 }; |
| 114 |
| 115 |
| 116 class MarkingVisitor : public ObjectPointerVisitor { |
| 117 public: |
| 118 MarkingVisitor(Heap* heap, PageSpace* page_space, MarkingStack* marking_stack) |
| 119 : heap_(heap), |
| 120 vm_heap_(Dart::vm_isolate()->heap()), |
| 121 page_space_(page_space), |
| 122 marking_stack_(marking_stack) {} |
| 123 |
| 124 MarkingStack* marking_stack() const { return marking_stack_; } |
| 125 |
| 126 void VisitPointers(RawObject** first, RawObject** last) { |
| 127 for (RawObject** current = first; current <= last; current++) { |
| 128 MarkObject(*current); |
| 129 } |
| 130 } |
| 131 |
| 132 private: |
| 133 void MarkAndPush(RawObject* raw_obj) { |
| 134 ASSERT(raw_obj->IsHeapObject()); |
| 135 |
| 136 // Mark the object and push it on the marking stack. |
| 137 ASSERT(!raw_obj->IsMarked()); |
| 138 RawClass* raw_class = raw_obj->ptr()->class_; |
| 139 raw_obj->SetMarkBit(); |
| 140 marking_stack_->Push(raw_obj); |
| 141 |
| 142 // TODO(iposva): Should we mark the classes early? |
| 143 MarkObject(raw_class); |
| 144 } |
| 145 |
| 146 void MarkObject(RawObject* raw_obj) { |
| 147 // Fast exit if the raw object is a Smi. |
| 148 if (!raw_obj->IsHeapObject()) return; |
| 149 |
| 150 // Fast exit if the raw object is marked. |
| 151 if (raw_obj->IsMarked()) return; |
| 152 |
| 153 // Skip over new objects, but verify consistency of heap while at it. |
| 154 if (raw_obj->IsNewObject()) { |
| 155 // TODO(iposva): Add consistency check. |
| 156 return; |
| 157 } |
| 158 |
| 159 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 160 // TODO(iposva): Premark vm_isolate objects, to avoid this extra check here. |
| 161 if (vm_heap_->Contains(raw_addr)) { |
| 162 return; |
| 163 } |
| 164 // TODO(iposva): merge old and code spaces. |
| 165 // ASSERT(page_space_->Contains(raw_addr)); |
| 166 |
| 167 MarkAndPush(raw_obj); |
| 168 } |
| 169 |
| 170 Heap* heap_; |
| 171 Heap* vm_heap_; |
| 172 PageSpace* page_space_; |
| 173 MarkingStack* marking_stack_; |
| 174 |
| 175 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); |
| 176 }; |
| 177 |
| 178 |
| 179 void GCMarker::Prologue(Isolate* isolate) { |
| 180 // Nothing to do at the moment. |
| 181 } |
| 182 |
| 183 |
| 184 void GCMarker::IterateRoots(Isolate* isolate, MarkingVisitor* visitor) { |
| 185 isolate->VisitObjectPointers(visitor, |
| 186 StackFrameIterator::kDontValidateFrames); |
| 187 heap_->IterateNewPointers(visitor); |
| 188 } |
| 189 |
| 190 |
| 191 void GCMarker::DrainMarkingStack(Isolate* isolate, MarkingVisitor* visitor) { |
| 192 while (!visitor->marking_stack()->IsEmpty()) { |
| 193 RawObject* raw_obj = visitor->marking_stack()->Pop(); |
| 194 raw_obj->VisitPointers(visitor); |
| 195 } |
| 196 } |
| 197 |
| 198 |
| 199 void GCMarker::MarkObjects(Isolate* isolate, PageSpace* page_space) { |
| 200 MarkingStack marking_stack; |
| 201 Prologue(isolate); |
| 202 MarkingVisitor mark(heap_, page_space, &marking_stack); |
| 203 IterateRoots(isolate, &mark); |
| 204 DrainMarkingStack(isolate, &mark); |
| 205 } |
| 206 |
| 207 } // namespace dart |
| OLD | NEW |