| 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 "vm/dart.h" | 7 #include "vm/dart.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/stack_frame.h" | 10 #include "vm/stack_frame.h" |
| 11 #include "vm/verifier.h" | 11 #include "vm/verifier.h" |
| 12 #include "vm/visitor.h" | 12 #include "vm/visitor.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 enum { |
| 17 kForwardingMask = 3, |
| 18 kNotForwarded = 1, // Tagged pointer. |
| 19 kForwarded = 3, // Tagged pointer and forwarding bit set. |
| 20 }; |
| 21 |
| 22 |
| 23 static inline bool IsForwarding(uword header) { |
| 24 uword bits = header & kForwardingMask; |
| 25 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); |
| 26 return bits == kForwarded; |
| 27 } |
| 28 |
| 29 |
| 30 static inline uword ForwardedAddr(uword header) { |
| 31 ASSERT(IsForwarding(header)); |
| 32 return header & ~kForwardingMask; |
| 33 } |
| 34 |
| 35 |
| 36 static inline void ForwardTo(uword orignal, uword target) { |
| 37 // Make sure forwarding can be encoded. |
| 38 ASSERT((target & kForwardingMask) == 0); |
| 39 *reinterpret_cast<uword*>(orignal) = target | kForwarded; |
| 40 } |
| 41 |
| 42 |
| 16 class ScavengerVisitor : public ObjectPointerVisitor { | 43 class ScavengerVisitor : public ObjectPointerVisitor { |
| 17 public: | 44 public: |
| 18 explicit ScavengerVisitor(Scavenger* scavenger) | 45 explicit ScavengerVisitor(Scavenger* scavenger) |
| 19 : scavenger_(scavenger), | 46 : scavenger_(scavenger), |
| 20 heap_(scavenger->heap_), | 47 heap_(scavenger->heap_), |
| 21 vm_heap_(Dart::vm_isolate()->heap()) {} | 48 vm_heap_(Dart::vm_isolate()->heap()) {} |
| 22 | 49 |
| 23 void VisitPointers(RawObject** first, RawObject** last) { | 50 void VisitPointers(RawObject** first, RawObject** last) { |
| 24 for (RawObject** current = first; current <= last; current++) { | 51 for (RawObject** current = first; current <= last; current++) { |
| 25 ScavengePointer(current); | 52 ScavengePointer(current); |
| 26 } | 53 } |
| 27 } | 54 } |
| 28 | 55 |
| 29 private: | 56 private: |
| 30 enum { | |
| 31 kForwardingMask = 3, | |
| 32 kNotForwarded = 1, // Tagged pointer. | |
| 33 kForwarded = 3, // Tagged pointer and forwarding bit set. | |
| 34 }; | |
| 35 | |
| 36 static inline bool IsForwarding(uword header) { | |
| 37 uword bits = header & kForwardingMask; | |
| 38 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); | |
| 39 return bits == kForwarded; | |
| 40 } | |
| 41 | |
| 42 static inline uword ForwardedAddr(uword header) { | |
| 43 ASSERT(IsForwarding(header)); | |
| 44 return header & ~kForwardingMask; | |
| 45 } | |
| 46 | |
| 47 static inline void ForwardTo(uword orignal, uword target) { | |
| 48 // Make sure forwarding can be encoded. | |
| 49 ASSERT((target & kForwardingMask) == 0); | |
| 50 *reinterpret_cast<uword*>(orignal) = target | kForwarded; | |
| 51 } | |
| 52 | |
| 53 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 57 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
| 54 // TODO(iposva): Implement store buffers. | 58 // TODO(iposva): Implement store buffers. |
| 55 } | 59 } |
| 56 | 60 |
| 57 void ScavengePointer(RawObject** p) { | 61 void ScavengePointer(RawObject** p) { |
| 58 RawObject* raw_obj = *p; | 62 RawObject* raw_obj = *p; |
| 59 | 63 |
| 60 // Fast exit if the raw object is a Smi. | 64 // Fast exit if the raw object is a Smi. |
| 61 if (!raw_obj->IsHeapObject()) return; | 65 if (!raw_obj->IsHeapObject()) return; |
| 62 | 66 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 // Update the reference. | 102 // Update the reference. |
| 99 RawObject* new_obj = RawObject::FromAddr(new_addr); | 103 RawObject* new_obj = RawObject::FromAddr(new_addr); |
| 100 *p = new_obj; | 104 *p = new_obj; |
| 101 // Update the store buffer as needed. | 105 // Update the store buffer as needed. |
| 102 UpdateStoreBuffer(p, new_obj); | 106 UpdateStoreBuffer(p, new_obj); |
| 103 } | 107 } |
| 104 | 108 |
| 105 Scavenger* scavenger_; | 109 Scavenger* scavenger_; |
| 106 Heap* heap_; | 110 Heap* heap_; |
| 107 Heap* vm_heap_; | 111 Heap* vm_heap_; |
| 112 |
| 113 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
| 108 }; | 114 }; |
| 109 | 115 |
| 110 | 116 |
| 117 class ScavengerWeakVisitor : public ObjectPointerVisitor { |
| 118 public: |
| 119 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
| 120 } |
| 121 |
| 122 void VisitPointers(RawObject** first, RawObject** last) { |
| 123 for (RawObject** current = first; current <= last; current++) { |
| 124 RawObject* raw_obj = *current; |
| 125 ASSERT(raw_obj->IsHeapObject()); |
| 126 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 127 if (scavenger_->from_->Contains(raw_addr)) { |
| 128 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 129 if (IsForwarding(header)) { |
| 130 *current = RawObject::FromAddr(ForwardedAddr(header)); |
| 131 } else { |
| 132 *current = Object::null(); |
| 133 } |
| 134 } |
| 135 } |
| 136 } |
| 137 |
| 138 private: |
| 139 Scavenger* scavenger_; |
| 140 |
| 141 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); |
| 142 }; |
| 143 |
| 144 |
| 111 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) | 145 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) |
| 112 : heap_(heap), | 146 : heap_(heap), |
| 113 object_alignment_(object_alignment), | 147 object_alignment_(object_alignment), |
| 114 count_(0), | 148 count_(0), |
| 115 scavenging_(false) { | 149 scavenging_(false) { |
| 116 // Allocate the virtual memory for this scavenge heap. | 150 // Allocate the virtual memory for this scavenge heap. |
| 117 space_ = VirtualMemory::Reserve(max_capacity); | 151 space_ = VirtualMemory::Reserve(max_capacity); |
| 118 ASSERT(space_ != NULL); | 152 ASSERT(space_ != NULL); |
| 119 | 153 |
| 120 // Allocate the entire space at the beginning. | 154 // Allocate the entire space at the beginning. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 194 |
| 161 | 195 |
| 162 void Scavenger::Epilogue() { | 196 void Scavenger::Epilogue() { |
| 163 #if defined(DEBUG) | 197 #if defined(DEBUG) |
| 164 memset(from_->pointer(), 0xf3, from_->size()); | 198 memset(from_->pointer(), 0xf3, from_->size()); |
| 165 #endif // defined(DEBUG) | 199 #endif // defined(DEBUG) |
| 166 } | 200 } |
| 167 | 201 |
| 168 | 202 |
| 169 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { | 203 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { |
| 170 isolate->VisitObjectPointers(visitor, | 204 isolate->VisitStrongObjectPointers(visitor, |
| 171 StackFrameIterator::kDontValidateFrames); | 205 StackFrameIterator::kDontValidateFrames); |
| 172 heap_->IterateOldPointers(visitor); | 206 heap_->IterateOldPointers(visitor); |
| 173 } | 207 } |
| 174 | 208 |
| 175 | 209 |
| 210 void Scavenger::IterateWeakRoots(Isolate* isolate, |
| 211 ObjectPointerVisitor* visitor) { |
| 212 isolate->VisitWeakObjectPointers(visitor); |
| 213 } |
| 214 |
| 215 |
| 176 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 216 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { |
| 177 uword resolved_top = FirstObjectStart(); | 217 uword resolved_top = FirstObjectStart(); |
| 178 // Iterate until all work has been drained. | 218 // Iterate until all work has been drained. |
| 179 while (resolved_top < top_) { | 219 while (resolved_top < top_) { |
| 180 RawObject* raw_obj = RawObject::FromAddr(resolved_top); | 220 RawObject* raw_obj = RawObject::FromAddr(resolved_top); |
| 181 resolved_top += raw_obj->VisitPointers(visitor); | 221 resolved_top += raw_obj->VisitPointers(visitor); |
| 182 } | 222 } |
| 183 } | 223 } |
| 184 | 224 |
| 185 | 225 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 199 Isolate* isolate = Isolate::Current(); | 239 Isolate* isolate = Isolate::Current(); |
| 200 NoHandleScope no_handles(isolate); | 240 NoHandleScope no_handles(isolate); |
| 201 | 241 |
| 202 Timer timer(FLAG_verbose_gc, "Scavenge"); | 242 Timer timer(FLAG_verbose_gc, "Scavenge"); |
| 203 timer.Start(); | 243 timer.Start(); |
| 204 // Setup the visitor and run a scavenge. | 244 // Setup the visitor and run a scavenge. |
| 205 ScavengerVisitor visitor(this); | 245 ScavengerVisitor visitor(this); |
| 206 Prologue(); | 246 Prologue(); |
| 207 IterateRoots(isolate, &visitor); | 247 IterateRoots(isolate, &visitor); |
| 208 ProcessToSpace(&visitor); | 248 ProcessToSpace(&visitor); |
| 249 ScavengerWeakVisitor weak_visitor(this); |
| 250 IterateWeakRoots(isolate, &weak_visitor); |
| 209 Epilogue(); | 251 Epilogue(); |
| 210 timer.Stop(); | 252 timer.Stop(); |
| 211 if (FLAG_verbose_gc) { | 253 if (FLAG_verbose_gc) { |
| 212 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 254 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
| 213 } | 255 } |
| 214 | 256 |
| 215 count_++; | 257 count_++; |
| 216 // Done scavenging. Reset the marker. | 258 // Done scavenging. Reset the marker. |
| 217 ASSERT(scavenging_); | 259 ASSERT(scavenging_); |
| 218 scavenging_ = false; | 260 scavenging_ = false; |
| 219 } | 261 } |
| 220 | 262 |
| 221 } // namespace dart | 263 } // namespace dart |
| OLD | NEW |